From f546087cb597f4096d695e21b3a37a55dbd3c0d3 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Tue, 12 Dec 2017 21:57:52 -0800 Subject: Added option to create shader from bytecode for D3D11 and D3D12 --- .../GraphicsEngineD3DBase/src/ShaderD3DBase.cpp | 105 ++++++++++++--------- 1 file changed, 62 insertions(+), 43 deletions(-) (limited to 'Graphics/GraphicsEngineD3DBase') diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp index a637b6eb..d16d4815 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp @@ -146,55 +146,74 @@ const char* DXShaderProfileToString(SHADER_PROFILE DXProfile) ShaderD3DBase::ShaderD3DBase(const ShaderCreationAttribs &CreationAttribs) { - std::string strShaderProfile; - switch(CreationAttribs.Desc.ShaderType) + if (CreationAttribs.Source || CreationAttribs.FilePath) { - case SHADER_TYPE_VERTEX: strShaderProfile="vs"; break; - case SHADER_TYPE_PIXEL: strShaderProfile="ps"; break; - case SHADER_TYPE_GEOMETRY:strShaderProfile="gs"; break; - case SHADER_TYPE_HULL: strShaderProfile="hs"; break; - case SHADER_TYPE_DOMAIN: strShaderProfile="ds"; break; - case SHADER_TYPE_COMPUTE: strShaderProfile="cs"; break; - - default: UNEXPECTED( "Unknown shader type" ); - } - strShaderProfile += "_"; - auto *pProfileSuffix = DXShaderProfileToString(CreationAttribs.Desc.TargetProfile); - strShaderProfile += pProfileSuffix; + VERIFY(CreationAttribs.ByteCode == nullptr, "'ByteCode' must be null when shader is created from the source code or a file"); + VERIFY(CreationAttribs.ByteCodeSize == 0, "'ByteCodeSize' must be 0 when shader is created from the source code or a file"); - String ShaderSource(g_HLSLDefinitions); - if( CreationAttribs.Source ) - ShaderSource.append( CreationAttribs.Source ); - else - { - VERIFY(CreationAttribs.pShaderSourceStreamFactory, "Input stream factory is null"); - VERIFY(CreationAttribs.FilePath, "File path is null. Either shader source or source file path must be specified."); - RefCntAutoPtr pSourceStream; - CreationAttribs.pShaderSourceStreamFactory->CreateInputStream( CreationAttribs.FilePath, &pSourceStream ); - RefCntAutoPtr pFileData( MakeNewRCObj()(0) ); - if (pSourceStream == nullptr) - LOG_ERROR_AND_THROW("Failed to open shader source file") - pSourceStream->Read( pFileData ); - // Null terminator is not read from the stream! - auto* FileDataPtr = reinterpret_cast( pFileData->GetDataPtr() ); - auto Size = pFileData->GetSize(); - ShaderSource.append( FileDataPtr, FileDataPtr + Size/sizeof(*FileDataPtr) ); - } + std::string strShaderProfile; + switch(CreationAttribs.Desc.ShaderType) + { + case SHADER_TYPE_VERTEX: strShaderProfile="vs"; break; + case SHADER_TYPE_PIXEL: strShaderProfile="ps"; break; + case SHADER_TYPE_GEOMETRY:strShaderProfile="gs"; break; + case SHADER_TYPE_HULL: strShaderProfile="hs"; break; + case SHADER_TYPE_DOMAIN: strShaderProfile="ds"; break; + case SHADER_TYPE_COMPUTE: strShaderProfile="cs"; break; + + default: UNEXPECTED( "Unknown shader type" ); + } + strShaderProfile += "_"; + auto *pProfileSuffix = DXShaderProfileToString(CreationAttribs.Desc.TargetProfile); + strShaderProfile += pProfileSuffix; - const D3D_SHADER_MACRO *pDefines = nullptr; - std::vector D3DMacros; - if( CreationAttribs.Macros ) - { - for( auto* pCurrMacro = CreationAttribs.Macros; pCurrMacro->Name && pCurrMacro->Definition; ++pCurrMacro ) + String ShaderSource(g_HLSLDefinitions); + if (CreationAttribs.Source) { - D3DMacros.push_back( {pCurrMacro->Name, pCurrMacro->Definition} ); + VERIFY(CreationAttribs.FilePath == nullptr, "'FilePath' is expected to be null when shader source code is provided"); + ShaderSource.append(CreationAttribs.Source); + } + else + { + VERIFY(CreationAttribs.pShaderSourceStreamFactory, "Input stream factory is null"); + RefCntAutoPtr pSourceStream; + CreationAttribs.pShaderSourceStreamFactory->CreateInputStream(CreationAttribs.FilePath, &pSourceStream); + RefCntAutoPtr pFileData(MakeNewRCObj()(0)); + if (pSourceStream == nullptr) + LOG_ERROR_AND_THROW("Failed to open shader source file") + pSourceStream->Read(pFileData); + // Null terminator is not read from the stream! + auto* FileDataPtr = reinterpret_cast(pFileData->GetDataPtr()); + auto Size = pFileData->GetSize(); + ShaderSource.append(FileDataPtr, FileDataPtr + Size / sizeof(*FileDataPtr)); + } + + const D3D_SHADER_MACRO *pDefines = nullptr; + std::vector D3DMacros; + if (CreationAttribs.Macros) + { + for (auto* pCurrMacro = CreationAttribs.Macros; pCurrMacro->Name && pCurrMacro->Definition; ++pCurrMacro) + { + D3DMacros.push_back({ pCurrMacro->Name, pCurrMacro->Definition }); + } + D3DMacros.push_back({ nullptr, nullptr }); + pDefines = D3DMacros.data(); } - D3DMacros.push_back( {nullptr, nullptr} ); - pDefines = D3DMacros.data(); - } - CHECK_D3D_RESULT_THROW( CompileShader( ShaderSource.c_str(), CreationAttribs.EntryPoint, pDefines, CreationAttribs.pShaderSourceStreamFactory, strShaderProfile.c_str(), &m_pShaderByteCode ), - "Failed to compile the shader"); + VERIFY(CreationAttribs.EntryPoint != nullptr, "Entry point must not be null"); + CHECK_D3D_RESULT_THROW(CompileShader(ShaderSource.c_str(), CreationAttribs.EntryPoint, pDefines, CreationAttribs.pShaderSourceStreamFactory, strShaderProfile.c_str(), &m_pShaderByteCode), + "Failed to compile the shader"); + } + else if (CreationAttribs.ByteCode) + { + VERIFY(CreationAttribs.ByteCodeSize != 0, "ByteCode size must be greater than 0"); + CHECK_D3D_RESULT_THROW(D3DCreateBlob(CreationAttribs.ByteCodeSize, &m_pShaderByteCode), "Failed to create D3D blob"); + memcpy(m_pShaderByteCode->GetBufferPointer(), CreationAttribs.ByteCode, CreationAttribs.ByteCodeSize); + } + else + { + LOG_ERROR_AND_THROW("Shader source must be provided through one of the 'Source', 'FilePath' or 'ByteCode' members") + } } } -- cgit v1.2.3