From 1313de1ab167fe67d14fa2a848946f442491ca11 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Tue, 25 Aug 2020 04:56:42 +0300 Subject: added HLSLTools, HLSL shader compiler refactoring added ShaderCompiler field to ShaderCreateInfo, fixed tests that doesn't compile on DXC, added dxc/WinAdapter.h to fix compilation on linux --- Graphics/GraphicsEngineD3DBase/CMakeLists.txt | 1 + .../include/ShaderD3DBase.hpp | 10 +- .../GraphicsEngineD3DBase/src/ShaderD3DBase.cpp | 307 ++++----------------- 3 files changed, 55 insertions(+), 263 deletions(-) (limited to 'Graphics/GraphicsEngineD3DBase') diff --git a/Graphics/GraphicsEngineD3DBase/CMakeLists.txt b/Graphics/GraphicsEngineD3DBase/CMakeLists.txt index cfdffb0c..dbdd9436 100644 --- a/Graphics/GraphicsEngineD3DBase/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3DBase/CMakeLists.txt @@ -62,6 +62,7 @@ PUBLIC target_link_libraries(Diligent-GraphicsEngineD3DBase PRIVATE Diligent-BuildSettings + Diligent-HLSLTools PUBLIC Diligent-GraphicsEngine Diligent-GraphicsEngineD3DBaseInterface diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp index 899546ce..2667b639 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp @@ -28,8 +28,6 @@ #pragma once #include -#include - #include "Shader.h" /// \file @@ -42,17 +40,11 @@ namespace Diligent class ShaderD3DBase { public: - ShaderD3DBase(const ShaderCreateInfo& ShaderCI, ShaderVersion ShaderModel); + ShaderD3DBase(const ShaderCreateInfo& ShaderCI, ShaderVersion ShaderModel, bool IsD3D12); protected: CComPtr m_pShaderByteCode; bool m_isDXIL; }; -// calls DxcCreateInstance -HRESULT DXILCreateInstance( - _In_ REFCLSID rclsid, - _In_ REFIID riid, - _Out_ LPVOID* ppv); - } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp index f10b4bef..25ea3406 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp @@ -33,170 +33,28 @@ #include "RefCntAutoPtr.hpp" #include #include "ShaderD3DBase.hpp" +#include "DXILUtils.hpp" +#include "dxc/dxcapi.h" #include #include namespace Diligent { - -static const Char* g_HLSLDefinitions = - { -#include "HLSLDefinitions_inc.fxh" -}; - - namespace { -struct DXILCompilerLib -{ - HMODULE Module = nullptr; - DxcCreateInstanceProc CreateInstance = nullptr; - ShaderVersion MaxShaderModel{6, 5}; - - DXILCompilerLib() - { - Module = LoadLibraryA("dxcompiler.dll"); - if (Module) - { - CreateInstance = reinterpret_cast(GetProcAddress(Module, "DxcCreateInstance")); - - if (CreateInstance) - { - CComPtr validator; - if (SUCCEEDED(CreateInstance(CLSID_DxcValidator, IID_PPV_ARGS(&validator)))) - { - CComPtr info; - if (SUCCEEDED(validator->QueryInterface(IID_PPV_ARGS(&info)))) - { - UINT32 ver = 0, minor = 0; - info->GetVersion(&ver, &minor); - - LOG_INFO_MESSAGE("Loaded D3D12 DXIL compiler, version ", ver, ".", minor); - - ver = (ver << 16) | (minor & 0xFFFF); - - // map known DXC version to maximum SM - switch (ver) - { - case 0x10005: MaxShaderModel = {6, 5}; break; - case 0x10004: MaxShaderModel = {6, 4}; break; // SM 6.4 and SM 6.5 preview ??? - case 0x10002: MaxShaderModel = {6, 2}; break; // SM 6.1 and SM 6.2 preview - default: MaxShaderModel = (ver > 0x10005 ? ShaderVersion{6, 6} : ShaderVersion{6, 0}); break; // unknown version - } - } - } - } - } - } - - ~DXILCompilerLib() - { - FreeLibrary(Module); - } - - static DXILCompilerLib& Instance() - { - static DXILCompilerLib inst; - return inst; - } -}; -} // namespace - -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; -} - - -namespace -{ -class DxcIncludeHandlerImpl final : public IDxcIncludeHandler -{ -public: - explicit DxcIncludeHandlerImpl(IShaderSourceInputStreamFactory* pStreamFactory, CComPtr pLibrary) : - m_pLibrary{pLibrary}, - m_pStreamFactory{pStreamFactory}, - m_RefCount{1} - { - } - - HRESULT STDMETHODCALLTYPE LoadSource(_In_ LPCWSTR pFilename, _COM_Outptr_result_maybenull_ IDxcBlob** ppIncludeSource) override - { - String fileName = std::wstring_convert, wchar_t>{}.to_bytes(pFilename); - if (fileName.empty()) - { - LOG_ERROR("Failed to convert shader include file name ", fileName, ". File name must be ANSI string"); - return E_FAIL; - } - - RefCntAutoPtr pSourceStream; - m_pStreamFactory->CreateInputStream(fileName.c_str(), &pSourceStream); - if (pSourceStream == nullptr) - { - LOG_ERROR("Failed to open shader include file ", fileName, ". Check that the file exists"); - return E_FAIL; - } - - RefCntAutoPtr pFileData(MakeNewRCObj()(0)); - pSourceStream->ReadBlob(pFileData); - - CComPtr sourceBlob; - HRESULT hr = m_pLibrary->CreateBlobWithEncodingFromPinned(pFileData->GetDataPtr(), UINT32(pFileData->GetSize()), CP_UTF8, &sourceBlob); - if (FAILED(hr)) - { - LOG_ERROR("Failed to allocate space for shader include file ", fileName, "."); - return E_FAIL; - } - - m_FileDataCache.push_back(pFileData); - - sourceBlob->QueryInterface(IID_PPV_ARGS(ppIncludeSource)); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override - { - return E_FAIL; - } - - ULONG STDMETHODCALLTYPE AddRef(void) override - { - return m_RefCount++; - } - ULONG STDMETHODCALLTYPE Release(void) override +static const Char* g_HLSLDefinitions = { - --m_RefCount; - VERIFY(m_RefCount > 0, "Inconsistent call to Release()"); - return m_RefCount; - } - -private: - CComPtr m_pLibrary; - IShaderSourceInputStreamFactory* m_pStreamFactory; - ULONG m_RefCount; - std::vector> m_FileDataCache; +#include "HLSLDefinitions_inc.fxh" }; static HRESULT CompileDxilShader(const char* Source, + size_t SourceLength, const ShaderCreateInfo& ShaderCI, LPCSTR profile, ID3DBlob** ppBlobOut, ID3DBlob** ppCompilerOutput) { - if (DXILCompilerLib::Instance().CreateInstance == nullptr) - { - LOG_ERROR("Failed to load dxcompiler.dll"); - return E_FAIL; - } - struct WStringChunk { WCHAR* Buffer; @@ -295,23 +153,6 @@ static HRESULT CompileDxilShader(const char* Source, } } - HRESULT hr; - - CComPtr library; - hr = DXILCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&library)); - if (FAILED(hr)) - return E_FAIL; - - CComPtr compiler; - hr = DXILCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); - if (FAILED(hr)) - return E_FAIL; - - CComPtr sourceBlob; - hr = library->CreateBlobWithEncodingFromPinned(Source, UINT32(strlen(Source)), CP_UTF8, &sourceBlob); - if (FAILED(hr)) - return E_FAIL; - const wchar_t* pArgs[] = { L"-Zpc", // Matrices in column-major order @@ -325,79 +166,23 @@ static HRESULT CompileDxilShader(const char* Source, #endif }; - DxcIncludeHandlerImpl IncludeHandler{ShaderCI.pShaderSourceStreamFactory, library}; - - CComPtr result; - hr = compiler->Compile( - sourceBlob, - L"", - ToUnicode(ShaderCI.EntryPoint), - ToUnicode(profile), - pArgs, UINT32(std::size(pArgs)), - D3DMacros.data(), UINT32(D3DMacros.size()), - &IncludeHandler, - &result); - - if (SUCCEEDED(hr)) - { - HRESULT status; - if (SUCCEEDED(result->GetStatus(&status))) - hr = status; - } - - if (result) - { - CComPtr errorsBlob; - CComPtr errorsBlobUtf8; - if (SUCCEEDED(result->GetErrorBuffer(&errorsBlob)) && SUCCEEDED(library->GetBlobAsUtf8(errorsBlob, &errorsBlobUtf8))) - { - errorsBlobUtf8->QueryInterface(IID_PPV_ARGS(ppCompilerOutput)); - } - } - - if (FAILED(hr)) - return hr; // compilation failed - - CComPtr compiled; - hr = result->GetResult(&compiled); - if (FAILED(hr)) - return E_FAIL; - - CComPtr validator; - hr = DXILCreateInstance(CLSID_DxcValidator, IID_PPV_ARGS(&validator)); - if (FAILED(hr)) - return E_FAIL; - - CComPtr validationResult; - hr = validator->Validate(compiled, DxcValidatorFlags_InPlaceEdit, &validationResult); - - if (FAILED(hr)) - return hr; // validation failed + VERIFY_EXPR(__uuidof(ID3DBlob) == __uuidof(IDxcBlob)); - HRESULT status; - if (SUCCEEDED(validationResult->GetStatus(&status)) && FAILED(status)) + if (!DXILCompile(DXILCompilerTarget::Direct3D12, + Source, SourceLength, + ToUnicode(ShaderCI.EntryPoint), + ToUnicode(profile), + D3DMacros.data(), D3DMacros.size(), + pArgs, std::size(pArgs), + ShaderCI.pShaderSourceStreamFactory, + reinterpret_cast(ppBlobOut), + reinterpret_cast(ppCompilerOutput))) { - CComPtr validationOutput; - CComPtr validationOutputUtf8; - validationResult->GetErrorBuffer(&validationOutput); - library->GetBlobAsUtf8(validationOutput, &validationOutputUtf8); - - size_t ValidationMsgLen = validationOutputUtf8 ? validationOutputUtf8->GetBufferSize() : 0; - const char* ValidationMsg = ValidationMsgLen > 0 ? static_cast(validationOutputUtf8->GetBufferPointer()) : ""; - - LOG_ERROR("Shader validation failed: ", ValidationMsg); return E_FAIL; } - - VERIFY_EXPR(__uuidof(ID3DBlob) == __uuidof(IDxcBlob)); - - *ppBlobOut = reinterpret_cast(compiled.Detach()); return S_OK; } -} // namespace -namespace -{ class D3DIncludeImpl : public ID3DInclude { public: @@ -440,6 +225,7 @@ private: }; static HRESULT CompileShader(const char* Source, + size_t SourceLength, const ShaderCreateInfo& ShaderCI, LPCSTR profile, ID3DBlob** ppBlobOut, @@ -505,8 +291,7 @@ static HRESULT CompileShader(const char* Source, // { D3DIncludeImpl IncludeImpl(ShaderCI.pShaderSourceStreamFactory); - auto SourceLen = strlen(Source); - auto hr = D3DCompile(Source, SourceLen, NULL, D3DMacros.data(), &IncludeImpl, ShaderCI.EntryPoint, profile, dwShaderFlags, 0, ppBlobOut, ppCompilerOutput); + auto hr = D3DCompile(Source, SourceLength, NULL, D3DMacros.data(), &IncludeImpl, ShaderCI.EntryPoint, profile, dwShaderFlags, 0, ppBlobOut, ppCompilerOutput); // if( FAILED(hr) || errors ) // { @@ -525,7 +310,7 @@ static HRESULT CompileShader(const char* Source, } // namespace -ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, ShaderVersion ShaderModel) : +ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, ShaderVersion ShaderModel, bool IsD3D12) : m_isDXIL{false} { if (ShaderCI.Source || ShaderCI.FilePath) @@ -533,6 +318,38 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, ShaderVersion Sha DEV_CHECK_ERR(ShaderCI.ByteCode == nullptr, "'ByteCode' must be null when shader is created from the source code or a file"); DEV_CHECK_ERR(ShaderCI.ByteCodeSize == 0, "'ByteCodeSize' must be 0 when shader is created from the source code or a file"); + // validate compiler type + switch (ShaderCI.ShaderCompiler) + { + // clang-format off + case SHADER_COMPILER_DEFAULT: m_isDXIL = IsD3D12; break; + case SHADER_COMPILER_DXC: m_isDXIL = true; break; + case SHADER_COMPILER_FXC: m_isDXIL = false; break; + // clang-format on + default: UNEXPECTED("Unsupported shader compiler"); m_isDXIL = IsD3D12; + } + + // validate shader model + if (m_isDXIL) + { + ShaderModel = (ShaderModel.Major >= 6 ? ShaderModel : ShaderVersion{6, 0}); + + // clamp to maximum supported version + ShaderVersion MaxSM; + if (DXILGetMaxShaderModel(DXILCompilerTarget::Direct3D12, MaxSM)) + { + if (ShaderModel.Major > MaxSM.Major) + ShaderModel = MaxSM; + + if (ShaderModel.Major == MaxSM.Major && ShaderModel.Minor > MaxSM.Minor) + ShaderModel = MaxSM; + } + } + else + { + ShaderModel = (ShaderModel.Major < 6 ? ShaderModel : (IsD3D12 ? ShaderVersion{5, 1} : ShaderVersion{5, 0})); + } + std::string strShaderProfile; switch (ShaderCI.Desc.ShaderType) { @@ -550,24 +367,6 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, ShaderVersion Sha default: UNEXPECTED("Unknown shader type"); } - if (ShaderModel.Major >= 6) - { - auto& DxilLib = DXILCompilerLib::Instance(); - - m_isDXIL = DxilLib.CreateInstance != nullptr; - - // clamp to maximum supported version - if (ShaderModel.Major > DxilLib.MaxShaderModel.Major || (ShaderModel.Major == DxilLib.MaxShaderModel.Major && ShaderModel.Minor > DxilLib.MaxShaderModel.Minor)) - ShaderModel = DxilLib.MaxShaderModel; - - if (ShaderModel.Major == 0 || ShaderModel.Major < 6) - ShaderModel = DxilLib.MaxShaderModel; - - // if DXIL is not loaded then try to compile as SM 5.1 - if (!m_isDXIL) - ShaderModel = {5, 1}; - } - strShaderProfile += "_"; strShaderProfile += '0' + (ShaderModel.Major % 10); strShaderProfile += "_"; @@ -600,14 +399,14 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, ShaderVersion Sha HRESULT hr; if (m_isDXIL) - hr = CompileDxilShader(ShaderSource.c_str(), ShaderCI, strShaderProfile.c_str(), &m_pShaderByteCode, &errors); + hr = CompileDxilShader(ShaderSource.c_str(), ShaderSource.length(), ShaderCI, strShaderProfile.c_str(), &m_pShaderByteCode, &errors); else - hr = CompileShader(ShaderSource.c_str(), ShaderCI, strShaderProfile.c_str(), &m_pShaderByteCode, &errors); + hr = CompileShader(ShaderSource.c_str(), ShaderSource.length(), ShaderCI, strShaderProfile.c_str(), &m_pShaderByteCode, &errors); const size_t CompilerMsgLen = errors ? errors->GetBufferSize() : 0; const char* CompilerMsg = CompilerMsgLen > 0 ? static_cast(errors->GetBufferPointer()) : nullptr; - if (CompilerMsg != nullptr && CompilerMsgLen > 0 && ShaderCI.ppCompilerOutput != nullptr) + if (CompilerMsg != nullptr && ShaderCI.ppCompilerOutput != nullptr) { auto* pOutputDataBlob = MakeNewRCObj()(CompilerMsgLen + 1 + ShaderSource.length() + 1); char* DataPtr = static_cast(pOutputDataBlob->GetDataPtr()); -- cgit v1.2.3