#include #include #include #include #include #include #include #include "DXShaderManager.h" //#include "Util.h" ShaderManager g_shaderManager; using namespace Microsoft::WRL; template <> HRESULT CreateShader(ID3D11Device* pd3dDevice, ID3D11VertexShader** shader, ID3DBlob* pBlob) { HRESULT hr; ID3D11VertexShader* vs = NULL; V(pd3dDevice->CreateVertexShader( pBlob->GetBufferPointer(),pBlob->GetBufferSize(), NULL, &vs ) ); if(FAILED(hr)) { SAFE_RELEASE(vs); } else { SAFE_RELEASE(*shader); *shader = vs; } return hr; }; template <> HRESULT CreateShader(ID3D11Device* pd3dDevice,ID3D11DomainShader** shader, ID3DBlob* pBlob) { HRESULT hr; ID3D11DomainShader* ds = NULL; V( pd3dDevice->CreateDomainShader( pBlob->GetBufferPointer(),pBlob->GetBufferSize(), NULL, &ds ) ); if(FAILED(hr)) { SAFE_RELEASE(ds); } else { SAFE_RELEASE(*shader); *shader = ds; } return hr; }; template <> HRESULT CreateShader(ID3D11Device* pd3dDevice, ID3D11HullShader** shader, ID3DBlob* pBlob) { HRESULT hr; ID3D11HullShader* vs = NULL; V( pd3dDevice->CreateHullShader( pBlob->GetBufferPointer(),pBlob->GetBufferSize(), NULL, &vs ) ); if(FAILED(hr)) { SAFE_RELEASE(vs); } else { SAFE_RELEASE(*shader); *shader = vs; } return hr; }; template <> HRESULT CreateShader(ID3D11Device* pd3dDevice, ID3D11GeometryShader** shader, ID3DBlob* pBlob) { HRESULT hr; ID3D11GeometryShader* vs = NULL; V( pd3dDevice->CreateGeometryShader( pBlob->GetBufferPointer(),pBlob->GetBufferSize(), NULL, &vs ) ); if(FAILED(hr)) { SAFE_RELEASE(vs); } else { SAFE_RELEASE(*shader); *shader = vs; } return hr; }; template <> HRESULT CreateShader(ID3D11Device* pd3dDevice,ID3D11PixelShader** shader, ID3DBlob* pBlob) { HRESULT hr; ID3D11PixelShader* ps = NULL; V( pd3dDevice->CreatePixelShader( pBlob->GetBufferPointer(),pBlob->GetBufferSize(), NULL, &ps ) ); if(FAILED(hr)) { SAFE_RELEASE(ps); } else { SAFE_RELEASE(*shader); *shader = ps; } return hr; }; template <> HRESULT CreateShader(ID3D11Device* pd3dDevice,ID3D11ComputeShader** shader, ID3DBlob* pBlob) { HRESULT hr; ID3D11ComputeShader* vs = NULL; V( pd3dDevice->CreateComputeShader( pBlob->GetBufferPointer(),pBlob->GetBufferSize(), NULL, &vs ) ); if(FAILED(hr)) { SAFE_RELEASE(vs); } else { SAFE_RELEASE(*shader); *shader = vs; } return hr; }; template <> HRESULT CreateShaderStreamOutput(ID3D11Device* pd3dDevice, ID3D11VertexShader** shader, ID3DBlob* pBlob, D3D11_SO_DECLARATION_ENTRY *pSODeclaration, UINT numSOEntries, UINT* pSOStrides, UINT numSOStrides, UINT rasterizerStream ) { return S_FALSE; }; template <> HRESULT CreateShaderStreamOutput(ID3D11Device* pd3dDevice, ID3D11HullShader** shader, ID3DBlob* pBlob, D3D11_SO_DECLARATION_ENTRY *pSODeclaration, UINT numSOEntries, UINT* pSOStrides, UINT numSOStrides, UINT rasterizerStream ) { return S_FALSE; }; template <> HRESULT CreateShaderStreamOutput(ID3D11Device* pd3dDevice, ID3D11DomainShader** shader, ID3DBlob* pBlob, D3D11_SO_DECLARATION_ENTRY *pSODeclaration, UINT numSOEntries, UINT* pSOStrides, UINT numSOStrides, UINT rasterizerStream ) { return S_FALSE; }; template <> HRESULT CreateShaderStreamOutput(ID3D11Device* pd3dDevice, ID3D11GeometryShader** shader, ID3DBlob* pBlob, D3D11_SO_DECLARATION_ENTRY *pSODeclaration, UINT numSOEntries, UINT* pSOStrides, UINT numSOStrides, UINT rasterizerStream ) { HRESULT hr; ID3D11GeometryShader* vs = NULL; V( pd3dDevice->CreateGeometryShaderWithStreamOutput( pBlob->GetBufferPointer(), pBlob->GetBufferSize(),pSODeclaration, numSOEntries, pSOStrides, numSOStrides, rasterizerStream, NULL, &vs) ); if(FAILED(hr)) { SAFE_RELEASE(vs); } else { SAFE_RELEASE(*shader); *shader = vs; } return hr; }; template <> HRESULT CreateShaderStreamOutput(ID3D11Device* pd3dDevice, ID3D11PixelShader** shader, ID3DBlob* pBlob, D3D11_SO_DECLARATION_ENTRY *pSODeclaration, UINT numSOEntries, UINT* pSOStrides, UINT numSOStrides, UINT rasterizerStream ) { return S_FALSE; }; template <> HRESULT CreateShaderStreamOutput(ID3D11Device* pd3dDevice, ID3D11ComputeShader** shader, ID3DBlob* pBlob, D3D11_SO_DECLARATION_ENTRY *pSODeclaration, UINT numSOEntries, UINT* pSOStrides, UINT numSOStrides, UINT rasterizerStream ) { return S_FALSE; }; #include template HRESULT Shader::CompileShader(ID3D11Device* pd3dDevice, ID3DBlob** ppBlobOut ) { HRESULT hr = S_OK; bool srcChanged = false; const auto& globIncludes = g_shaderManager.GetIncludes(); if(m_compiledInvalid) { srcChanged = true; } else { WatchedFile* shaderSrcFileWatch = globIncludes.find(m_fileNameSrcString)->second; srcChanged = CompareFileTime(&shaderSrcFileWatch->getLastWrite().ftLastWriteTime, &m_lastChangeCompiled.ftLastWriteTime) > 0; } if(srcChanged == false) { // check include if(m_firstLoad) // first run { ID3DBlob* srcBlob; D3DReadFileToBlob(m_fileNameSrc, &srcBlob); ID3DBlob* codeBlob; ID3DBlob* errBlob; // preparse CShaderInclude includeObj(m_fileNameSrcString.c_str()); D3DPreprocess(srcBlob->GetBufferPointer(),srcBlob->GetBufferSize(),NULL, m_pDefines, &includeObj, &codeBlob, &errBlob); const std::set& includes = includeObj.GetIncludes(); for(auto inclFileName : includes) { m_includes.insert(inclFileName); WatchedFile* currInclude = g_shaderManager.AddIncludeFile(inclFileName); //std::cout << inclFileName << std::endl; //exit(0); } SAFE_RELEASE(srcBlob); SAFE_RELEASE(codeBlob); SAFE_RELEASE(errBlob); } // check if includes are newer for(const auto it : m_includes) { WatchedFile* incFile = globIncludes.find(it)->second; if(CompareFileTime(&incFile->getLastWrite().ftLastWriteTime, &m_lastChangeCompiled.ftLastWriteTime ) > 0) { srcChanged = true; std::cout << "src changed" << std::endl; break; } } } if(m_firstLoad == false && srcChanged == false) return S_OK; #ifndef _DEBUG // for nsight shader debugging: compile shaders on first load, then only modified if(!g_shaderManager.UsePrecompiledShaders()) { if(m_firstLoad) srcChanged = true; } #endif if(srcChanged) { std::cout << "." ; // make sure sub directories exist CreateDirectory(ExtractPath(m_fileNameCompiled).c_str(), NULL); CShaderInclude includeObj(m_fileNameSrcString.c_str()); DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; if(!g_shaderManager.UsePrecompiledShaders()) { // dwShaderFlags |= D3DCOMPILE_WARNINGS_ARE_ERRORS; } #if defined( DEBUG ) || defined( _DEBUG ) // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders. // Setting this flag improves the shader debugging experience, but still allows // the shaders to be optimized and to run exactly the way they will run in // the release configuration of this program. dwShaderFlags |= D3DCOMPILE_DEBUG; //dwShaderFlags |= D3DCOMPILE_IEEE_STRICTNESS; #endif //dwShaderFlags |= D3DCOMPILE_DEBUG; dwShaderFlags |= m_compilerFlags; ID3DBlob* pErrorBlob= NULL; std::wcout << "Compile: " << m_fileNameSrc << " Entrypoint: " << m_entryPoint << std::endl; hr = D3DCompileFromFile(m_fileNameSrc, m_pDefines, &includeObj, m_entryPoint, m_shaderModel, dwShaderFlags, 0, ppBlobOut, &pErrorBlob); if(pErrorBlob != NULL && pErrorBlob->GetBufferPointer() != NULL && pErrorBlob->GetBufferSize() > 0) { OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() ); std::cerr << (char*)pErrorBlob->GetBufferPointer() << std::endl; SAFE_RELEASE( pErrorBlob ); } if( FAILED(hr) ) { OutputDebugStringA(m_fileNameCompiled.c_str()); OutputDebugStringA("\n"); OutputDebugStringA("-------------------------------------------------------------------------------\n"); std::cout << "filename " << m_fileNameCompiled << std::endl; std::cout << "-------------------------------------------------------------------------------" << std::endl; std::cout << " shader macros: " << std::endl; if(m_pDefines) { for(int numDefs = 0; m_pDefines[numDefs].Name != NULL; ++numDefs) { //std::cout << numDefs << ": " << m_pDefines[numDefs].Name << " " << m_pDefines[numDefs].Definition << std::endl; std::cout << m_pDefines[numDefs].Name << "=" << m_pDefines[numDefs].Definition << std::endl; } } return hr; } // regenerate include file list //m_includes.clear(); const std::set& includes = includeObj.GetIncludes(); for(auto inclFileName : includes) { m_includes.insert(inclFileName); WatchedFile* currInclude = g_shaderManager.AddIncludeFile(inclFileName); } // write compiled shader to disk //std::wcout << m_fileNameCompiled << std::endl; V(D3DWriteBlobToFile(*ppBlobOut, std::wstring(m_fileNameCompiled.begin(), m_fileNameCompiled.end()).c_str(), true)); if(hr!= S_OK) { std::cout << "filename " << m_fileNameCompiled << "to long, aborting" << std::endl; V_RETURN(hr); exit(1); } std::ofstream compiledFile(m_fileNameCompiled.c_str(), std::ios::out | std::ios::binary); compiledFile.write((char*)(*ppBlobOut)->GetBufferPointer(), (*ppBlobOut)->GetBufferSize()); compiledFile.close(); // unref old shader if one is bound SAFE_RELEASE(m_shader); if(m_SONumEntries>0) { V(CreateShaderStreamOutput(pd3dDevice, &m_shader, *ppBlobOut, m_SODeclarationArray, m_SONumEntries, m_SOStridesArray, m_SONumStrides, m_rasterizerStream)); } else V(CreateShader(pd3dDevice, &m_shader, *ppBlobOut)); HANDLE hFindCompiled = FindFirstFile(m_fileNameCompiled.c_str(), &m_lastChangeCompiled); if(hFindCompiled != INVALID_HANDLE_VALUE) m_compiledInvalid = false; } else // load pre-compiled shader { std::cout << "." ; std::ifstream compiledFile(m_fileNameCompiled.c_str(), std::ios::in | std::ios::binary); assert(compiledFile.is_open()); unsigned int size_data = m_lastChangeCompiled.nFileSizeLow; V(D3DReadFileToBlob(std::wstring(m_fileNameCompiled.begin(), m_fileNameCompiled.end()).c_str(), ppBlobOut)); if(hr!= S_OK) { std::cout << "filename " << m_fileNameCompiled << " path to long, aborting" << std::endl; V_RETURN(hr); exit(1); } //V(D3DCreateBlob(size_data,ppBlobOut)); //compiledFile.read((char*)(*ppBlobOut)->GetBufferPointer(), size_data); //compiledFile.close(); // unref old shader if one is bound SAFE_RELEASE(m_shader); if(m_SONumEntries>0) { V(CreateShaderStreamOutput(pd3dDevice, &m_shader, *ppBlobOut, m_SODeclarationArray, m_SONumEntries, m_SOStridesArray, m_SONumStrides, m_rasterizerStream)); } else { V(CreateShader(pd3dDevice, &m_shader, *ppBlobOut)); } m_compiledInvalid = false; } m_firstLoad = false; return hr; } ShaderManager::ShaderManager() { m_compiledShaderDirectory = COMPILED_SHADER_DIR; CreateDirectory(m_compiledShaderDirectory.c_str(), NULL); m_precompiledShadersEnabled = true; } ShaderManager::~ShaderManager() { Destroy(); } Shader* ShaderManager::AddVertexShader( ID3D11Device* pd3dDevice, const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut, D3D_SHADER_MACRO* pDefines /*= NULL*/, DWORD compilerFlags, const std::vector& configHashes, ID3D11ClassLinkage* pClassLinkage /*= NULL */ ) { std::string compiledFileName = CreateCompiledFileName( szFileName, szEntryPoint, szShaderModel, pDefines, compilerFlags, configHashes); // check if shader is cached auto it = m_vertexShaders.find(compiledFileName); if(it != m_vertexShaders.end()) { return it->second; } // otherwise load the shader Shader* shader = new Shader(pd3dDevice, szFileName, szEntryPoint, szShaderModel, VERTEX_SHADER, ppBlobOut, compiledFileName, pDefines, compilerFlags, pClassLinkage); m_vertexShaders[compiledFileName] = shader; return shader; } Shader* ShaderManager::AddHullShader( ID3D11Device* pd3dDevice, const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut, D3D_SHADER_MACRO* pDefines /*= NULL*/, DWORD compilerFlags, const std::vector& configHashes, ID3D11ClassLinkage* pClassLinkage /*= NULL */ ) { std::string compiledFileName = CreateCompiledFileName( szFileName, szEntryPoint, szShaderModel, pDefines, compilerFlags, configHashes); // check if shader is cached auto it = m_hullShaders.find(compiledFileName); if(it != m_hullShaders.end()) return it->second; // otherwise load the shader Shader* shader = new Shader(pd3dDevice, szFileName, szEntryPoint, szShaderModel, HULL_SHADER, ppBlobOut, compiledFileName, pDefines, compilerFlags, pClassLinkage); m_hullShaders[compiledFileName] = shader; return shader; } Shader* ShaderManager::AddDomainShader( ID3D11Device* pd3dDevice, const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut, D3D_SHADER_MACRO* pDefines /*= NULL*/, DWORD compilerFlags, const std::vector& configHashes, ID3D11ClassLinkage* pClassLinkage /*= NULL */ ) { std::string compiledFileName = CreateCompiledFileName( szFileName, szEntryPoint, szShaderModel, pDefines, compilerFlags, configHashes); // check if shader is cached auto it = m_domainShaders.find(compiledFileName); if(it != m_domainShaders.end()) return it->second; // otherwise load the shader Shader* shader = new Shader(pd3dDevice, szFileName, szEntryPoint, szShaderModel, DOMAIN_SHADER, ppBlobOut, compiledFileName, pDefines, compilerFlags, pClassLinkage); if(shader->Get() != NULL) { m_domainShaders[compiledFileName] = shader; return shader; } else return NULL; } Shader* ShaderManager::AddGeometryShader( ID3D11Device* pd3dDevice, const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut, D3D_SHADER_MACRO* pDefines /*= NULL*/, DWORD compilerFlags, const std::vector& configHashes, ID3D11ClassLinkage* pClassLinkage /*= NULL */ ) { std::string compiledFileName = CreateCompiledFileName( szFileName, szEntryPoint, szShaderModel, pDefines, compilerFlags, configHashes); // check if shader is cached auto it = m_geometryShaders.find(compiledFileName); if(it != m_geometryShaders.end()) return it->second; // otherwise load the shader Shader* shader = new Shader(pd3dDevice, szFileName, szEntryPoint, szShaderModel, GEOMETRY_SHADER, ppBlobOut, compiledFileName, pDefines, compilerFlags, pClassLinkage); m_geometryShaders[compiledFileName] = shader; return shader; } Shader* ShaderManager::AddGeometryShaderSO( ID3D11Device* pd3dDevice, const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut, D3D_SHADER_MACRO* pDefines /*= NULL*/, DWORD compilerFlags /*= 0*/, D3D11_SO_DECLARATION_ENTRY *pSODeclaration /*= NULL*/, UINT numSOEntries /*= 0*/, UINT* pSOStrides /*= NULL*/, UINT numSOStrides /*= 0*/, UINT rasterizerStream /*= D3D11_SO_NO_RASTERIZED_STREAM*/, ID3D11ClassLinkage* pClassLinkage /*= NULL*/ ) { std::string compiledFileName = CreateCompiledFileName( szFileName, szEntryPoint, szShaderModel, pDefines, compilerFlags); // check if shader is cached auto it = m_geometryShaders.find(compiledFileName); if(it != m_geometryShaders.end()) return it->second; // otherwise load the shader Shader* shader = new Shader(pd3dDevice, szFileName, szEntryPoint, szShaderModel, GEOMETRY_SHADER, ppBlobOut, compiledFileName, pDefines, compilerFlags, pSODeclaration, numSOEntries, pSOStrides, numSOStrides, rasterizerStream, pClassLinkage); m_geometryShaders[compiledFileName] = shader; return shader; } Shader* ShaderManager::AddPixelShader( ID3D11Device* pd3dDevice, const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut, D3D_SHADER_MACRO* pDefines /*= NULL*/, DWORD compilerFlags, const std::vector& configHashes, ID3D11ClassLinkage* pClassLinkage /*= NULL */ ) { std::string compiledFileName = CreateCompiledFileName( szFileName, szEntryPoint, szShaderModel, pDefines, compilerFlags, configHashes); // check if shader is cached auto it = m_pixelShaders.find(compiledFileName); if(it != m_pixelShaders.end()) return it->second; // otherwise load the shader Shader* shader = new Shader(pd3dDevice, szFileName, szEntryPoint, szShaderModel, PIXEL_SHADER, ppBlobOut, compiledFileName, pDefines, compilerFlags, pClassLinkage); m_pixelShaders[compiledFileName] = shader; return shader; } Shader* ShaderManager::AddComputeShader( ID3D11Device* pd3dDevice, const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut, D3D_SHADER_MACRO* pDefines /*= NULL*/, DWORD compilerFlags, const std::vector& configHashes, ID3D11ClassLinkage* pClassLinkage /*= NULL */ ) { std::string compiledFileName = CreateCompiledFileName( szFileName, szEntryPoint, szShaderModel, pDefines, compilerFlags, configHashes); // check if shader is cached auto it = m_computeShaders.find(compiledFileName); if(it != m_computeShaders.end()) return it->second; // otherwise load the shader Shader* shader = new Shader(pd3dDevice, szFileName, szEntryPoint, szShaderModel, COMPUTE_SHADER, ppBlobOut, compiledFileName, pDefines, compilerFlags, pClassLinkage); m_computeShaders[compiledFileName] = shader; return shader; } HRESULT ShaderManager::CheckAndReload(ID3D11Device* pd3dDevice) { HRESULT hr = S_OK; for(auto& inc : m_includeFiles ) { inc.second->CheckIsModified(); } for( const auto& shader : m_vertexShaders) { hr = shader.second->CheckAndReload(pd3dDevice); if(FAILED(hr)) return hr;} for( const auto& shader : m_hullShaders) { hr = shader.second->CheckAndReload(pd3dDevice); if(FAILED(hr)) return hr;} for( const auto& shader : m_domainShaders) { hr = shader.second->CheckAndReload(pd3dDevice); if(FAILED(hr)) return hr;} for( const auto& shader : m_geometryShaders){ hr = shader.second->CheckAndReload(pd3dDevice); if(FAILED(hr)) return hr;} for( const auto& shader : m_pixelShaders) { hr = shader.second->CheckAndReload(pd3dDevice); if(FAILED(hr)) return hr;} for( const auto& shader : m_computeShaders) { hr = shader.second->CheckAndReload(pd3dDevice); if(FAILED(hr)) return hr;} return hr; } void ShaderManager::Destroy() { for(auto& inc : m_includeFiles) { SAFE_DELETE(inc.second); } m_includeFiles.clear(); for(auto &shader : m_vertexShaders) delete shader.second; for(auto &shader : m_domainShaders) delete shader.second; for(auto &shader : m_hullShaders) delete shader.second; for(auto &shader : m_geometryShaders) delete shader.second; for(auto &shader : m_pixelShaders) delete shader.second; for(auto &shader : m_computeShaders) delete shader.second; m_vertexShaders.clear(); m_hullShaders.clear(); m_domainShaders.clear(); m_geometryShaders.clear(); m_pixelShaders.clear(); m_computeShaders.clear(); } //const char* gSystemDir = "..\\Shader"; std::string ShaderManager::CreateCompiledFileName( const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, D3D_SHADER_MACRO* pDefines /*= NULL*/, DWORD compilerFlags /*= 0*/, const std::vector& config_hashes ) { std::string compiledFileName = m_compiledShaderDirectory; compiledFileName.append(szFileName); compiledFileName.append("-"); compiledFileName.append( szEntryPoint ); if(!config_hashes.empty()) { for(auto hash : config_hashes) { std::stringstream ws; ws << (int)hash; compiledFileName.append("_"); compiledFileName.append(ws.str().c_str()); } } else { if(pDefines) { compiledFileName.append("-"); for(UINT i = 0; pDefines[i].Name != NULL; ++i) { std::string name = pDefines[i].Name; if(name[0] == L'\"') name[0] = L'x'; if(name[name.length() -1 ] == '\"') name[name.length()-1] = L'x'; std::string def = pDefines[i].Definition; if(def[0] == L'\"') def[0] = L'x'; if(def[def.length() -1 ] == L'\"') def[def.length()-1] = 'x'; compiledFileName.append(name); compiledFileName.append("_"); compiledFileName.append(def); if(pDefines[i+1].Name != NULL) compiledFileName.append("-"); } } } if(compilerFlags) { compiledFileName.append("-"); std::stringstream ss; ss << compilerFlags; compiledFileName.append(ss.str()); } compiledFileName.append(".p"); //std::wcout << compiledFileName.c_str()<< std::endl; return compiledFileName; } WatchedFile* ShaderManager::AddIncludeFile( std::string includeFileName ) { const auto& it = m_includeFiles.find(includeFileName); if(it == m_includeFiles.end()) { WatchedFile* inc = new WatchedFile(includeFileName); m_includeFiles[includeFileName] = inc; return inc; } else return it->second; } CShaderInclude::CShaderInclude( const char* shaderDir, const char* systemDir ) { m_ShaderDir = ExtractPath(shaderDir); m_SystemDir = ExtractPath(systemDir); } HRESULT __stdcall CShaderInclude::Open(D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) { try { std::string finalPath; switch(IncludeType) { case D3D_INCLUDE_LOCAL: if (m_ShaderDir != std::string("")) finalPath = m_ShaderDir + "\\" + pFileName; else finalPath = pFileName; break; case D3D_INCLUDE_SYSTEM: if (m_SystemDir != std::string("")) finalPath = m_SystemDir + "\\" + pFileName; else finalPath = pFileName; break; default: assert(0); } m_includeFiles.insert(finalPath); //std::cout << finalPath << std::endl; std::ifstream includeFile(finalPath.c_str(), std::ios::in|std::ios::binary|std::ios::ate); if (includeFile.is_open()) { long long fileSize = includeFile.tellg(); char* buf = new char[(unsigned int)fileSize]; includeFile.seekg (0, std::ios::beg); includeFile.read (buf, fileSize); includeFile.close(); *ppData = buf; *pBytes = (unsigned int)fileSize; } else { return E_FAIL; } return S_OK; } catch(std::exception) { return E_FAIL; } } HRESULT __stdcall CShaderInclude::Close(LPCVOID pData) { char* buf = (char*)pData; delete[] buf; return S_OK; } WatchedFile::WatchedFile( const std::string& includeFileName ) { m_fileName = includeFileName; HANDLE hFind = FindFirstFile(m_fileName.c_str(), &m_lastWrite); } WatchedFile::~WatchedFile() { } bool WatchedFile::CheckIsModified() { auto lastWrite = m_lastWrite.ftLastWriteTime; HANDLE hFind = FindFirstFile(m_fileName.c_str(), &m_lastWrite); return CompareFileTime(&m_lastWrite.ftLastWriteTime,&lastWrite) > 0; } DrawSourceConfig::~DrawSourceConfig() { for(auto e: commonShader.defines) { e.first.clear(); e.second.clear(); } for(auto e: vertexShader.defines) { e.first.clear(); e.second.clear(); } for(auto e: hullShader.defines) { e.first.clear(); e.second.clear(); } for(auto e: domainShader.defines) { e.first.clear(); e.second.clear(); } for(auto e: geometryShader.defines) { e.first.clear(); e.second.clear(); } for(auto e: pixelShader.defines) { e.first.clear(); e.second.clear(); } for(auto e: commonShader.defines) { e.first.clear(); e.second.clear(); } commonShader.defines.clear(); computeShader.defines.clear(); vertexShader.defines.clear(); hullShader.defines.clear(); domainShader.defines.clear(); geometryShader.defines.clear(); pixelShader.defines.clear(); } DrawSourceConfig * DrawRegistryBase::_CreateDrawSourceConfig( DescType const & desc, ID3D11Device * pd3dDevice ) const { DrawSourceConfig * sconfig = _NewDrawSourceConfig(); sconfig->vertexShader.target = "vs_5_0"; sconfig->hullShader.target = "hs_5_0"; sconfig->domainShader.target = "ds_5_0"; sconfig->geometryShader.target = "gs_5_0"; sconfig->pixelShader.target = "ps_5_0"; sconfig->computeShader.target = "cs_5_0"; sconfig->vertexShader.sourceFile.clear(); sconfig->hullShader.sourceFile.clear(); sconfig->domainShader.sourceFile.clear(); sconfig->geometryShader.sourceFile.clear(); sconfig->pixelShader.sourceFile.clear(); sconfig->computeShader.sourceFile.clear(); return sconfig; } void createDefineMacro(const std::vector< const ShaderDefineVector* >& defvec, std::vector& outDefs) { for (int i=0; i<(int)defvec.size(); ++i) { for(const auto& defI : *defvec[i]) { const D3D_SHADER_MACRO def = { defI.first.c_str(), defI.second.c_str(), }; outDefs.push_back(def); } } const D3D_SHADER_MACRO zerodef = { 0, 0 }; outDefs.push_back(zerodef); } DrawConfig* DrawRegistryBase::_CreateDrawConfig( DescType const & desc, SourceConfigType const * sconfig, ID3D11Device * pd3dDevice, ID3D11InputLayout ** ppInputLayout, D3D11_INPUT_ELEMENT_DESC const * pInputElementDescs, int numInputElements ) const { assert(sconfig); bool debug_shader_build = false; DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; #ifdef _DEBUG dwShaderFlags |= D3DCOMPILE_DEBUG; debug_shader_build = true; #else //dwShaderFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; #endif ID3DBlob * pBlob = NULL; Shader *vertexShader = NULL; if (! sconfig->vertexShader.sourceFile.empty()) { std::vector config_hashes; config_hashes.push_back(sconfig->value); if(debug_shader_build) config_hashes.push_back(1337); std::vector fullDefs; fullDefs.push_back(&sconfig->commonShader.defines); fullDefs.push_back(&sconfig->vertexShader.defines); std::vector defs; createDefineMacro(fullDefs,defs); vertexShader = g_shaderManager.AddVertexShader(pd3dDevice, sconfig->vertexShader.sourceFile.c_str(), sconfig->vertexShader.entry.c_str(), sconfig->vertexShader.target.c_str(), &pBlob, &defs[0], dwShaderFlags, config_hashes); fullDefs.clear(); assert(vertexShader->Get()); if (ppInputLayout && !*ppInputLayout) { pd3dDevice->CreateInputLayout(pInputElementDescs, numInputElements, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), ppInputLayout); assert(ppInputLayout); } SAFE_RELEASE(pBlob); } Shader *hullShader = NULL; if (! sconfig->hullShader.sourceFile.empty()) { std::vector config_hashes; config_hashes.push_back(sconfig->value); if(debug_shader_build) config_hashes.push_back(1337); std::vector fullDefs; fullDefs.push_back(&sconfig->commonShader.defines); fullDefs.push_back(&sconfig->hullShader.defines); std::vector defs; createDefineMacro(fullDefs,defs); hullShader = g_shaderManager.AddHullShader(pd3dDevice, sconfig->hullShader.sourceFile.c_str(), sconfig->hullShader.entry.c_str(), sconfig->hullShader.target.c_str(), &pBlob, &defs[0], dwShaderFlags, config_hashes); assert(hullShader->Get()); SAFE_RELEASE(pBlob); } Shader *domainShader = NULL; if (! sconfig->domainShader.sourceFile.empty()) { std::vector config_hashes; config_hashes.push_back(sconfig->value); if(debug_shader_build) config_hashes.push_back(1337); std::vector fullDefs; fullDefs.push_back(&sconfig->commonShader.defines); fullDefs.push_back(&sconfig->domainShader.defines); std::vector defs; createDefineMacro(fullDefs, defs); domainShader = g_shaderManager.AddDomainShader(pd3dDevice, sconfig->domainShader.sourceFile.c_str(), sconfig->domainShader.entry.c_str(), sconfig->domainShader.target.c_str(), &pBlob, &defs[0], dwShaderFlags, config_hashes); assert(domainShader->Get()); SAFE_RELEASE(pBlob); } Shader *geometryShader = NULL; if (! sconfig->geometryShader.sourceFile.empty()) { std::vector config_hashes; config_hashes.push_back(sconfig->value); if(debug_shader_build) config_hashes.push_back(1337); std::vector fullDefs; fullDefs.push_back(&sconfig->commonShader.defines); fullDefs.push_back(&sconfig->geometryShader.defines); std::vector defs; createDefineMacro(fullDefs,defs); geometryShader = g_shaderManager.AddGeometryShader(pd3dDevice, sconfig->geometryShader.sourceFile.c_str(), sconfig->geometryShader.entry.c_str(), sconfig->geometryShader.target.c_str(), &pBlob, &defs[0], dwShaderFlags, config_hashes); assert(geometryShader->Get()); SAFE_RELEASE(pBlob); } Shader *pixelShader = NULL; if (! sconfig->pixelShader.sourceFile.empty()) { std::vector config_hashes; config_hashes.push_back(sconfig->value); if(debug_shader_build) config_hashes.push_back(1337); std::vector fullDefs; fullDefs.push_back(&sconfig->commonShader.defines); fullDefs.push_back(&sconfig->pixelShader.defines); std::vector defs; createDefineMacro(fullDefs,defs); pixelShader = g_shaderManager.AddPixelShader(pd3dDevice, sconfig->pixelShader.sourceFile.c_str(), sconfig->pixelShader.entry.c_str(), sconfig->pixelShader.target.c_str(), &pBlob, &defs[0], dwShaderFlags, config_hashes); assert(pixelShader); SAFE_RELEASE(pBlob); } Shader *computeShader = NULL; if (! sconfig->computeShader.sourceFile.empty()) { std::vector config_hashes; config_hashes.push_back(sconfig->value); if(debug_shader_build) config_hashes.push_back(1337); std::vector fullDefs; fullDefs.push_back(&sconfig->commonShader.defines); fullDefs.push_back(&sconfig->computeShader.defines); std::vector defs; createDefineMacro(fullDefs,defs); computeShader = g_shaderManager.AddComputeShader(pd3dDevice, sconfig->computeShader.sourceFile.c_str(), sconfig->computeShader.entry.c_str(), sconfig->computeShader.target.c_str(), &pBlob, &defs[0], dwShaderFlags, config_hashes); assert(computeShader); SAFE_RELEASE(pBlob); } DrawConfig * config = _NewDrawConfig(); config->srcConfig = const_cast(sconfig); config->vertexShader = vertexShader; config->hullShader = hullShader; config->domainShader = domainShader; config->geometryShader = geometryShader; config->pixelShader = pixelShader; config->computeShader = computeShader; return config; }