ComputeShader::ComputeShader( Device& _Device, const char* _pShaderFileName, ID3DBlob* _pCS ) : Component( _Device ) , m_pCS( NULL ) , m_pShaderPath( NULL ) , m_pIncludeOverride( NULL ) , m_pMacros( NULL ) , m_bHasErrors( false ) #if defined(_DEBUG) || !defined(GODCOMPLEX) , m_LastShaderModificationTime( 0 ) #endif #ifdef COMPUTE_SHADER_COMPILE_THREADED , m_hCompileThread( 0 ) #endif { #if defined(_DEBUG) || !defined(GODCOMPLEX) m_pShaderFileName = CopyString( _pShaderFileName ); #endif #ifndef GODCOMPLEX m_pShaderPath = GetShaderPath( _pShaderFileName ); m_Pointer2FileName.Add( NULL, m_pShaderPath ); #endif ASSERT( _pCS != NULL, "You can't provide a NULL CS blob!" ); CompileShaders( NULL, _pCS ); }
//------------------------------------------------------------------------------------ Shader* D3D11RenderSystem::CreateShader(eShaderType type, eRenderPhase phase, const STRING& filename, uint32 flags, const STRING& strEntryFunc, eVertexType vertType, const std::vector<D3D_SHADER_MACRO>& vecMacros) { D3D11Shader* pShader = nullptr; STRING strShaderFile = GetShaderPath(filename); switch (type) { case eShaderType_VS: pShader = new D3D11VertexShader(strShaderFile.c_str(), flags, strEntryFunc.c_str(), vertType, vecMacros); break; case eShaderType_PS: pShader = new D3D11PixelShader(strShaderFile.c_str(), flags, strEntryFunc.c_str(), vecMacros); break; case eShaderType_GS: pShader = new D3D11GeometryShader(strShaderFile.c_str(), flags, strEntryFunc.c_str(), vecMacros); break; case eShaderType_CS: pShader = new D3D11ComputeShader(strShaderFile.c_str(), flags, strEntryFunc.c_str(), vecMacros); break; case eShaderType_HS: pShader = new D3D11HullShader(strShaderFile.c_str(), flags, strEntryFunc.c_str(), vecMacros); break; case eShaderType_DS: pShader = new D3D11DomainShader(strShaderFile.c_str(), flags, strEntryFunc.c_str(), vecMacros); break; default: _AST(0); } return pShader; }
HRESULT ComputeShader::Open( THIS_ D3D_INCLUDE_TYPE _IncludeType, LPCSTR _pFileName, LPCVOID _pParentData, LPCVOID* _ppData, UINT* _pBytes ) { if ( m_pIncludeOverride != NULL ) return m_pIncludeOverride->Open( _IncludeType, _pFileName, _pParentData, _ppData, _pBytes ); #ifndef GODCOMPLEX const char** ppShaderPath = m_Pointer2FileName.Get( U32(_pParentData) ); ASSERT( ppShaderPath != NULL, "Failed to retrieve data pointer !" ); const char* pShaderPath = *ppShaderPath; char pFullName[4096]; sprintf_s( pFullName, 4096, "%s%s", pShaderPath, _pFileName ); FILE* pFile; fopen_s( &pFile, pFullName, "rb" ); ASSERT( pFile != NULL, "Include file not found !" ); fseek( pFile, 0, SEEK_END ); U32 Size = ftell( pFile ); fseek( pFile, 0, SEEK_SET ); char* pBuffer = new char[Size]; fread_s( pBuffer, Size, 1, Size, pFile ); // pBuffer[Size] = '\0'; *_pBytes = Size; *_ppData = pBuffer; fclose( pFile ); // Register this shader's path as attached to the data pointer const char* pIncludedShaderPath = GetShaderPath( pFullName ); m_Pointer2FileName.Add( U32(*_ppData), pIncludedShaderPath ); #else ASSERT( false, "You MUST provide an ID3DINCLUDE override when compiling with the GODCOMPLEX option !" ); #endif return S_OK; }
//test code to compile Test.hlsl bool Renderer::createShadersAndInputLayouts(void) { UINT flags1 = 0; #if _DEBUG flags1 |= D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG; #endif ID3DBlob *vShaderCode = nullptr; ID3DBlob *pShaderCode = nullptr; ID3DBlob *gShaderCode = nullptr; ID3DBlob *errorCode = nullptr; HRESULT res; D3D11_INPUT_ELEMENT_DESC positionInputElement; positionInputElement.AlignedByteOffset = 0; positionInputElement.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; positionInputElement.InputSlot = 0; positionInputElement.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; positionInputElement.InstanceDataStepRate = 0; positionInputElement.SemanticName = "POSITION"; positionInputElement.SemanticIndex = 0; //create Texture shaders------------------------------------------------------------------------------------------------------------ if(FAILED(D3DCompileFromFile(GetShaderPath(L"Texture.hlsl").data(), nullptr, nullptr, "VShader", "vs_5_0", flags1, 0, &vShaderCode, &errorCode))) { SafeRelease<ID3DBlob>(&vShaderCode); if(errorCode) { OutputDebugStringA((LPCSTR)errorCode->GetBufferPointer()); SafeRelease<ID3DBlob>(&errorCode); } return false; } if(FAILED(D3DCompileFromFile(GetShaderPath(L"Texture.hlsl").data(), nullptr, nullptr, "PShader", "ps_5_0", flags1, 0, &pShaderCode, &errorCode))) { SafeRelease<ID3DBlob>(&pShaderCode); if(errorCode) { OutputDebugStringA((LPCSTR)errorCode->GetBufferPointer()); SafeRelease<ID3DBlob>(&errorCode); } return false; } if(FAILED(this->device->CreatePixelShader(pShaderCode->GetBufferPointer(), pShaderCode->GetBufferSize(), nullptr, &this->texturePShader))) { OutputDebugString("\n create texture pixel shader failed \n"); return false; } if(FAILED(this->device->CreateVertexShader(vShaderCode->GetBufferPointer(), vShaderCode->GetBufferSize(), nullptr, &this->textureVShader))) { OutputDebugString("\n create texture vertex shader failed \n"); return false; } D3D11_INPUT_ELEMENT_DESC textureInputElement; textureInputElement.AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; textureInputElement.Format = DXGI_FORMAT_R32G32_FLOAT; textureInputElement.InputSlot = 0; textureInputElement.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; textureInputElement.InstanceDataStepRate = 0; textureInputElement.SemanticIndex = 0; textureInputElement.SemanticName = "TEXCOORD"; D3D11_INPUT_ELEMENT_DESC textureShaderInput[] = {positionInputElement, textureInputElement}; if(FAILED(this->device->CreateInputLayout(textureShaderInput, 2, vShaderCode->GetBufferPointer(), vShaderCode->GetBufferSize(), &this->textureInputLayout))) { OutputDebugString("\n Create textureShaderInput failed \n"); return false; } SafeRelease<ID3DBlob>(&vShaderCode); SafeRelease<ID3DBlob>(&pShaderCode); //create color shaders and input layout --------------------------------------------------------------------------------------------- if(FAILED(D3DCompileFromFile(GetShaderPath(L"Colored.hlsl").data(), nullptr, nullptr, "VShader", "vs_5_0", flags1, 0, &vShaderCode, &errorCode))) { SafeRelease<ID3DBlob>(&vShaderCode); if(errorCode) { OutputDebugStringA((LPCSTR)errorCode->GetBufferPointer()); SafeRelease<ID3DBlob>(&errorCode); } return false; } if(FAILED(D3DCompileFromFile(GetShaderPath(L"Colored.hlsl").data(), nullptr, nullptr, "PShader", "ps_5_0", flags1, 0, &pShaderCode, &errorCode))) { SafeRelease<ID3DBlob>(&pShaderCode); if(errorCode) { OutputDebugStringA((LPCSTR)errorCode->GetBufferPointer()); SafeRelease<ID3DBlob>(&errorCode); } return false; } if(FAILED(this->device->CreatePixelShader(pShaderCode->GetBufferPointer(), pShaderCode->GetBufferSize(), nullptr, &this->colorPShader))) { OutputDebugString("\n create colored pixel shader failed \n"); return false; } if(FAILED(this->device->CreateVertexShader(vShaderCode->GetBufferPointer(), vShaderCode->GetBufferSize(), nullptr, &this->colorVShader))) { OutputDebugString("\n create colored vertex shader failed \n"); return false; } D3D11_INPUT_ELEMENT_DESC colorIEArr[1] = {positionInputElement}; if(FAILED(this->device->CreateInputLayout(colorIEArr, 1, vShaderCode->GetBufferPointer(), vShaderCode->GetBufferSize(), &this->colorInputLayout))) { OutputDebugString("\n create colorIEArr failed \n"); return false; } SafeRelease<ID3DBlob>(&vShaderCode); SafeRelease<ID3DBlob>(&pShaderCode); return true; }
ComputeShader::ComputeShader( Device& _Device, const char* _pShaderFileName, const char* _pShaderCode, D3D_SHADER_MACRO* _pMacros, const char* _pEntryPoint, ID3DInclude* _pIncludeOverride ) : Component( _Device ) , m_pCS( NULL ) , m_pShaderPath( NULL ) #if defined(_DEBUG) || !defined(GODCOMPLEX) , m_LastShaderModificationTime( 0 ) #endif #ifdef COMPUTE_SHADER_COMPILE_THREADED , m_hCompileThread( 0 ) #endif { ASSERT( Shader::ms_LoadFromBinary || _pShaderCode != NULL, "Shader code is NULL!" ); m_pIncludeOverride = _pIncludeOverride; m_bHasErrors = false; // Store the default NULL pointer to point to the shader path #if defined(_DEBUG) || !defined(GODCOMPLEX) m_pShaderFileName = CopyString( _pShaderFileName ); #endif #ifndef GODCOMPLEX m_pShaderPath = GetShaderPath( _pShaderFileName ); m_Pointer2FileName.Add( NULL, m_pShaderPath ); #endif #if defined(_DEBUG) && defined(WATCH_SHADER_MODIFICATIONS) if ( _pShaderFileName != NULL ) { // Just ensure the file exists ! FILE* pFile; fopen_s( &pFile, _pShaderFileName, "rb" ); ASSERT( pFile != NULL, "Compute Shader file not found => You can ignore this assert but compute shader file will NOT be watched for modification!" ); fclose( pFile ); // Register as a watched shader ms_WatchedShaders.Add( _pShaderFileName, this ); #ifndef COMPUTE_SHADER_COMPILE_AT_RUNTIME m_LastShaderModificationTime = GetFileModTime( _pShaderFileName ); #endif } #endif m_pEntryPointCS = _pEntryPoint; if ( _pMacros != NULL ) { D3D_SHADER_MACRO* pMacro = _pMacros; while ( pMacro->Name != NULL ) pMacro++; int MacrosCount = int( 1 + pMacro - _pMacros ); m_pMacros = new D3D_SHADER_MACRO[MacrosCount]; memcpy( m_pMacros, _pMacros, MacrosCount*sizeof(D3D_SHADER_MACRO) ); } else m_pMacros = NULL; #ifdef COMPUTE_SHADER_COMPILE_THREADED // Create the mutex for compilation exclusivity m_hCompileMutex = CreateMutexA( NULL, false, m_pShaderFileName ); if ( m_hCompileMutex == NULL ) m_hCompileMutex = OpenMutexA( SYNCHRONIZE, false, m_pShaderFileName ); // Try and reuse any existing mutex ASSERT( m_hCompileMutex != 0, "Failed to create compilation mutex!" ); #endif #ifndef COMPUTE_SHADER_COMPILE_AT_RUNTIME #ifdef COMPUTE_SHADER_COMPILE_THREADED ASSERT( false, "The COMPUTE_SHADER_COMPILE_THREADED option should only work in pair with the COMPUTE_SHADER_COMPILE_AT_RUNTIME option! (i.e. You CANNOT define COMPUTE_SHADER_COMPILE_THREADED without defining COMPUTE_SHADER_COMPILE_AT_RUNTIME at the same time!)" ); #endif // Compile immediately CompileShaders( _pShaderCode ); #endif }