void ShaderImpl_DirectX9::setupConstantData(UniformType type, LPD3DXCONSTANTTABLE ct) { for(uint32 ctidx=0;;ctidx++) { if(D3DXHANDLE constant = ct->GetConstant(NULL, ctidx)) { ConstantData &data = mConstants.Add(); D3DXCONSTANT_DESC constDesc; UINT constCount; ct->GetConstantDesc(constant, &constDesc, &constCount); data.name = constDesc.Name; data.shaderType = type; data.paramType = constDesc.Type; if( data.paramType == D3DXPT_TEXTURE || data.paramType == D3DXPT_TEXTURE1D || data.paramType == D3DXPT_TEXTURE2D || data.paramType == D3DXPT_TEXTURE3D || data.paramType == D3DXPT_TEXTURECUBE || data.paramType == D3DXPT_SAMPLER || data.paramType == D3DXPT_SAMPLER1D || data.paramType == D3DXPT_SAMPLER2D || data.paramType == D3DXPT_SAMPLER3D || data.paramType == D3DXPT_SAMPLERCUBE ) { data.location = ct->GetSamplerIndex(constant); } data.handle = constant; } else break; } }
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, s32 index, const s32* ints, int count) { LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable; if (index < 0 || !tbl) return false; // currently we only support top level parameters. // Should be enough for the beginning. (TODO) D3DXHANDLE hndl = tbl->GetConstant(NULL, index); if (!hndl) return false; D3DXCONSTANT_DESC Description; UINT ucount = 1; tbl->GetConstantDesc(hndl, &Description, &ucount); if(Description.RegisterSet != D3DXRS_SAMPLER) { HRESULT hr = tbl->SetIntArray(pID3DDevice, hndl, ints, count); if (FAILED(hr)) { os::Printer::log("Error setting int array for HLSL variable", ELL_WARNING); return false; } } return true; }
s32 CD3D9HLSLMaterialRenderer::getVariableID(bool vertexShader, const c8* name) { LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable; if (!tbl) return -1; D3DXCONSTANTTABLE_DESC tblDesc; if (!FAILED(tbl->GetDesc(&tblDesc))) { for (u32 i = 0; i < tblDesc.Constants; ++i) { D3DXHANDLE curConst = tbl->GetConstant(NULL, i); D3DXCONSTANT_DESC constDesc; UINT ucount = 1; if (!FAILED(tbl->GetConstantDesc(curConst, &constDesc, &ucount))) if(strcmp(name, constDesc.Name) == 0) return i; } } core::stringc s = "HLSL Variable to get ID not found: '"; s += name; s += "'. Available variables are:"; os::Printer::log(s.c_str(), ELL_WARNING); printHLSLVariables(tbl); return -1; }
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name, const f32* floats, int count) { LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable; if (!tbl) return false; // currently we only support top level parameters. // Should be enough for the beginning. (TODO) D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name); if (!hndl) { core::stringc s = "HLSL Variable to set not found: '"; s += name; s += "'. Available variables are:"; os::Printer::log(s.c_str(), ELL_WARNING); printHLSLVariables(tbl); return false; } HRESULT hr = tbl->SetFloatArray(pID3DDevice, hndl, floats, count); if (FAILED(hr)) { os::Printer::log("Error setting float array for HLSL variable", ELL_WARNING); return false; } return true; }
int compileHLSLToD3D9(const char* from, const char* to, const std::map<std::string, int>& attributes) { LPD3DXBUFFER errors; LPD3DXBUFFER shader; LPD3DXCONSTANTTABLE table; HRESULT hr = D3DXCompileShaderFromFileA(from, nullptr, nullptr, "main", isVertexShader(from) ? "vs_2_0" : "ps_2_0", 0, &shader, &errors, &table); if (FAILED(hr)) hr = D3DXCompileShaderFromFileA(from, nullptr, nullptr, "main", isVertexShader(from) ? "vs_3_0" : "ps_3_0", 0, &shader, &errors, &table); if (errors != nullptr) std::cerr << (char*)errors->GetBufferPointer(); if (!FAILED(hr)) { std::ofstream file(to, std::ios_base::binary); file.put(attributes.size()); for (std::map<std::string, int>::const_iterator attribute = attributes.begin(); attribute != attributes.end(); ++attribute) { file << attribute->first.c_str(); file.put(0); file.put(attribute->second); } D3DXCONSTANTTABLE_DESC desc; table->GetDesc(&desc); file.put(desc.Constants); for (UINT i = 0; i < desc.Constants; ++i) { D3DXHANDLE handle = table->GetConstant(nullptr, i); D3DXCONSTANT_DESC descriptions[10]; UINT count = 10; table->GetConstantDesc(handle, descriptions, &count); if (count > 1) std::cerr << "Error: Number of descriptors for one constant is greater than one." << std::endl; for (UINT i2 = 0; i2 < count; ++i2) { char regtype; switch (descriptions[i2].RegisterSet) { case D3DXRS_BOOL: regtype = 'b'; break; case D3DXRS_INT4: regtype = 'i'; break; case D3DXRS_FLOAT4: regtype = 'f'; break; case D3DXRS_SAMPLER: regtype = 's'; break; } //std::cout << descriptions[i2].Name << " " << regtype << descriptions[i2].RegisterIndex << " " << descriptions[i2].RegisterCount << std::endl; file << descriptions[i2].Name; file.put(0); file.put(regtype); file.put(descriptions[i2].RegisterIndex); file.put(descriptions[i2].RegisterCount); } } DWORD* data = (DWORD*)shader->GetBufferPointer(); for (unsigned i = 0; i < shader->GetBufferSize() / 4; ++i) { if ((data[i] & 0xffff) == 0xfffe) { //comment token unsigned size = (data[i] >> 16) & 0xffff; i += size; } else file.write((char*)&data[i], 4);
// Function for pixel shader that just needs material colour void PS_PlainColourFn( int method, CMatrix4x4* worldMatrix, CCamera* camera ) { // Ensure we have default render states SetDefaultStates(); LPD3DXCONSTANTTABLE shaderConsts = renderMethods[method].pixelConsts; shaderConsts->SetFloatArray( g_pd3dDevice, "MaterialColour", (FLOAT*)&m_DiffuseColour, 3 ); }
// Pass the world matrix and view/projection matrix to the vertex shader void VS_XFormFn( int method, CMatrix4x4* worldMatrix, CCamera* camera ) { LPD3DXCONSTANTTABLE shaderConsts = renderMethods[method].vertexConsts; D3DXMATRIXA16 matViewProj = ToD3DXMATRIX( camera->GetViewProjMatrix() ); shaderConsts->SetMatrix( g_pd3dDevice, "ViewProjMatrix", &matViewProj ); D3DXMATRIX* matWorld = ToD3DXMATRIXPtr( worldMatrix ); shaderConsts->SetMatrix( g_pd3dDevice, "WorldMatrix", matWorld ); }
TRESULT D3DWrapper::CompileVertexShader( OCShader*& shader ) { if( NULL == shader ) return RE_FAILED; if( NULL == shader->GetVertexShaderCode() ) return RE_FAILED; UINT codeSize = static_cast<UINT>( strlen(shader->GetVertexShaderCode()) ); if( 0 == codeSize ) return RE_FAILED; LPD3DXCONSTANTTABLE pConstantTable; LPD3DXBUFFER pCode; LPD3DXBUFFER pErrorMsgs; HRESULT hr = D3DXCompileShader( shader->GetVertexShaderCode(), codeSize, NULL, NULL, "main", "vs_3_0", 0, &pCode, &pErrorMsgs, &pConstantTable ); if(FAILED(hr))return RE_FAILED; hr = m_pD3dDevice->CreateVertexShader( (DWORD*)pCode->GetBufferPointer(), shader->GetVertexShaderPtr() ); if(FAILED(hr))return RE_FAILED; //vector<string> constantNameList; //if( pConstantTable ) //{ // D3DXCONSTANTTABLE_DESC constant_desc; // pConstantTable->GetDesc( &constant_desc ); // // Get Constant list // D3DXCONSTANT_DESC Desc; // UINT Count; // for( UINT i = 0; i<constant_desc.Constants; i++ ) // { // D3DXHANDLE handle = pConstantTable->GetConstant(NULL, i); // pConstantTable->GetConstantDesc( handle, &Desc, &Count ); // constantNameList.push_back( Desc.Name ); // } //} if(pCode) pCode->Release(); if(pErrorMsgs) pErrorMsgs->Release(); if(pConstantTable) pConstantTable->Release(); return RE_SUCCEED; }
GXINT GShaderImpl::UpdateConstTabDesc(LPD3DXCONSTANTTABLE pct, LPD3DXCONSTANTTABLE_DESC pctd, GXUINT uHandleShift) { GXINT nCacheSize = 0; GXDWORD dwTopIndex = (GXDWORD)m_aConstDesc.size() + 1; Marimo::ShaderConstName* pConstNameObj = m_pGraphicsImpl->InlGetShaderConstantNameObj(); pct->GetDesc(pctd); GXD3DXCONSTDESC cd; for(GXUINT i = 0; i < pctd->Constants; i++) { GXUINT uCount; D3DXHANDLE hConst = pct->GetConstant(NULL, i); pct->GetConstantDesc(hConst, &cd, &uCount); //// 把RegisterIndex +1,便于Pixel与Vertex的Index打包 //cd.RegisterIndex = cd.RegisterIndex; #ifdef _DEBUG if(cd.RegisterSet == D3DXRS_SAMPLER) { ASSERT(cd.Bytes == 4); } else if(cd.RegisterSet == D3DXRS_FLOAT4 || cd.RegisterSet == D3DXRS_INT4) { // Shader被优化后有可能Rows和RegisterCount不相等 //ASSERT(cd.Rows == cd.RegisterCount); ASSERT(cd.Bytes == cd.Rows * cd.Columns * sizeof(float)); } else ASSERT(0); #endif // _DEBUG // Sampler不算在常量寄存器内 // 寄存器的大小按照出现的最大寄存器索引+占用的寄存器数量决定, // 因为寄存器可能是跳跃的,不一定是连续使用的. if(cd.RegisterSet != D3DXRS_SAMPLER) { nCacheSize = clMax(nCacheSize, (GXINT)((cd.RegisterIndex + cd.RegisterCount) * sizeof(float4))); // 根据上面的断言调整,保证这个计算不会覆盖 } cd.dwNameID = clStringA(cd.Name).GetHash(); cd.dwHandle = (i + dwTopIndex) << uHandleShift; cd.nCanvasUniform = pConstNameObj->AddName(this, cd.Name, cd.Bytes); m_aConstDesc.push_back(cd); } return nCacheSize; }
HRESULT APIENTRY D3DProxyDeviceAdv::SetVertexShader(IDirect3DVertexShader9* pvShader) { IDirect3DVertexShader9* pShader = NULL; LPD3DXCONSTANTTABLE pConstantTable = NULL; BYTE *pData = NULL; HRESULT hr = m_pDevice->SetVertexShader(pvShader); m_pDevice->GetVertexShader(&pShader); UINT pSizeOfData; if(NULL == pShader) goto grexit; pShader->GetFunction(NULL,&pSizeOfData); findWeirdMirrorsEdgeShader(pSizeOfData); pData = new BYTE[pSizeOfData]; pShader->GetFunction(pData,&pSizeOfData); bool shaderSeen = hasSeenShader(pSizeOfData); D3DXCONSTANT_DESC pConstantDesc[32]; UINT pConstantNum = 32; D3DXGetShaderConstantTable(reinterpret_cast<DWORD*>(pData),&pConstantTable); if(pConstantTable == NULL) goto grexit; D3DXCONSTANTTABLE_DESC pDesc; pConstantTable->GetDesc(&pDesc); for(UINT i = 0; i < pDesc.Constants; i++) { D3DXHANDLE Handle = pConstantTable->GetConstant(NULL,i); if(Handle == NULL) continue; pConstantTable->GetConstantDesc(Handle,pConstantDesc,&pConstantNum); for(UINT j = 0; j < pConstantNum; j++) { removeExistingMatrices(pConstantDesc[j]); parse4by4Matrices(pConstantDesc[j]); parseIndividualFloats(pConstantDesc[j]); } } grexit: _SAFE_RELEASE(pConstantTable); _SAFE_RELEASE(pShader); if(pData) delete[] pData; return hr; }
//----------------------------------------------------------------------- void CEnvironmentMap::modelShaderApply(OwnMatrix4x4 *pModelMtx /*= NULL*/, bool bRenderEnvMappedMesh) { LPD3DXCONSTANTTABLE constable = mVtxConstTable; OwnMatrix4x4 modelMtx, viewProjMtx, modelViewProjMtx; if (NULL == pModelMtx) modelMtx.setIdentity(); else modelMtx = *pModelMtx; viewProjMtx.setMultiply(mCamera->mViewTrans, mCamera->mProjectionTrans); modelViewProjMtx.setMultiply(modelMtx, viewProjMtx); HRESULT hr; D3DXHANDLE handle; D3DXHANDLE modelViewProj = mVtxConstTable->GetConstantByName(0, "u_ModelViewProjMatrix"); hr = mVtxConstTable->SetMatrix(mD3DDevice, modelViewProj, (D3DXMATRIX*)&modelViewProjMtx); D3DXHANDLE u_ModelMatrix = constable->GetConstantByName(0, "u_ModelToWorld"); hr = constable->SetMatrix(mD3DDevice, u_ModelMatrix, (D3DXMATRIX*)&modelMtx); LPD3DXCONSTANTTABLE pixConstable = mPxlConstTable; float value = bRenderEnvMappedMesh ? 0.5f : 0; D3DXHANDLE reflectivity = pixConstable->GetConstantByName(0, "$reflectivity"); hr = pixConstable->SetFloat(mD3DDevice, reflectivity, value); }
// draw draws the set of graphics primitives using the object's world // transformation and reflected colour // void Graphic::draw(const iObject* object, int i) { // if graphic is not setup, set it up if (!isSetup) setup(object); if (isSetup) { #if PIPELINE == FIXED_FUNCTION #elif PIPELINE == PROGRAMMABLE || PIPELINE == PROGRAMMABLE_EFFECT Display* disp = reinterpret_cast<Display*>(display); Matrix worldView = object->world() * disp->viewMatrix(); Matrix worldViewProjection = worldView * disp->projectionMatrix(); #endif #if PIPELINE == FIXED_FUNCTION d3dd->SetTransform(D3DTS_WORLD, (D3DXMATRIX*)(&object->world())); d3dd->SetMaterial(&mat); if (!strcmp(technique, "opaque") || !strcmp(technique, "skybox")) d3dd->SetRenderState(D3DRS_ALPHABLENDENABLE, false); else if (!strcmp(technique, "translucent")) d3dd->SetRenderState(D3DRS_ALPHABLENDENABLE, true); vertexList->draw(i); #elif PIPELINE == PROGRAMMABLE LPD3DXCONSTANTTABLE vertexTable = (LPD3DXCONSTANTTABLE)uniformVS; LPD3DXCONSTANTTABLE fragmentTable = (LPD3DXCONSTANTTABLE)uniformFS; vertexTable->SetMatrix(d3dd, "world", (D3DXMATRIX*)&object->world()); fragmentTable->SetFloatArray(d3dd, "material.ambient", (FLOAT*)&ambient, 4); fragmentTable->SetFloatArray(d3dd, "material.diffuse", (FLOAT*)&diffuse, 4); fragmentTable->SetFloatArray(d3dd, "material.specular", (FLOAT*)&specular, 4); fragmentTable->SetFloat(d3dd, "material.power", (FLOAT)power); if (!strcmp(technique, "opaque") || !strcmp(technique, "skybox")) d3dd->SetRenderState(D3DRS_ALPHABLENDENABLE, false); else if (!strcmp(technique, "translucent")) d3dd->SetRenderState(D3DRS_ALPHABLENDENABLE, true); #elif PIPELINE == PROGRAMMABLE_EFFECT effect->SetInt(stagesHandle, nStages); effect->SetMatrix(worldHandle, (D3DXMATRIX*)&object->world()); effect->SetVector(ambientHandle, (D3DXVECTOR4*)&ambient); effect->SetVector(diffuseHandle, (D3DXVECTOR4*)&diffuse); effect->SetVector(specularHandle, (D3DXVECTOR4*)&specular); effect->SetFloat(powerHandle, power); effect->SetFloat(roughnessHandle, object->getRoughness()); effect->SetFloat(refractionHandle,object->getIndexOfRefraction()); effect->SetInt(algorithmHandle, object->getAlgorithm()); effect->SetMatrix(worldViewHandle, (D3DXMATRIX*)&worldView); effect->SetMatrix(clipMatrixHandle, (D3DXMATRIX*)&worldViewProjection); effect->CommitChanges(); Matrix viewProjectionBak; effect->GetMatrix("viewProjection", (D3DXMATRIX*)&viewProjectionBak); effect->SetTechnique(techniqueHandle); unsigned nPasses; effect->Begin(&nPasses, 0); for (unsigned iPass = 0; iPass < nPasses; iPass++) { effect->BeginPass(iPass); vertexList->draw(i); effect->EndPass(); } effect->End(); #endif } }
//----------------------------------------------------------------------- void CEnvironmentMap::lightShaderConfig() { HRESULT hr; D3DXHANDLE handle; Material material; material.Ke = D3DXVECTOR3(0, 0, 0); material.Ka = D3DXVECTOR3(0, 0, 0); material.Kd = D3DXVECTOR3(1, 1, 1); material.Ks = D3DXVECTOR3(1, 1, 1); material.shininess = 5; Light light; light.position = D3DXVECTOR3(-10, 0, -10); light.color = D3DXVECTOR3(0, 1, 0); LPD3DXCONSTANTTABLE constable = mVtxConstTable; D3DXHANDLE u_Material = constable->GetConstantByName(0, "u_Material"); hr = constable->SetValue(mD3DDevice, u_Material, &material, sizeof(material)); D3DXHANDLE u_Light = constable->GetConstantByName(0, "u_Light"); hr = constable->SetValue(mD3DDevice, u_Light, &light, sizeof(light)); }
int compileHLSLToD3D9(const char* from, const char* to, const std::map<std::string, int>& attributes, EShLanguage stage) { #ifdef SYS_WINDOWS HMODULE lib = LoadLibraryA("d3dx9_43.dll"); if (lib != nullptr) CompileShaderFromFileA = (D3DXCompileShaderFromFileAType)GetProcAddress(lib, "D3DXCompileShaderFromFileA"); if (CompileShaderFromFileA == nullptr) { std::cerr << "d3dx9_43.dll could not be loaded, please install dxwebsetup." << std::endl; return 1; } LPD3DXBUFFER errors; LPD3DXBUFFER shader; LPD3DXCONSTANTTABLE table; HRESULT hr = CompileShaderFromFileA(from, nullptr, nullptr, "main", stage == EShLangVertex ? "vs_2_0" : "ps_2_0", 0, &shader, &errors, &table); if (FAILED(hr)) hr = CompileShaderFromFileA(from, nullptr, nullptr, "main", stage == EShLangVertex ? "vs_3_0" : "ps_3_0", 0, &shader, &errors, &table); if (errors != nullptr) std::cerr << (char*)errors->GetBufferPointer(); if (!FAILED(hr)) { std::ofstream file(to, std::ios_base::binary); file.put((char)attributes.size()); for (std::map<std::string, int>::const_iterator attribute = attributes.begin(); attribute != attributes.end(); ++attribute) { file << attribute->first.c_str(); file.put(0); file.put(attribute->second); } D3DXCONSTANTTABLE_DESC desc; table->GetDesc(&desc); file.put(desc.Constants); for (UINT i = 0; i < desc.Constants; ++i) { D3DXHANDLE handle = table->GetConstant(nullptr, i); D3DXCONSTANT_DESC descriptions[10]; UINT count = 10; table->GetConstantDesc(handle, descriptions, &count); if (count > 1) std::cerr << "Error: Number of descriptors for one constant is greater than one." << std::endl; for (UINT i2 = 0; i2 < count; ++i2) { char regtype; switch (descriptions[i2].RegisterSet) { case D3DXRS_BOOL: regtype = 'b'; break; case D3DXRS_INT4: regtype = 'i'; break; case D3DXRS_FLOAT4: regtype = 'f'; break; case D3DXRS_SAMPLER: regtype = 's'; break; } //std::cout << descriptions[i2].Name << " " << regtype << descriptions[i2].RegisterIndex << " " << descriptions[i2].RegisterCount << std::endl; if (strcmp(descriptions[i2].Name, "dx_ViewAdjust") != 0) file << "_"; // TODO: Remove when kfx is deprecated file << descriptions[i2].Name; file.put(0); file.put(regtype); file.put(descriptions[i2].RegisterIndex); file.put(descriptions[i2].RegisterCount); } } DWORD* data = (DWORD*)shader->GetBufferPointer(); for (unsigned i = 0; i < shader->GetBufferSize() / 4; ++i) { if ((data[i] & 0xffff) == 0xfffe) { //comment token unsigned size = (data[i] >> 16) & 0xffff; i += size; } else file.write((char*)&data[i], 4);
void main(int argc, char* argv[]) { int i, n; HRESULT hr; LPD3DXBUFFER pCode; LPD3DXBUFFER pErr; LPD3DXCONSTANTTABLE pTbl; char* src_name = "test.hlsl"; char* cod_name = "test.cod"; char* prm_name = "test.prm"; char* profile = "ps_3_0"; if (argc > 1) { src_name = argv[1]; } if (argc > 2) { cod_name = argv[2]; } if (argc > 3) { prm_name = argv[3]; } if (argc > 4) { profile = argv[4]; } hr = D3DXCompileShaderFromFile(src_name, NULL, NULL, "main", profile, D3DXSHADER_PREFER_FLOW_CONTROL, &pCode, &pErr, &pTbl); if (D3D_OK == hr) { D3DXCONSTANTTABLE_DESC desc; pTbl->GetDesc(&desc); n = desc.Constants; SymTbl* pSym = new SymTbl(2*1024*1024); s_tbl.nb_param = 0; printf("# const = %d\n", n); PARAM_INFO* pInfo = s_tbl.info; for (i = 0; i < n; ++i) { UINT count = 1; D3DXCONSTANT_DESC info[1]; D3DXHANDLE hConst = pTbl->GetConstant(NULL, i); pTbl->GetConstantDesc(hConst, info, &count); printf("%s, reg = %d, len = %d\n", info[0].Name, info[0].RegisterIndex, info[0].RegisterCount); int sym_id = pSym->Add((char*)info[0].Name); pInfo->name = sym_id; pInfo->reg = info[0].RegisterIndex; pInfo->len = info[0].RegisterCount; switch (info[0].Type) { case D3DXPT_FLOAT: if (info[0].Class == D3DXPC_SCALAR) { pInfo->type = E_PARAMTYPE_FLOAT; } else { pInfo->type = E_PARAMTYPE_FVEC; } break; case D3DXPT_INT: if (info[0].Class == D3DXPC_SCALAR) { pInfo->type = E_PARAMTYPE_INT; } else { pInfo->type = E_PARAMTYPE_IVEC; } break; case D3DXPT_BOOL: pInfo->type = E_PARAMTYPE_BOOL; break; case D3DXPT_SAMPLER: case D3DXPT_SAMPLER1D: case D3DXPT_SAMPLER2D: case D3DXPT_SAMPLER3D: case D3DXPT_SAMPLERCUBE: pInfo->type = E_PARAMTYPE_SMP; break; } ++pInfo; ++s_tbl.nb_param; } int tbl_size = sizeof(int) + s_tbl.nb_param*sizeof(PARAM_INFO); int prm_size = tbl_size + pSym->Length(); char* pPrm = new char[prm_size]; memcpy(pPrm, &s_tbl, tbl_size); memcpy(pPrm + tbl_size, pSym->Top(), pSym->Length()); Bin_write(cod_name, pCode->GetBufferPointer(), pCode->GetBufferSize()); Bin_write(prm_name, pPrm, prm_size); delete pSym; if (pTbl) { pTbl->Release(); } } else { if (pErr) { char* pErr_msg = (char*)pErr->GetBufferPointer(); printf("%s", pErr_msg); } } if (pErr) { pErr->Release(); } }
// Pass data to pixel shaders that perform pixel lighting (2 point lights) void PS_PixelLit2Fn( int method, CMatrix4x4* worldMatrix, CCamera* camera ) { // Ensure we have default render states SetDefaultStates(); LPD3DXCONSTANTTABLE shaderConsts = renderMethods[method].pixelConsts; D3DXVECTOR3 cameraPos = ToD3DXVECTOR( camera->Position() ); shaderConsts->SetFloatArray( g_pd3dDevice, "CameraPosition", (FLOAT*)&cameraPos, 3 ); shaderConsts->SetFloatArray( g_pd3dDevice, "AmbientLight", (FLOAT*)&m_AmbientLight, 3 ); shaderConsts->SetFloatArray( g_pd3dDevice, "Light1Position", (FLOAT*)&m_Lights[0]->GetPosition(), 3 ); shaderConsts->SetFloatArray( g_pd3dDevice, "Light1Colour", (FLOAT*)&m_Lights[0]->GetColour(), 3 ); shaderConsts->SetFloat( g_pd3dDevice, "Light1Brightness", m_Lights[0]->GetBrightness() ); shaderConsts->SetFloatArray( g_pd3dDevice, "Light2Position", (FLOAT*)&m_Lights[1]->GetPosition(), 3 ); shaderConsts->SetFloatArray( g_pd3dDevice, "Light2Colour", (FLOAT*)&m_Lights[1]->GetColour(), 3 ); shaderConsts->SetFloat( g_pd3dDevice, "Light2Brightness", m_Lights[1]->GetBrightness() ); shaderConsts->SetFloatArray( g_pd3dDevice, "MaterialColour", (FLOAT*)&m_DiffuseColour, 3 ); // If needed shaderConsts->SetFloatArray( g_pd3dDevice, "SpecularStrength", (FLOAT*)&m_SpecularColour, 3 ); // If needed shaderConsts->SetFloat( g_pd3dDevice, "SpecularPower", m_SpecularPower ); }
// Pass data to vertex shaders that perform vertex lighting (1 point light) // Passes full range of data - some shaders don't need all of it. This // reduces the number of these functions at the expense of redundancy void VS_VertLit1Fn( int method, CMatrix4x4* worldMatrix, CCamera* camera ) { LPD3DXCONSTANTTABLE shaderConsts = renderMethods[method].vertexConsts; D3DXMATRIXA16 matViewProj = ToD3DXMATRIX( camera->GetViewProjMatrix() ); shaderConsts->SetMatrix( g_pd3dDevice, "ViewProjMatrix", &matViewProj ); D3DXMATRIX* matWorld = ToD3DXMATRIXPtr( worldMatrix ); shaderConsts->SetMatrix( g_pd3dDevice, "WorldMatrix", matWorld ); D3DXVECTOR3 cameraPos = ToD3DXVECTOR( camera->Position() ); shaderConsts->SetFloatArray( g_pd3dDevice, "CameraPosition", (FLOAT*)&cameraPos, 3 ); // If needed shaderConsts->SetFloatArray( g_pd3dDevice, "AmbientLight", (FLOAT*)&m_AmbientLight, 3 ); shaderConsts->SetFloatArray( g_pd3dDevice, "LightPosition", (FLOAT*)&m_Lights[0]->GetPosition(), 3 ); shaderConsts->SetFloatArray( g_pd3dDevice, "LightColour", (FLOAT*)&m_Lights[0]->GetColour(), 3 ); shaderConsts->SetFloat( g_pd3dDevice, "LightBrightness", m_Lights[0]->GetBrightness() ); shaderConsts->SetFloatArray( g_pd3dDevice, "MaterialColour", (FLOAT*)&m_DiffuseColour, 3 ); // If needed shaderConsts->SetFloatArray( g_pd3dDevice, "SpecularStrength", (FLOAT*)&m_SpecularColour, 3 ); // If needed shaderConsts->SetFloat( g_pd3dDevice, "SpecularPower", m_SpecularPower ); // If needed }
bool compileHLSLShaderDx9(bx::CommandLine& _cmdLine, const std::string& _code, bx::WriterI* _writer) { BX_TRACE("DX9"); const char* profile = _cmdLine.findOption('p', "profile"); if (NULL == profile) { fprintf(stderr, "Shader profile must be specified.\n"); return false; } bool debug = _cmdLine.hasArg('\0', "debug"); uint32_t flags = 0; flags |= debug ? D3DXSHADER_DEBUG : 0; flags |= _cmdLine.hasArg('\0', "avoid-flow-control") ? D3DXSHADER_AVOID_FLOW_CONTROL : 0; flags |= _cmdLine.hasArg('\0', "no-preshader") ? D3DXSHADER_NO_PRESHADER : 0; flags |= _cmdLine.hasArg('\0', "partial-precision") ? D3DXSHADER_PARTIALPRECISION : 0; flags |= _cmdLine.hasArg('\0', "prefer-flow-control") ? D3DXSHADER_PREFER_FLOW_CONTROL : 0; flags |= _cmdLine.hasArg('\0', "backwards-compatibility") ? D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY : 0; bool werror = _cmdLine.hasArg('\0', "Werror"); uint32_t optimization = 3; if (_cmdLine.hasArg(optimization, 'O') ) { optimization = bx::uint32_min(optimization, BX_COUNTOF(s_optimizationLevelDx9)-1); flags |= s_optimizationLevelDx9[optimization]; } else { flags |= D3DXSHADER_SKIPOPTIMIZATION; } BX_TRACE("Profile: %s", profile); BX_TRACE("Flags: 0x%08x", flags); LPD3DXBUFFER code; LPD3DXBUFFER errorMsg; LPD3DXCONSTANTTABLE constantTable; HRESULT hr; // Output preprocessed shader so that HLSL can be debugged via GPA // or PIX. Compiling through memory won't embed preprocessed shader // file path. if (debug) { std::string hlslfp = _cmdLine.findOption('o'); hlslfp += ".hlsl"; writeFile(hlslfp.c_str(), _code.c_str(), (int32_t)_code.size() ); hr = D3DXCompileShaderFromFileA(hlslfp.c_str() , NULL , NULL , "main" , profile , flags , &code , &errorMsg , &constantTable ); } else { hr = D3DXCompileShader(_code.c_str() , (uint32_t)_code.size() , NULL , NULL , "main" , profile , flags , &code , &errorMsg , &constantTable ); } if (FAILED(hr) || (werror && NULL != errorMsg) ) { const char* log = (const char*)errorMsg->GetBufferPointer(); char source[1024]; int32_t line = 0; int32_t column = 0; int32_t start = 0; int32_t end = INT32_MAX; if (3 == sscanf(log, "%[^(](%u,%u):", source, &line, &column) && 0 != line) { start = bx::uint32_imax(1, line-10); end = start + 20; } printCode(_code.c_str(), line, start, end); fprintf(stderr, "Error: 0x%08x %s\n", (uint32_t)hr, log); errorMsg->Release(); return false; } UniformArray uniforms; if (NULL != constantTable) { D3DXCONSTANTTABLE_DESC desc; hr = constantTable->GetDesc(&desc); if (FAILED(hr) ) { fprintf(stderr, "Error 0x%08x\n", (uint32_t)hr); return false; } BX_TRACE("Creator: %s 0x%08x", desc.Creator, (uint32_t /*mingw warning*/)desc.Version); BX_TRACE("Num constants: %d", desc.Constants); BX_TRACE("# cl ty RxC S By Name"); for (uint32_t ii = 0; ii < desc.Constants; ++ii) { D3DXHANDLE handle = constantTable->GetConstant(NULL, ii); D3DXCONSTANT_DESC constDesc; uint32_t count; constantTable->GetConstantDesc(handle, &constDesc, &count); BX_TRACE("%3d %2d %2d [%dx%d] %d %3d %s[%d] c%d (%d)" , ii , constDesc.Class , constDesc.Type , constDesc.Rows , constDesc.Columns , constDesc.StructMembers , constDesc.Bytes , constDesc.Name , constDesc.Elements , constDesc.RegisterIndex , constDesc.RegisterCount ); UniformType::Enum type = findUniformTypeDx9(constDesc); if (UniformType::Count != type) { Uniform un; un.name = '$' == constDesc.Name[0] ? constDesc.Name+1 : constDesc.Name; un.type = type; un.num = constDesc.Elements; un.regIndex = constDesc.RegisterIndex; un.regCount = constDesc.RegisterCount; uniforms.push_back(un); } } } uint16_t count = (uint16_t)uniforms.size(); bx::write(_writer, count); uint32_t fragmentBit = profile[0] == 'p' ? BGFX_UNIFORM_FRAGMENTBIT : 0; for (UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it) { const Uniform& un = *it; uint8_t nameSize = (uint8_t)un.name.size(); bx::write(_writer, nameSize); bx::write(_writer, un.name.c_str(), nameSize); uint8_t type = un.type|fragmentBit; bx::write(_writer, type); bx::write(_writer, un.num); bx::write(_writer, un.regIndex); bx::write(_writer, un.regCount); BX_TRACE("%s, %s, %d, %d, %d" , un.name.c_str() , getUniformTypeName(un.type) , un.num , un.regIndex , un.regCount ); } uint16_t shaderSize = (uint16_t)code->GetBufferSize(); bx::write(_writer, shaderSize); bx::write(_writer, code->GetBufferPointer(), shaderSize); uint8_t nul = 0; bx::write(_writer, nul); if (_cmdLine.hasArg('\0', "disasm") ) { LPD3DXBUFFER disasm; D3DXDisassembleShader( (const DWORD*)code->GetBufferPointer() , false , NULL , &disasm ); if (NULL != disasm) { std::string disasmfp = _cmdLine.findOption('o'); disasmfp += ".disasm"; writeFile(disasmfp.c_str(), disasm->GetBufferPointer(), disasm->GetBufferSize() ); disasm->Release(); } } if (NULL != code) { code->Release(); } if (NULL != errorMsg) { errorMsg->Release(); } if (NULL != constantTable) { constantTable->Release(); } return true; }
/** * Returns a collection of modified constants for the specified shader. * (may be an empty collection if no modifications apply) * <StrartRegister, StereoShaderConstant<float>> * * Hash the shader and load modification rules: * If rules for this specific shader use those else use default rules. * * For each shader constant: * Check if constant matches a rule (name and/or index). If it does create a stereoshaderconstant * based on rule and add to map of stereoshaderconstants to return. * * @param pActualVertexShader The actual (not wrapped) vertex shader. * @return Collection of stereoshaderconstants for this shader (empty collection if no modifications). ***/ std::map<UINT, StereoShaderConstant<float>> ShaderModificationRepository::GetModifiedConstantsF(IDirect3DVertexShader9* pActualVertexShader) { // All rules are assumed to be valid. Validation of rules should be done when rules are loaded/created std::vector<ConstantModificationRule*> rulesToApply; std::map<UINT, StereoShaderConstant<float>> result; // Hash the shader and load modification rules BYTE *pData = NULL; UINT pSizeOfData; pActualVertexShader->GetFunction(NULL, &pSizeOfData); pData = new BYTE[pSizeOfData]; pActualVertexShader->GetFunction(pData,&pSizeOfData); uint32_t hash; MurmurHash3_x86_32(pData, pSizeOfData, VIREIO_SEED, &hash); if (m_shaderSpecificModificationRuleIDs.count(hash) == 1) { // There are specific modification rules to use with this shader auto itRules = m_shaderSpecificModificationRuleIDs[hash].begin(); while (itRules != m_shaderSpecificModificationRuleIDs[hash].end()) { rulesToApply.push_back(&(m_AllModificationRules[*itRules])); ++itRules; } } else { // No specific rules, use general rules auto itRules = m_defaultModificationRuleIDs.begin(); while (itRules != m_defaultModificationRuleIDs.end()) { rulesToApply.push_back(&(m_AllModificationRules[*itRules])); ++itRules; } } // Load the constant descriptions for this shader and create StereoShaderConstants as the applicable rules require them. LPD3DXCONSTANTTABLE pConstantTable = NULL; D3DXGetShaderConstantTable(reinterpret_cast<DWORD*>(pData), &pConstantTable); if(pConstantTable) { D3DXCONSTANTTABLE_DESC pDesc; pConstantTable->GetDesc(&pDesc); D3DXCONSTANT_DESC pConstantDesc[64]; for(UINT i = 0; i < pDesc.Constants; i++) { D3DXHANDLE handle = pConstantTable->GetConstant(NULL,i); if(handle == NULL) continue; UINT pConstantNum = 64; pConstantTable->GetConstantDesc(handle, pConstantDesc, &pConstantNum); if (pConstantNum >= 64) { OutputDebugString("ShaderModificationRepository::GetModifiedConstantsF - Need larger constant description buffer"); } for(UINT j = 0; j < pConstantNum; j++) { // We are only modifying selected float vectors/matricies. if (pConstantDesc[j].RegisterSet != D3DXRS_FLOAT4) continue; if ( ((pConstantDesc[j].Class == D3DXPC_VECTOR) && (pConstantDesc[j].RegisterCount == 1)) || (((pConstantDesc[j].Class == D3DXPC_MATRIX_ROWS) || (pConstantDesc[j].Class == D3DXPC_MATRIX_COLUMNS)) && (pConstantDesc[j].RegisterCount == 4)) ) { // Check if any rules match this constant auto itRules = rulesToApply.begin(); while (itRules != rulesToApply.end()) { // Type match if ((*itRules)->m_constantType == pConstantDesc[j].Class) { // name match required if ((*itRules)->m_constantName.size() > 0) { bool nameMatch = false; if ((*itRules)->m_allowPartialNameMatch) { nameMatch = std::strstr(pConstantDesc[j].Name, (*itRules)->m_constantName.c_str()) != NULL; /*if (nameMatch) { OutputDebugString("Match\n"); } else { OutputDebugString("No Match\n"); }*/ } else { nameMatch = (*itRules)->m_constantName.compare(pConstantDesc[j].Name) == 0; //OutputDebugString("Full name match only\n"); } if (!nameMatch) { // no match ++itRules; continue; } } // register match required if ((*itRules)->m_startRegIndex != UINT_MAX) { if ((*itRules)->m_startRegIndex != pConstantDesc[j].RegisterIndex) { // no match ++itRules; continue; } } #ifdef _DEBUG // output shader constant + index switch(pConstantDesc[j].Class) { case D3DXPC_VECTOR: OutputDebugString("D3DXPC_VECTOR"); break; case D3DXPC_MATRIX_ROWS: OutputDebugString("D3DXPC_MATRIX_ROWS"); break; case D3DXPC_MATRIX_COLUMNS: OutputDebugString("D3DXPC_MATRIX_COLUMNS"); break; } char buf[32]; sprintf_s(buf,"Register Index: %d", pConstantDesc[j].RegisterIndex); OutputDebugString(buf); #endif // Create StereoShaderConstant<float> and add to result result.insert(std::pair<UINT, StereoShaderConstant<>>(pConstantDesc[j].RegisterIndex, CreateStereoConstantFrom(*itRules, pConstantDesc[j].RegisterIndex, pConstantDesc[j].RegisterCount))); // only the first matching rule is applied to a constant break; } ++itRules; } } } } } _SAFE_RELEASE(pConstantTable); if (pData) delete[] pData; return result; }
void Renderer::SetConstantTableVector( LPD3DXCONSTANTTABLE pConstantTable, char* pConstantName, D3DXVECTOR4* pVector) { pConstantTable->SetVector( m_pD3DDevice, pConstantName, pVector ); }
void Renderer::SetConstantTableMatrix( LPD3DXCONSTANTTABLE pConstantTable, char* pConstantName, D3DXMATRIX* pMatrix ) { pConstantTable->SetMatrix( m_pD3DDevice, pConstantName, pMatrix ); }
void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table) { // currently we only support top level parameters. // Should be enough for the beginning. (TODO) // print out constant names D3DXCONSTANTTABLE_DESC tblDesc; HRESULT hr = table->GetDesc(&tblDesc); if (!FAILED(hr)) { for (int i=0; i<(int)tblDesc.Constants; ++i) { D3DXCONSTANT_DESC d; UINT n = 1; D3DXHANDLE cHndl = table->GetConstant(NULL, i); if (!FAILED(table->GetConstantDesc(cHndl, &d, &n))) { core::stringc s = " '"; s += d.Name; s += "' Registers:[begin:"; s += (int)d.RegisterIndex; s += ", count:"; s += (int)d.RegisterCount; s += "]"; os::Printer::log(s.c_str()); } } } }