From 42b99e509eeb2f791b47207f7d00348c0e57ab6b Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 19 Aug 2020 18:55:52 +0300 Subject: Load dxcompiler.dll in runtime --- .../include/ShaderD3DBase.hpp | 8 ++ .../GraphicsEngineD3DBase/src/ShaderD3DBase.cpp | 139 ++++++++++++++++----- 2 files changed, 115 insertions(+), 32 deletions(-) (limited to 'Graphics/GraphicsEngineD3DBase') diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp index cbde6451..ed41bb5f 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp @@ -52,4 +52,12 @@ protected: bool m_isDXIL; }; +#ifdef HAS_D12_DXIL_COMPILER +// calls DxcCreateInstance +HRESULT DXILCreateInstance( + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Out_ LPVOID* ppv); +#endif + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp index 51f8aa5c..604e385a 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp @@ -46,6 +46,43 @@ static const Char* g_HLSLDefinitions = #ifdef HAS_D12_DXIL_COMPILER +struct DXILCompilerLib +{ + HMODULE Module = nullptr; + DxcCreateInstanceProc CreateInstance = nullptr; + + DXILCompilerLib() + { + Module = LoadLibraryA("dxcompiler.dll"); + if (Module) + CreateInstance = reinterpret_cast(GetProcAddress(Module, "DxcCreateInstance")); + } + + ~DXILCompilerLib() + { + FreeLibrary(Module); + } + + static DXILCompilerLib& Instance() + { + static DXILCompilerLib inst; + return inst; + } +}; + +HRESULT DXILCreateInstance( + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Out_ LPVOID* ppv) +{ + auto proc = DXILCompilerLib::Instance().CreateInstance; + if (proc) + return proc(rclsid, riid, ppv); + else + return E_NOTIMPL; +} + + class DxcIncludeHandlerImpl final : public IDxcIncludeHandler { public: @@ -86,7 +123,7 @@ public: m_FileDataCache.push_back(pFileData); - sourceBlob->QueryInterface(__uuidof(*ppIncludeSource), reinterpret_cast(ppIncludeSource)); + sourceBlob->QueryInterface(IID_PPV_ARGS(ppIncludeSource)); return S_OK; } @@ -121,21 +158,59 @@ static HRESULT CompileDxilShader(const char* Source, ID3DBlob** ppBlobOut, ID3DBlob** ppCompilerOutput) { - std::vector unicodeBuffer; - unicodeBuffer.resize(1u << 15); - size_t unicodeBufferOffset = 0; #ifdef HAS_D12_DXIL_COMPILER + if (DXILCompilerLib::Instance().CreateInstance == nullptr) + { + LOG_ERROR("Failed to load dxcompiler.dll"); + return E_FAIL; + } + + struct WStringChunk + { + WCHAR* Buffer; + size_t Size = 0; + size_t Capacity = 0; + + WStringChunk() + { + Capacity = 1u << 12; + Buffer = new WCHAR[Capacity]; + } + + WStringChunk(WStringChunk&& other) : + Buffer{other.Buffer}, Size{other.Size}, Capacity{other.Capacity} + { + other.Buffer = nullptr; + } + + ~WStringChunk() + { + delete[] Buffer; + } + }; + std::vector wstringPool; + + const auto ToUnicode = [&wstringPool](const char* str) { + const auto ConvertString = [](const char* src, WCHAR* dst, size_t len) { + for (size_t i = 0; i < len; ++i) + dst[i] = static_cast(src[i]); + return dst; + }; - const auto ToUnicode = [&unicodeBuffer, &unicodeBufferOffset](const char* str) { auto len = strlen(str) + 1; - auto pos = unicodeBufferOffset; - unicodeBufferOffset += len; - VERIFY(unicodeBufferOffset < unicodeBuffer.size(), "buffer overflow"); - for (size_t i = 0; i < len; ++i) + for (auto& chunk : wstringPool) { - unicodeBuffer[pos + i] = str[i]; + if (chunk.Size + len <= chunk.Capacity) + { + auto pos = chunk.Size; + chunk.Size += len; + return ConvertString(str, chunk.Buffer + pos, len); + } } - return &unicodeBuffer[pos]; + wstringPool.emplace_back(); + auto& chunk = wstringPool.back(); + chunk.Size += len; + return ConvertString(str, chunk.Buffer, len); }; std::vector D3DMacros; @@ -191,12 +266,12 @@ static HRESULT CompileDxilShader(const char* Source, HRESULT hr; CComPtr library; - hr = DxcCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&library)); + hr = DXILCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&library)); if (FAILED(hr)) return hr; CComPtr compiler; - hr = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); + hr = DXILCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); if (FAILED(hr)) return hr; @@ -210,9 +285,9 @@ static HRESULT CompileDxilShader(const char* Source, L"-Zpc", // Matrices in column-major order L"-WX", // Warnings as errors # ifdef DILIGENT_DEBUG - L"-Zi", // Debug info - //L"-Qembed_debug", // Embed debug info into the shader (some compilers do not recognize this flag) - L"-Od", // Disable optimization + L"-Zi", // Debug info + L"-Qembed_debug", // Embed debug info into the shader (some compilers do not recognize this flag) + L"-Od", // Disable optimization # else L"-O3", // Optimization level 3 # endif @@ -238,19 +313,18 @@ static HRESULT CompileDxilShader(const char* Source, hr = status; } - if (FAILED(hr)) + if (result) { - if (result) + CComPtr errorsBlob; + if (SUCCEEDED(result->GetErrorBuffer(&errorsBlob))) { - CComPtr errorsBlob; - if (SUCCEEDED(result->GetErrorBuffer(&errorsBlob)) && errorsBlob) - { - errorsBlob->QueryInterface(__uuidof(*ppCompilerOutput), reinterpret_cast(ppCompilerOutput)); - } + errorsBlob->QueryInterface(IID_PPV_ARGS(ppCompilerOutput)); } - return hr; } + if (FAILED(hr)) + return hr; + hr = result->GetResult(reinterpret_cast(ppBlobOut)); return hr; #else @@ -432,7 +506,7 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, const ShaderVersi LOG_ERROR_AND_THROW("Failed to open shader source file"); pSourceStream->ReadBlob(pFileData); // Null terminator is not read from the stream! - auto* FileDataPtr = reinterpret_cast(pFileData->GetDataPtr()); + auto* FileDataPtr = static_cast(pFileData->GetDataPtr()); auto Size = pFileData->GetSize(); ShaderSource.append(FileDataPtr, FileDataPtr + Size / sizeof(*FileDataPtr)); } @@ -447,14 +521,15 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, const ShaderVersi else hr = CompileShader(ShaderSource.c_str(), ShaderCI, strShaderProfile.c_str(), &m_pShaderByteCode, &errors); - const char* CompilerMsg = errors ? static_cast(errors->GetBufferPointer()) : nullptr; - if (CompilerMsg != nullptr && ShaderCI.ppCompilerOutput != nullptr) + const size_t CompilerMsgLen = errors->GetBufferSize(); + const char* CompilerMsg = errors && CompilerMsgLen > 0 ? static_cast(errors->GetBufferPointer()) : nullptr; + + if (CompilerMsg != nullptr && CompilerMsgLen > 0 && ShaderCI.ppCompilerOutput != nullptr) { - auto ErrorMsgLen = strlen(CompilerMsg); - auto* pOutputDataBlob = MakeNewRCObj()(ErrorMsgLen + 1 + ShaderSource.length() + 1); - char* DataPtr = reinterpret_cast(pOutputDataBlob->GetDataPtr()); - memcpy(DataPtr, CompilerMsg, ErrorMsgLen + 1); - memcpy(DataPtr + ErrorMsgLen + 1, ShaderSource.data(), ShaderSource.length() + 1); + auto* pOutputDataBlob = MakeNewRCObj()(CompilerMsgLen + 1 + ShaderSource.length() + 1); + char* DataPtr = static_cast(pOutputDataBlob->GetDataPtr()); + memcpy(DataPtr, CompilerMsg, CompilerMsgLen + 1); + memcpy(DataPtr + CompilerMsgLen + 1, ShaderSource.data(), ShaderSource.length() + 1); pOutputDataBlob->QueryInterface(IID_DataBlob, reinterpret_cast(ShaderCI.ppCompilerOutput)); } -- cgit v1.2.3