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);
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO * pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER * ppShader, LPD3DXBUFFER * ppErrorMsgs, LPD3DXCONSTANTTABLE * ppConstantTable) { // wondering what I'm doing here? // see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader() #if ( D3DX_SDK_VERSION < 24 ) // directly link functions, old d3d sdks didn't try to load external dlls // when linking to the d3dx9.lib #ifdef _MSC_VER #pragma comment (lib, "d3dx9.lib") #endif // invoke static linked function return D3DXCompileShaderFromFileA(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable); #else { // try to load shader functions from the dll and print error if failed. // D3DXCompileShaderFromFileA typedef HRESULT(WINAPI * D3DXCompileShaderFromFileFunction)(LPCSTR pSrcFile, CONST D3DXMACRO * pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER * ppShader, LPD3DXBUFFER * ppErrorMsgs, LPD3DXCONSTANTTABLE * ppConstantTable); static bool LoadFailed = false; static D3DXCompileShaderFromFileFunction pFn = 0; if (!pFn && !LoadFailed) { // try to load dll io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; HMODULE hMod = LoadLibrary(strDllName.c_str()); if (hMod) { pFn = (D3DXCompileShaderFromFileFunction)GetProcAddress(hMod, "D3DXCompileShaderFromFileA"); } if (!pFn) { LoadFailed = true; os::Printer::log("Could not load shader function D3DXCompileShaderFromFileA from dll, shaders disabled", strDllName.c_str(), ELL_ERROR); } } if (pFn) { // call already loaded function return (*pFn)(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable); } } #endif // D3DX_SDK_VERSION < 24 return 0; }
HRESULT MyCreateEffectFromFile(TCHAR *fName, DWORD dwShaderFlags, ID3D11Device *pDevice, ID3DX11Effect **pEffect) { char fNameChar[1024]; CharToOem(fName, fNameChar); ID3DXBuffer *pShader; HRESULT hr; ID3DXBuffer *pErrors; if (FAILED(D3DXCompileShaderFromFileA(fNameChar, NULL, NULL, NULL, "fx_5_0", 0, &pShader, &pErrors, NULL))) { MessageBoxA(NULL, (char *)pErrors->GetBufferPointer(), "Error", MB_OK); return E_FAIL; } V_RETURN(D3DX11CreateEffectFromMemory(pShader->GetBufferPointer(), pShader->GetBufferSize(), dwShaderFlags, pDevice, pEffect)); SAFE_RELEASE(pErrors); SAFE_RELEASE(pShader); return S_OK; }
bool PrepareShader() { ID3DXBuffer *shader ; ID3DXBuffer *errorBuffer ; // Compile shader from file, Shader.txt must exist in current directory, and it must contain // the "Main" function HRESULT hr = D3DXCompileShaderFromFileA("torus.fx", 0, 0, "Main", "ps_2_0", D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, &shader, &errorBuffer, NULL) ; // output any error messages if( errorBuffer ) { MessageBoxA(0, (char*)errorBuffer->GetBufferPointer(), 0, 0); errorBuffer->Release() ; } if(FAILED(hr)) { MessageBox(0, L"D3DXCompileShaderFromFile() - FAILED", 0, 0); return false; } // Create pixel shader hr = g_pd3dDevice->CreatePixelShader((DWORD*)shader->GetBufferPointer(), &g_pPixelShader) ; // handling error if(FAILED(hr)) { MessageBox(0, L"CreatePixelShader - FAILED", 0, 0); return false; } // Release DX buffer shader->Release() ; return true ; }
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; }