DFORCEINLINE static void getResources(ID3D10Device *d3dDevice, const String& prefix, DUNORDERED_MAP <String, size_t>& mapResource, DUNORDERED_MAP <String, size_t>& mapSampler, ID3D10Blob* pCode){ HRESULT hr; ID3D10ShaderReflection* pReflection = NULL; hr = D3D10ReflectShader((void*)pCode->GetBufferPointer(), pCode->GetBufferSize(), &pReflection); if (FAILED(hr)) { DEBUG_ASSERT_MSG(0, "Shader reflection could not be obtained. Reason: " << DXGetErrorDescription(hr)); return; } D3D10_SHADER_DESC desc; DX_ASSERT_MSG(pReflection->GetDesc(&desc)); //init size_t valueOffset = 0; //calc size for (uint i = 0; i < desc.BoundResources; ++i) { D3D10_SHADER_INPUT_BIND_DESC resourceDesc; pReflection->GetResourceBindingDesc(i, &resourceDesc); if (resourceDesc.Type == D3D10_SIT_TEXTURE){ mapResource[prefix + '.' + resourceDesc.Name] = resourceDesc.BindPoint; } else if (resourceDesc.Type == D3D10_SIT_SAMPLER){ mapSampler[resourceDesc.Name] = resourceDesc.BindPoint; } } }
DFORCEINLINE static void getContants(ID3D10Device *d3dDevice, const String& prefix, DUNORDERED_MAP <String, size_t>& mapVars, ID3D10Blob* pCode, ID3D10Buffer** pBuffer, size_t& size){ HRESULT hr; ID3D10ShaderReflection* pReflection = NULL; hr = D3D10ReflectShader((void*)pCode->GetBufferPointer(), pCode->GetBufferSize(), &pReflection); if (FAILED(hr)) { DEBUG_ASSERT_MSG(0, "Shader reflection could not be obtained. Reason: " << DXGetErrorDescription(hr)); return; } D3D10_SHADER_DESC desc; DX_ASSERT_MSG(pReflection->GetDesc(&desc)); //init ID3D10ShaderReflectionConstantBuffer* pConstantBuffer = NULL; size_t valueOffset = 0; size = 0; //calc size for (uint i = 0; i < desc.ConstantBuffers; ++i) { pConstantBuffer = pReflection->GetConstantBufferByIndex(i); uint count = 0; D3D10_SHADER_BUFFER_DESC bufferDesc; DX_ASSERT_MSG(pConstantBuffer->GetDesc(&bufferDesc)); if (bufferDesc.Type == D3D10_CT_TBUFFER) continue; count = bufferDesc.Variables; ID3D10ShaderReflectionVariable* pConstant = NULL; D3D10_SHADER_VARIABLE_DESC constantDesc; for (uint j = 0; j < count; ++j) { pConstant = pConstantBuffer->GetVariableByIndex(j); pConstant->GetDesc(&constantDesc); mapVars[prefix + '.' + constantDesc.Name] = valueOffset; valueOffset += constantDesc.Size; } } //save size buffer size = Math::multipleOfX(valueOffset, 16); // if (valueOffset) { (*pBuffer) = genBufferObject(d3dDevice, size); } }
void ShaderBase::InitUniforms(ID3D10Blob* s) { ID3D10ShaderReflection* ref = NULL; D3D10ReflectShader(s->GetBufferPointer(), s->GetBufferSize(), &ref); ID3D10ShaderReflectionConstantBuffer* buf = ref->GetConstantBufferByIndex(0); D3D10_SHADER_BUFFER_DESC bufd; if (FAILED(buf->GetDesc(&bufd))) { UniformsSize = 0; if (UniformData) { OVR_FREE(UniformData); UniformData = 0; } return; } for(unsigned i = 0; i < bufd.Variables; i++) { ID3D10ShaderReflectionVariable* var = buf->GetVariableByIndex(i); if (var) { D3D10_SHADER_VARIABLE_DESC vd; if (SUCCEEDED(var->GetDesc(&vd))) { Uniform u; u.Name = vd.Name; u.Offset = vd.StartOffset; u.Size = vd.Size; UniformInfo.PushBack(u); } } } UniformsSize = bufd.Size; UniformData = (unsigned char*)OVR_ALLOC(bufd.Size); }
bool CShaderHLSL::Create(P3D::sShaderDesc &desc) { const char *pData; ULONG fsize; IFileSystem* pFS = CRenderer::mEngine()->mFilesystem(); wchar path[P3DMAX_PATH]; wsprintf(path, P3DMAX_PATH-1, _W("shaders/%s.rshader"), desc.ShaderFile.Get()); FSFILE *fp = pFS->Load(path, (BYTE *&)pData, fsize, true); if (!fp) { CON(MSG_ERR, _W("Can't open %s.hlsl shader file from data/shaders directory!"), desc.ShaderFile.Get()); return false; } ID3D10Blob *pShaderBlob = NULL; ID3D10Blob *pErrors = NULL; UINT flags = D3D10_SHADER_DEBUG; //D3D10_SHADER_OPTIMIZATION_LEVEL3 char profile[128]; switch(desc.ShaderType) { case SHADERTYPE_VERTEX_SHADER: strcpy(profile, D3D10GetVertexShaderProfile(g_pD3ddev)); break; case SHADERTYPE_GEOMETRY_SHADER: strcpy(profile, D3D10GetGeometryShaderProfile(g_pD3ddev)); break; case SHADERTYPE_PIXEL_SHADER: strcpy(profile, D3D10GetPixelShaderProfile(g_pD3ddev)); break; default: CON(MSG_ERR, _W("Chader creation failed. No apropriate ShaderType given.")); return false; } CIncludeHandler includeHandler; D3D10_SHADER_MACRO Shader_Macros[] = { { "DX10", NULL }, { "SM4", NULL }, NULL }; if(!CheckHRResult(D3DX10CompileFromMemory( pData, fsize, NULL, Shader_Macros, &includeHandler, _W2A(desc.EntryFunction.Get()), profile, flags, 0, NULL, &pShaderBlob, &pErrors, NULL ))) { if(pErrors) CON(MSG_ERR, _W("%s"), _A2W((char*)pErrors->GetBufferPointer())); else CON(MSG_ERR, _W("Error description not given")); CON(MSG_ERR, _W("Shader %s could not be compiled"), desc.ShaderFile.Get()); SAFE_RELEASE(pErrors); return false; } pFS->UnLoad(fp, (BYTE *)pData); //save to cache fp = pFS->Open(_W("cache/shaders/hlsl"), _W("wb")); const char* cs = (const char*)pShaderBlob->GetBufferPointer(); pFS->Write(cs, 1, pShaderBlob->GetBufferSize(), fp); pFS->Close(fp); bool shaderCreated = false; switch(desc.ShaderType) { case SHADERTYPE_VERTEX_SHADER: shaderCreated = CheckHRResult(g_pD3ddev->CreateVertexShader(pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), &m_pVS)); break; case SHADERTYPE_GEOMETRY_SHADER: shaderCreated = CheckHRResult(g_pD3ddev->CreateGeometryShader(pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), &m_pGS)); break; case SHADERTYPE_PIXEL_SHADER: shaderCreated = CheckHRResult(g_pD3ddev->CreatePixelShader(pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), &m_pPS)); break; } if(!shaderCreated) { CON(MSG_ERR, _W("Shader creation error")); return false; } //if(!CheckHRResult(D3DReflect((DWORD*)pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), __uuidof(ID3D10ShaderReflection), &m_pReflection))) if(!CheckHRResult(D3D10ReflectShader(pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), &m_pReflection))) { CON(MSG_ERR, _W("Could not create a Shader reflection")); return false; } //HRESULT D3DReflect(LPCVOID pSrcData, SIZE_T SrcDataSize, REFIID pInterface, void **ppReflector); D3D10_SHADER_DESC shDesc; m_pReflection->GetDesc(&shDesc); m_numResources = shDesc.BoundResources; //not sure about this if(desc.ShaderType == SHADERTYPE_VERTEX_SHADER) m_pVertDecl = new CVertexDeclaration(CRenderer::cGraphicsManager()->GetVertexDescByID(desc.VertexDescID), pShaderBlob); SAFE_RELEASE(pShaderBlob); m_desc = desc; CON(MSG_INFO, _W("Shader '%s' created"), desc.ShaderFile); return true; }
//----------------------------------------------------------------------- void D3D10HLSLProgram::loadFromSource(void) { class HLSLIncludeHandler : public ID3D10Include { public: HLSLIncludeHandler(Resource* sourceProgram) : mProgram(sourceProgram) {} ~HLSLIncludeHandler() {} STDMETHOD(Open)(D3D10_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pByteLen ) { // find & load source code DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource( String(pFileName), mProgram->getGroup(), true, mProgram); String source = stream->getAsString(); // copy into separate c-string // Note - must NOT copy the null terminator, otherwise this will terminate // the entire program string! *pByteLen = static_cast<UINT>(source.length()); char* pChar = new char[*pByteLen]; memcpy(pChar, source.c_str(), *pByteLen); *ppData = pChar; return S_OK; } STDMETHOD(Close)(LPCVOID pData) { char* pChar = (char*)pData; delete [] pChar; return S_OK; } protected: Resource* mProgram; }; // include handler HLSLIncludeHandler includeHandler(this); ID3D10Blob * errors = 0; /*String profile; // Instruction set to be used when generating code. Possible values: "vs_4_0", "ps_4_0", or "gs_4_0". switch(mType) { case GPT_VERTEX_PROGRAM: profile = "vs_4_0"; break; case GPT_FRAGMENT_PROGRAM: profile = "ps_4_0"; break; }*/ HRESULT hr = D3DX10CompileFromMemory( mSource.c_str(), // [in] Pointer to the shader in memory. mSource.size(), // [in] Size of the shader in memory. NULL, // [in] The name of the file that contains the shader code. NULL, // [in] Optional. Pointer to a NULL-terminated array of macro definitions. See D3D10_SHADER_MACRO. If not used, set this to NULL. &includeHandler, // [in] Optional. Pointer to an ID3D10Include Interface interface for handling include files. Setting this to NULL will cause a compile error if a shader contains a #include. mEntryPoint.c_str(), // [in] Name of the shader-entrypoint function where shader execution begins. mTarget.c_str(), // [in] A string that specifies the shader model; can be any profile in shader model 2, shader model 3, or shader model 4. 0, // [in] Effect compile flags - no D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY at the first try... NULL, // [in] Effect compile flags NULL, // [in] A pointer to a thread pump interface (see ID3DX10ThreadPump Interface). Use NULL to specify that this function should not return until it is completed. &mpMicroCode, // [out] A pointer to an ID3D10Blob Interface which contains the compiled shader, as well as any embedded debug and symbol-table information. &errors, // [out] A pointer to an ID3D10Blob Interface which contains a listing of errors and warnings that occured during compilation. These errors and warnings are identical to the the debug output from a debugger. NULL // [out] A pointer to the return value. May be NULL. If pPump is not NULL, then pHResult must be a valid memory location until the asynchronous execution completes. ); if (FAILED(hr)) // if fails - try with backwards compatibility flag { hr = D3DX10CompileFromMemory( mSource.c_str(), // [in] Pointer to the shader in memory. mSource.size(), // [in] Size of the shader in memory. NULL, // [in] The name of the file that contains the shader code. NULL, // [in] Optional. Pointer to a NULL-terminated array of macro definitions. See D3D10_SHADER_MACRO. If not used, set this to NULL. &includeHandler, // [in] Optional. Pointer to an ID3D10Include Interface interface for handling include files. Setting this to NULL will cause a compile error if a shader contains a #include. mEntryPoint.c_str(), // [in] Name of the shader-entrypoint function where shader execution begins. mTarget.c_str(), // [in] A string that specifies the shader model; can be any profile in shader model 2, shader model 3, or shader model 4. D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY, // [in] Effect compile flags - D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY enables older shaders to compile to 4_0 targets NULL, // [in] Effect compile flags NULL, // [in] A pointer to a thread pump interface (see ID3DX10ThreadPump Interface). Use NULL to specify that this function should not return until it is completed. &mpMicroCode, // [out] A pointer to an ID3D10Blob Interface which contains the compiled shader, as well as any embedded debug and symbol-table information. &errors, // [out] A pointer to an ID3D10Blob Interface which contains a listing of errors and warnings that occured during compilation. These errors and warnings are identical to the the debug output from a debugger. NULL // [out] A pointer to the return value. May be NULL. If pPump is not NULL, then pHResult must be a valid memory location until the asynchronous execution completes. ); } #if 0 // this is how you disassemble LPCSTR commentString = NULL; ID3D10Blob* pIDisassembly = NULL; char* pDisassembly = NULL; if( mpMicroCode ) { D3D10DisassembleShader( (UINT*) mpMicroCode->GetBufferPointer(), mpMicroCode->GetBufferSize(), TRUE, commentString, &pIDisassembly ); } const char* assemblyCode = static_cast<const char*>(pIDisassembly->GetBufferPointer()); #endif if (FAILED(hr)) { mErrorsInCompile = true; String message = "Cannot assemble D3D10 high-level shader " + mName + " Errors:\n" + static_cast<const char*>(errors->GetBufferPointer()); errors->Release(); OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, message, "D3D10HLSLProgram::loadFromSource"); } SIZE_T BytecodeLength = mpMicroCode->GetBufferSize(); // this is a temp patch for the nov 08 DX SDK #ifdef D3DX10ReflectShader hr = D3DX10ReflectShader( (void*) mpMicroCode->GetBufferPointer(), BytecodeLength, &mpIShaderReflection ); #else hr = D3D10ReflectShader( (void*) mpMicroCode->GetBufferPointer(), BytecodeLength, &mpIShaderReflection ); #endif if (!FAILED(hr)) { hr = mpIShaderReflection->GetDesc( &mShaderDesc ); if (!FAILED(hr)) { if (mShaderDesc.ConstantBuffers == 1) { mShaderReflectionConstantBuffer = mpIShaderReflection->GetConstantBufferByIndex(0); hr = mShaderReflectionConstantBuffer->GetDesc(&mConstantBufferDesc); createConstantBuffer(mConstantBufferDesc.Size); for(unsigned int i = 0; i < mConstantBufferDesc.Variables ; i++) { ID3D10ShaderReflectionVariable* varRef; varRef = mShaderReflectionConstantBuffer->GetVariableByIndex(i); D3D10_SHADER_VARIABLE_DESC shaderVerDesc; HRESULT hr = varRef->GetDesc(&shaderVerDesc); ShaderVarWithPosInBuf newVar; newVar.var = shaderVerDesc; newVar.wasInit = false; mShaderVars.push_back(newVar); } } } } switch(mType) { case GPT_VERTEX_PROGRAM: CreateVertexShader(); break; case GPT_FRAGMENT_PROGRAM: CreatePixelShader(); break; } }
void CShaderCreator::FinalizeRes( TResource * pRes ) { // Компилируем шейдер -------------------------------------------------- ID3D10Blob * pByteCode = NULL; CShader * pShader = (CShader *)pRes->pResource; uint nConstBufferSize; const char * szEntry = NULL; const char * szProfile = NULL; bool bIsVertexShader = true; if ( CStr::FinishWith( pRes->sFileName.GetString(), ".vsh" ) ) { szEntry = "Ripple"; szProfile = "vs_4_0"; } else if ( CStr::FinishWith( pRes->sFileName.GetString(), ".psh" ) ) { szEntry = "main"; szProfile = "ps_4_0"; bIsVertexShader = false; } EResult rStatus = CompileShader( pRes->sFileName.GetString(), (const char *)pRes->pBuffer, szEntry, szProfile, &pByteCode ); // После компиляции исходный код уже не нужен DEL_ARRAY( pRes->pBuffer ); if ( R_OK != rStatus ) { // Компиляция провалилась pRes->eState = TResource::FAILED; return; } ID3D10ShaderReflection * pRef = NULL; HRESULT hRes; if ( bIsVertexShader ) { pShader->m_pByteCodeVS = pByteCode; // Обрабатываем переменные --------------------------------------------- hRes = D3D10ReflectShader( pByteCode->GetBufferPointer(), pByteCode->GetBufferSize(), &pRef ); if ( ( S_OK == hRes ) && ( NULL != pRef ) ) { D3D10_SHADER_DESC desc; pRef->GetDesc( &desc ); DEBUG_ASSERT( 1 == desc.ConstantBuffers ) // Перебираем каждый буффер констант for ( uint i = 0; i < desc.ConstantBuffers; ++i ) { ID3D10ShaderReflectionConstantBuffer * pCBuf = pRef->GetConstantBufferByIndex( i ); D3D10_SHADER_BUFFER_DESC bufDesc; pCBuf->GetDesc( &bufDesc ); const char * szCBName = bufDesc.Name; nConstBufferSize = bufDesc.Size; pShader->m_nUniformCount = bufDesc.Variables; pShader->m_pUniforms = NEW CShader::TUniform [ pShader->m_nUniformCount ]; // Перебираем каждую переменную в буффере for ( uint nVar = 0; nVar < bufDesc.Variables; ++nVar ) { ID3D10ShaderReflectionVariable * pVar = pCBuf->GetVariableByIndex( nVar ); D3D10_SHADER_VARIABLE_DESC varDesc; pVar->GetDesc( &varDesc ); CShader::TUniform & tUniform = pShader->m_pUniforms[ nVar ]; tUniform.sName = varDesc.Name; tUniform.nCount = varDesc.Size / sizeof( vec4 ); tUniform.nLoc = varDesc.StartOffset / sizeof( vec4 ); } } } hRes = g_pDevice->CreateVertexShader( pByteCode->GetBufferPointer(), pByteCode->GetBufferSize(), &pShader->m_pVS ); }