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; }
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; }
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(); } }