diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-10-26 04:25:09 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-10-26 04:25:09 +0000 |
| commit | c430a7906d1320172539494e331a823aa52f8ea3 (patch) | |
| tree | 41b2f4d18d39d14c065cc81aa3c6f7ac842926af /Graphics | |
| parent | Fixed https://github.com/DiligentGraphics/DiligentCore/issues/37 (build error... (diff) | |
| parent | Added HLSL definitions to SPIRV compiler + fixed bug in SPIRV shader resources (diff) | |
| download | DiligentCore-c430a7906d1320172539494e331a823aa52f8ea3.tar.gz DiligentCore-c430a7906d1320172539494e331a823aa52f8ea3.zip | |
Merge branch 'hlsl_glslang'
Diffstat (limited to 'Graphics')
16 files changed, 975 insertions, 650 deletions
diff --git a/Graphics/GLSLTools/CMakeLists.txt b/Graphics/GLSLTools/CMakeLists.txt index 71ead9fb..dd4540a8 100644 --- a/Graphics/GLSLTools/CMakeLists.txt +++ b/Graphics/GLSLTools/CMakeLists.txt @@ -13,11 +13,11 @@ set(SOURCE if(VULKAN_SUPPORTED) list(APPEND SOURCE src/SPIRVShaderResources.cpp - src/GLSL2SPIRV.cpp + src/SPIRVUtils.cpp ) list(APPEND INCLUDE include/SPIRVShaderResources.h - include/GLSL2SPIRV.h + include/SPIRVUtils.h ) endif() diff --git a/Graphics/GLSLTools/include/SPIRVShaderResources.h b/Graphics/GLSLTools/include/SPIRVShaderResources.h index 9f825c04..27764816 100644 --- a/Graphics/GLSLTools/include/SPIRVShaderResources.h +++ b/Graphics/GLSLTools/include/SPIRVShaderResources.h @@ -30,7 +30,7 @@ // // m_MemoryBuffer m_TotalResources // | | -// | Uniform Buffers | Storage Buffers | Storage Images | Sampled Images | Atomic Counters | Separate Images | Separate Samplers | Static Samplers | Resource Names | +// | Uniform Buffers | Storage Buffers | Storage Images | Sampled Images | Atomic Counters | Separate Samplers | Separate Images | Static Samplers | Resource Names | #include <memory> #include <vector> @@ -97,16 +97,33 @@ struct SPIRVShaderResourceAttribs const SHADER_VARIABLE_TYPE VarType : VarTypeBits; const Int8 StaticSamplerInd; + static constexpr const Uint32 InvalidSepSmplrOrImgInd = static_cast<Uint32>(-1); + // Used when HLSL shaders are compiled using combined texture samplers. + Uint32 SepSmplrOrImgInd = InvalidSepSmplrOrImgInd; + // Offset in SPIRV words (uint32_t) of binding & descriptor set decorations in SPIRV binary const uint32_t BindingDecorationOffset; const uint32_t DescriptorSetDecorationOffset; + bool ValidSepSamplerAssigned() const + { + VERIFY_EXPR(Type == SeparateImage); + return SepSmplrOrImgInd != InvalidSepSmplrOrImgInd; + } + + bool ValidSepImageAssigned() const + { + VERIFY_EXPR(Type == SeparateSampler); + return SepSmplrOrImgInd != InvalidSepSmplrOrImgInd; + } + SPIRVShaderResourceAttribs(const spirv_cross::Compiler& Compiler, const spirv_cross::Resource& Res, const char* _Name, ResourceType _Type, SHADER_VARIABLE_TYPE _VarType, - Int32 _StaticSamplerInd)noexcept; + Int32 _StaticSamplerInd, + Uint32 _SamplerOrSepImgId = InvalidSepSmplrOrImgInd)noexcept; String GetPrintName(Uint32 ArrayInd)const { @@ -121,12 +138,13 @@ struct SPIRVShaderResourceAttribs return Name; } - bool IsCompatibleWith(const SPIRVShaderResourceAttribs& Attibs)const + bool IsCompatibleWith(const SPIRVShaderResourceAttribs& Attribs)const { - return ArraySize == Attibs.ArraySize && - Type == Attibs.Type && - VarType == Attibs.VarType && - (StaticSamplerInd < 0 && Attibs.StaticSamplerInd < 0 || StaticSamplerInd >= 0 && Attibs.StaticSamplerInd >= 0); + return ArraySize == Attribs.ArraySize && + Type == Attribs.Type && + VarType == Attribs.VarType && + SepSmplrOrImgInd == Attribs.SepSmplrOrImgInd && + (StaticSamplerInd < 0 && Attribs.StaticSamplerInd < 0 || StaticSamplerInd >= 0 && Attribs.StaticSamplerInd >= 0); } }; static_assert(sizeof(SPIRVShaderResourceAttribs) % sizeof(void*) == 0, "Size of SPIRVShaderResourceAttribs struct must be multiple of sizeof(void*)" ); @@ -138,7 +156,8 @@ public: SPIRVShaderResources(IMemoryAllocator& Allocator, IRenderDevice* pRenderDevice, std::vector<uint32_t> spirv_binary, - const ShaderDesc& shaderDesc); + const ShaderDesc& shaderDesc, + const char* CombinedSamplerSuffix); SPIRVShaderResources (const SPIRVShaderResources&) = delete; SPIRVShaderResources (SPIRVShaderResources&&) = delete; @@ -149,43 +168,48 @@ public: using SamplerPtrType = RefCntAutoPtr<ISampler>; - Uint32 GetNumUBs ()const noexcept{ return (m_StorageBufferOffset - 0); } - Uint32 GetNumSBs ()const noexcept{ return (m_StorageImageOffset - m_StorageBufferOffset); } - Uint32 GetNumImgs ()const noexcept{ return (m_SampledImageOffset - m_StorageImageOffset); } - Uint32 GetNumSmplImgs()const noexcept{ return (m_AtomicCounterOffset - m_SampledImageOffset); } - Uint32 GetNumACs ()const noexcept{ return (m_SeparateImageOffset - m_AtomicCounterOffset); } - Uint32 GetNumSepImgs ()const noexcept{ return (m_SeparateSamplerOffset - m_SeparateImageOffset); } - Uint32 GetNumSepSmpls()const noexcept{ return (m_TotalResources - m_SeparateSamplerOffset);} + Uint32 GetNumUBs ()const noexcept{ return (m_StorageBufferOffset - 0); } + Uint32 GetNumSBs ()const noexcept{ return (m_StorageImageOffset - m_StorageBufferOffset); } + Uint32 GetNumImgs ()const noexcept{ return (m_SampledImageOffset - m_StorageImageOffset); } + Uint32 GetNumSmpldImgs()const noexcept{ return (m_AtomicCounterOffset - m_SampledImageOffset); } + Uint32 GetNumACs ()const noexcept{ return (m_SeparateSamplerOffset - m_AtomicCounterOffset); } + Uint32 GetNumSepSmplrs()const noexcept{ return (m_SeparateImageOffset - m_SeparateSamplerOffset);} + Uint32 GetNumSepImgs ()const noexcept{ return (m_TotalResources - m_SeparateImageOffset); } Uint32 GetTotalResources() const noexcept { return m_TotalResources; } Uint32 GetNumStaticSamplers()const noexcept { return m_NumStaticSamplers; } - const SPIRVShaderResourceAttribs& GetUB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); } - const SPIRVShaderResourceAttribs& GetSB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); } - const SPIRVShaderResourceAttribs& GetImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); } - const SPIRVShaderResourceAttribs& GetSmplImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSmplImgs(), m_SampledImageOffset ); } - const SPIRVShaderResourceAttribs& GetAC (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); } - const SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); } - const SPIRVShaderResourceAttribs& GetSepSmpl (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepSmpls(), m_SeparateSamplerOffset); } - const SPIRVShaderResourceAttribs& GetResource(Uint32 n)const noexcept{ return GetResAttribs(n, GetTotalResources(), 0); } + const SPIRVShaderResourceAttribs& GetUB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); } + const SPIRVShaderResourceAttribs& GetSB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); } + const SPIRVShaderResourceAttribs& GetImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); } + const SPIRVShaderResourceAttribs& GetSmpldImg(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); } + const SPIRVShaderResourceAttribs& GetAC (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); } + const SPIRVShaderResourceAttribs& GetSepSmplr(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); } + const SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); } + const SPIRVShaderResourceAttribs& GetResource(Uint32 n)const noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); } + ISampler* GetStaticSampler(const SPIRVShaderResourceAttribs& ResAttribs)const noexcept { if(ResAttribs.StaticSamplerInd < 0) return nullptr; + VERIFY_EXPR(ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); VERIFY(ResAttribs.StaticSamplerInd < m_NumStaticSamplers, "Static sampler index (", ResAttribs.StaticSamplerInd, ") is out of range. Array size: ", m_NumStaticSamplers); auto *ResourceMemoryEnd = reinterpret_cast<SPIRVShaderResourceAttribs*>(m_MemoryBuffer.get()) + m_TotalResources; return reinterpret_cast<SamplerPtrType*>(ResourceMemoryEnd)[ResAttribs.StaticSamplerInd]; } - void CountResources(const SHADER_VARIABLE_TYPE *AllowedVarTypes, - Uint32 NumAllowedTypes, - Uint32& NumUBs, - Uint32& NumSBs, - Uint32& NumImgs, - Uint32& NumSmplImgs, - Uint32& NumACs, - Uint32& NumSepImgs, - Uint32& NumSepSmpls)const noexcept; + struct ResourceCounters + { + Uint32 NumUBs = 0; + Uint32 NumSBs = 0; + Uint32 NumImgs = 0; + Uint32 NumSmpldImgs = 0; + Uint32 NumACs = 0; + Uint32 NumSepSmplrs = 0; + Uint32 NumSepImgs = 0; + }; + ResourceCounters CountResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes)const noexcept; SHADER_TYPE GetShaderType()const noexcept{return m_ShaderType;} @@ -195,8 +219,8 @@ public: typename THandleImg, typename THandleSmplImg, typename THandleAC, - typename THandleSepImg, - typename THandleSepSmpl> + typename THandleSepSmpl, + typename THandleSepImg> void ProcessResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes, THandleUB HandleUB, @@ -204,8 +228,8 @@ public: THandleImg HandleImg, THandleSmplImg HandleSmplImg, THandleAC HandleAC, - THandleSepImg HandleSepImg, - THandleSepSmpl HandleSepSmpl)const + THandleSepSmpl HandleSepSmpl, + THandleSepImg HandleSepImg)const { Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); @@ -230,9 +254,9 @@ public: HandleImg(Img, n); } - for (Uint32 n = 0; n < GetNumSmplImgs(); ++n) + for (Uint32 n = 0; n < GetNumSmpldImgs(); ++n) { - const auto& SmplImg = GetSmplImg(n); + const auto& SmplImg = GetSmpldImg(n); if (IsAllowedType(SmplImg.VarType, AllowedTypeBits)) HandleSmplImg(SmplImg, n); } @@ -244,19 +268,19 @@ public: HandleAC(AC, n); } + for (Uint32 n = 0; n < GetNumSepSmplrs(); ++n) + { + const auto& SepSmpl = GetSepSmplr(n); + if (IsAllowedType(SepSmpl.VarType, AllowedTypeBits)) + HandleSepSmpl(SepSmpl, n); + } + for (Uint32 n = 0; n < GetNumSepImgs(); ++n) { const auto& SepImg = GetSepImg(n); if (IsAllowedType(SepImg.VarType, AllowedTypeBits)) HandleSepImg(SepImg, n); } - - for (Uint32 n = 0; n < GetNumSepSmpls(); ++n) - { - const auto& SepSmpl = GetSepSmpl(n); - if (IsAllowedType(SepSmpl.VarType, AllowedTypeBits)) - HandleSepSmpl(SepSmpl, n); - } } template<typename THandler> @@ -280,17 +304,14 @@ public: //size_t GetHash()const; + const char* GetCombinedSamplerSuffix() const { return m_CombinedSamplerSuffix; } + bool IsUsingCombinedSamplers() const { return m_CombinedSamplerSuffix != nullptr; } + protected: - void Initialize(IMemoryAllocator& Allocator, - Uint32 NumUBs, - Uint32 NumSBs, - Uint32 NumImgs, - Uint32 NumSmplImgs, - Uint32 NumACs, - Uint32 NumSepImgs, - Uint32 NumSepSmpls, - Uint32 NumStaticSamplers, - size_t ResourceNamesPoolSize); + void Initialize(IMemoryAllocator& Allocator, + const ResourceCounters& Counters, + Uint32 NumStaticSamplers, + size_t ResourceNamesPoolSize); __forceinline SPIRVShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset)noexcept { @@ -306,14 +327,15 @@ protected: return reinterpret_cast<SPIRVShaderResourceAttribs*>(m_MemoryBuffer.get())[Offset + n]; } - SPIRVShaderResourceAttribs& GetUB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); } - SPIRVShaderResourceAttribs& GetSB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); } - SPIRVShaderResourceAttribs& GetImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); } - SPIRVShaderResourceAttribs& GetSmplImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSmplImgs(), m_SampledImageOffset ); } - SPIRVShaderResourceAttribs& GetAC (Uint32 n)noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); } - SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); } - SPIRVShaderResourceAttribs& GetSepSmpl (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepSmpls(), m_SeparateSamplerOffset); } - SPIRVShaderResourceAttribs& GetResource(Uint32 n)noexcept{ return GetResAttribs(n, GetTotalResources(), 0); } + SPIRVShaderResourceAttribs& GetUB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); } + SPIRVShaderResourceAttribs& GetSB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); } + SPIRVShaderResourceAttribs& GetImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); } + SPIRVShaderResourceAttribs& GetSmpldImg(Uint32 n)noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); } + SPIRVShaderResourceAttribs& GetAC (Uint32 n)noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); } + SPIRVShaderResourceAttribs& GetSepSmplr(Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); } + SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); } + SPIRVShaderResourceAttribs& GetResource(Uint32 n)noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); } + SamplerPtrType& GetStaticSampler(Uint32 n)noexcept { VERIFY(n < m_NumStaticSamplers, "Static sampler index (", n, ") is out of range. Array size: ", m_NumStaticSamplers); @@ -323,17 +345,19 @@ protected: private: // Memory buffer that holds all resources as continuous chunk of memory: - // | UBs | SBs | StrgImgs | SmplImgs | ACs | SepImgs | SepSamplers | Static Samplers | Resource Names | + // | UBs | SBs | StrgImgs | SmplImgs | ACs | SepSamplers | SepImgs | Static Samplers | Resource Names | std::unique_ptr< void, STDDeleterRawMem<void> > m_MemoryBuffer; StringPool m_ResourceNames; + const char* m_CombinedSamplerSuffix = nullptr; + using OffsetType = Uint16; OffsetType m_StorageBufferOffset = 0; OffsetType m_StorageImageOffset = 0; OffsetType m_SampledImageOffset = 0; OffsetType m_AtomicCounterOffset = 0; - OffsetType m_SeparateImageOffset = 0; OffsetType m_SeparateSamplerOffset = 0; + OffsetType m_SeparateImageOffset = 0; OffsetType m_TotalResources = 0; OffsetType m_NumStaticSamplers = 0; diff --git a/Graphics/GLSLTools/include/GLSL2SPIRV.h b/Graphics/GLSLTools/include/SPIRVUtils.h index 5951af2c..47c33242 100644 --- a/Graphics/GLSLTools/include/GLSL2SPIRV.h +++ b/Graphics/GLSLTools/include/SPIRVUtils.h @@ -32,6 +32,7 @@ namespace Diligent void InitializeGlslang(); void FinalizeGlslang(); -std::vector<unsigned int> GLSLtoSPIRV(const SHADER_TYPE ShaderType, const char* ShaderSource, IDataBlob** ppCompilerOutput); +std::vector<unsigned int> GLSLtoSPIRV(SHADER_TYPE ShaderType, const char* ShaderSource, int SourceCodeLen, IDataBlob** ppCompilerOutput); +std::vector<unsigned int> HLSLtoSPIRV(const ShaderCreationAttribs& Attribs, IDataBlob** ppCompilerOutput); }
\ No newline at end of file diff --git a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp index 45a63b07..524a96c6 100644 --- a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp +++ b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp @@ -26,6 +26,7 @@ #include "spirv_cross.hpp" #include "ShaderBase.h" #include "GraphicsAccessories.h" +#include "StringTools.h" namespace Diligent { @@ -62,35 +63,38 @@ SPIRVShaderResourceAttribs::SPIRVShaderResourceAttribs(const spirv_cross::Compil const char* _Name, ResourceType _Type, SHADER_VARIABLE_TYPE _VarType, - Int32 _StaticSamplerInd)noexcept : - Name(_Name), - ArraySize(GetResourceArraySize<decltype(ArraySize)>(Compiler, Res)), - Type(_Type), - VarType(_VarType), - StaticSamplerInd(static_cast<decltype(StaticSamplerInd)>(_StaticSamplerInd)), - BindingDecorationOffset(GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationBinding)), + Int32 _StaticSamplerInd, + Uint32 _SepSmplrOrImgInd)noexcept : + Name (_Name), + ArraySize (GetResourceArraySize<decltype(ArraySize)>(Compiler, Res)), + Type (_Type), + VarType (_VarType), + StaticSamplerInd (static_cast<decltype(StaticSamplerInd)>(_StaticSamplerInd)), + SepSmplrOrImgInd (_SepSmplrOrImgInd), + BindingDecorationOffset (GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationBinding)), DescriptorSetDecorationOffset(GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationDescriptorSet)) { VERIFY(_StaticSamplerInd >= std::numeric_limits<decltype(StaticSamplerInd)>::min() && _StaticSamplerInd <= std::numeric_limits<decltype(StaticSamplerInd)>::max(), "Static sampler index is out of representable range" ); } -static Int32 FindStaticSampler(const ShaderDesc& shaderDesc, const std::string& SamplerName) +static Int32 FindStaticSampler(const ShaderDesc& shaderDesc, const std::string& SamplerName, const char* SamplerSuffix) { for(Uint32 s=0; s < shaderDesc.NumStaticSamplers; ++s) { const auto& StSam = shaderDesc.StaticSamplers[s]; - if (SamplerName.compare(StSam.SamplerOrTextureName) == 0) + if (StreqSuff(SamplerName.c_str(), StSam.SamplerOrTextureName, SamplerSuffix)) return s; } return -1; } -SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, - IRenderDevice* pRenderDevice, - std::vector<uint32_t> spirv_binary, - const ShaderDesc& shaderDesc) : +SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, + IRenderDevice* pRenderDevice, + std::vector<uint32_t> spirv_binary, + const ShaderDesc& shaderDesc, + const char* CombinedSamplerSuffix) : m_ShaderType(shaderDesc.ShaderType) { // https://github.com/KhronosGroup/SPIRV-Cross/wiki/Reflection-API-user-guide @@ -115,16 +119,20 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, ResourceNamesPoolSize += res.name.length() + 1; } - Initialize(Allocator, - static_cast<Uint32>(resources.uniform_buffers.size()), - static_cast<Uint32>(resources.storage_buffers.size()), - static_cast<Uint32>(resources.storage_images.size()), - static_cast<Uint32>(resources.sampled_images.size()), - static_cast<Uint32>(resources.atomic_counters.size()), - static_cast<Uint32>(resources.separate_images.size()), - static_cast<Uint32>(resources.separate_samplers.size()), - shaderDesc.NumStaticSamplers, - ResourceNamesPoolSize); + if (CombinedSamplerSuffix != nullptr) + { + ResourceNamesPoolSize += strlen(CombinedSamplerSuffix) + 1; + } + + ResourceCounters ResCounters; + ResCounters.NumUBs = static_cast<Uint32>(resources.uniform_buffers.size()); + ResCounters.NumSBs = static_cast<Uint32>(resources.storage_buffers.size()); + ResCounters.NumImgs = static_cast<Uint32>(resources.storage_images.size()); + ResCounters.NumSmpldImgs = static_cast<Uint32>(resources.sampled_images.size()); + ResCounters.NumACs = static_cast<Uint32>(resources.atomic_counters.size()); + ResCounters.NumSepSmplrs = static_cast<Uint32>(resources.separate_samplers.size()); + ResCounters.NumSepImgs = static_cast<Uint32>(resources.separate_images.size()); + Initialize(Allocator, ResCounters, shaderDesc.NumStaticSamplers, ResourceNamesPoolSize); { Uint32 CurrUB = 0; @@ -160,12 +168,12 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, Uint32 CurrSmplImg = 0; for (const auto &SmplImg : resources.sampled_images) { - auto StaticSamplerInd = FindStaticSampler(shaderDesc, SmplImg.name); + auto StaticSamplerInd = FindStaticSampler(shaderDesc, SmplImg.name, nullptr); const auto& type = Compiler.get_type(SmplImg.type_id); auto ResType = type.image.dim == spv::DimBuffer ? SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer : SPIRVShaderResourceAttribs::ResourceType::SampledImage; - new (&GetSmplImg(CurrSmplImg++)) + new (&GetSmpldImg(CurrSmplImg++)) SPIRVShaderResourceAttribs(Compiler, SmplImg, m_ResourceNames.CopyString(SmplImg.name), @@ -173,7 +181,7 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, GetShaderVariableType(SmplImg.name, shaderDesc), StaticSamplerInd); } - VERIFY_EXPR(CurrSmplImg == GetNumSmplImgs()); + VERIFY_EXPR(CurrSmplImg == GetNumSmpldImgs()); } { @@ -211,34 +219,73 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, } { + Uint32 CurrSepSmpl = 0; + for (const auto &SepSam : resources.separate_samplers) + { + auto StaticSamplerInd = FindStaticSampler(shaderDesc, SepSam.name, CombinedSamplerSuffix); + // Use texture or sampler name to derive sampler type + auto VarType = GetShaderVariableType(shaderDesc.DefaultVariableType, shaderDesc.VariableDesc, shaderDesc.NumVariables, + [&](const char* VarName) + { + return StreqSuff(SepSam.name.c_str(), VarName, CombinedSamplerSuffix); + }); + + new (&GetSepSmplr(CurrSepSmpl++)) + SPIRVShaderResourceAttribs(Compiler, + SepSam, + m_ResourceNames.CopyString(SepSam.name), + SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, + VarType, + StaticSamplerInd); + } + VERIFY_EXPR(CurrSepSmpl == GetNumSepSmplrs()); + } + + { Uint32 CurrSepImg = 0; for (const auto &SepImg : resources.separate_images) { - new (&GetSepImg(CurrSepImg++)) + Uint32 SamplerInd = SPIRVShaderResourceAttribs::InvalidSepSmplrOrImgInd; + if (CombinedSamplerSuffix != nullptr) + { + auto NumSepSmpls = GetNumSepSmplrs(); + for (SamplerInd = 0; SamplerInd < NumSepSmpls; ++SamplerInd) + { + auto& SepSmplr = GetSepSmplr(SamplerInd); + if (StreqSuff(SepSmplr.Name, SepImg.name.c_str(), CombinedSamplerSuffix)) + { + SepSmplr.SepSmplrOrImgInd = static_cast<Uint16>(CurrSepImg); + if (SepSmplr.StaticSamplerInd >= 0) + SamplerInd = NumSepSmpls; + break; + } + } + if (SamplerInd == NumSepSmpls) + SamplerInd = SPIRVShaderResourceAttribs::InvalidSepSmplrOrImgInd; + } + auto* pNewSepImg = new (&GetSepImg(CurrSepImg++)) SPIRVShaderResourceAttribs(Compiler, SepImg, m_ResourceNames.CopyString(SepImg.name), SPIRVShaderResourceAttribs::ResourceType::SeparateImage, GetShaderVariableType(SepImg.name, shaderDesc), - -1); + -1, + SamplerInd); + if (pNewSepImg->ValidSepSamplerAssigned()) + { + const auto& SepSmplr = GetSepSmplr(pNewSepImg->SepSmplrOrImgInd); + DEV_CHECK_ERR(SepSmplr.ArraySize == 1 || SepSmplr.ArraySize == pNewSepImg->ArraySize, + "Array size (", SepSmplr.ArraySize,") of separate sampler variable '", + SepSmplr.Name, "' must be one or same as the array size (", pNewSepImg->ArraySize, + ") of separate image variable '", pNewSepImg->Name, "' it is assigned to"); + } } VERIFY_EXPR(CurrSepImg == GetNumSepImgs()); } - + + if (CombinedSamplerSuffix != nullptr) { - Uint32 CurrSepSmpl = 0; - for (const auto &SepSam : resources.separate_samplers) - { - auto StaticSamplerInd = FindStaticSampler(shaderDesc, SepSam.name); - new (&GetSepSmpl(CurrSepSmpl++)) - SPIRVShaderResourceAttribs(Compiler, - SepSam, - m_ResourceNames.CopyString(SepSam.name), - SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, - GetShaderVariableType(SepSam.name, shaderDesc), - StaticSamplerInd); - } - VERIFY_EXPR(CurrSepSmpl == GetNumSepSmpls()); + m_CombinedSamplerSuffix = m_ResourceNames.CopyString(CombinedSamplerSuffix); } VERIFY(m_ResourceNames.GetRemainingSize() == 0, "Names pool must be empty"); @@ -252,7 +299,7 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, //LOG_INFO_MESSAGE(DumpResources()); -#ifdef _DEBUG +#ifdef DEVELOPMENT if (shaderDesc.NumVariables != 0) { for (Uint32 v = 0; v < shaderDesc.NumVariables; ++v) @@ -281,91 +328,87 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, { for (Uint32 s = 0; s < shaderDesc.NumStaticSamplers; ++s) { - bool SamplerFound = false; const auto* SamName = shaderDesc.StaticSamplers[s].SamplerOrTextureName; - for (Uint32 i = 0; i < GetNumSmplImgs(); ++i) + bool SamplerFound = false; + + for (Uint32 i = 0; i < GetNumSmpldImgs(); ++i) { - const auto &SmplImg = GetSmplImg(i); - if (strcmp(SmplImg.Name, SamName) == 0) - { - SamplerFound = true; + const auto& SmplImg = GetSmpldImg(i); + SamplerFound = (strcmp(SmplImg.Name, SamName) == 0); + if (SamplerFound) break; - } } - if(SamplerFound) - continue; - - for (Uint32 i = 0; i < GetNumSepSmpls(); ++i) + if (!SamplerFound) { - const auto &SepSmpl = GetSepSmpl(i); - if (strcmp(SepSmpl.Name, SamName) == 0) + for (Uint32 i = 0; i < GetNumSepSmplrs(); ++i) { - SamplerFound = true; - break; + const auto& SepSmpl = GetSepSmplr(i); + SamplerFound = StreqSuff(SepSmpl.Name, SamName, CombinedSamplerSuffix); + if (SamplerFound) + break; } } if (!SamplerFound) { - LOG_WARNING_MESSAGE("Static sampler '", SamName, "' not found in shader \'", shaderDesc.Name, "'"); + LOG_WARNING_MESSAGE("Static sampler '", SamName, "' not found in shader '", shaderDesc.Name, "'"); } } } + + if (CombinedSamplerSuffix != nullptr) + { + for (Uint32 n=0; n < GetNumSepSmplrs(); ++n) + { + const auto& SepSmplr = GetSepSmplr(n); + if (!SepSmplr.ValidSepImageAssigned()) + LOG_ERROR_MESSAGE("Shader '", shaderDesc.Name, "' uses combined texture samplers, but separate sampler '", SepSmplr.Name, "' is not assigned to any texture"); + } + } #endif } -void SPIRVShaderResources::Initialize(IMemoryAllocator& Allocator, - Uint32 NumUBs, - Uint32 NumSBs, - Uint32 NumImgs, - Uint32 NumSmplImgs, - Uint32 NumACs, - Uint32 NumSepImgs, - Uint32 NumSepSmpls, - Uint32 NumStaticSamplers, - size_t ResourceNamesPoolSize) +void SPIRVShaderResources::Initialize(IMemoryAllocator& Allocator, + const ResourceCounters& Counters, + Uint32 NumStaticSamplers, + size_t ResourceNamesPoolSize) { - static constexpr OffsetType UniformBufferOffset = 0; - - const auto MaxOffset = static_cast<Uint32>(std::numeric_limits<OffsetType>::max()); - VERIFY(UniformBufferOffset + NumUBs <= MaxOffset, "Max offset exceeded"); - m_StorageBufferOffset = UniformBufferOffset + static_cast<OffsetType>(NumUBs); - - VERIFY(m_StorageBufferOffset + NumSBs <= MaxOffset, "Max offset exceeded"); - m_StorageImageOffset = m_StorageBufferOffset + static_cast<OffsetType>(NumSBs); - - VERIFY(m_StorageImageOffset + NumImgs <= MaxOffset, "Max offset exceeded"); - m_SampledImageOffset = m_StorageImageOffset + static_cast<OffsetType>(NumImgs); - - VERIFY(m_SampledImageOffset + NumSmplImgs <= MaxOffset, "Max offset exceeded"); - m_AtomicCounterOffset = m_SampledImageOffset + static_cast<OffsetType>(NumSmplImgs); - - VERIFY(m_AtomicCounterOffset + NumACs <= MaxOffset, "Max offset exceeded"); - m_SeparateImageOffset = m_AtomicCounterOffset + static_cast<OffsetType>(NumACs); - - VERIFY(m_SeparateImageOffset + NumSepImgs <= MaxOffset, "Max offset exceeded"); - m_SeparateSamplerOffset = m_SeparateImageOffset + static_cast<OffsetType>(NumSepImgs); - - VERIFY(m_SeparateSamplerOffset + NumSepSmpls <= MaxOffset, "Max offset exceeded"); - m_TotalResources = m_SeparateSamplerOffset + static_cast<OffsetType>(NumSepSmpls); - - VERIFY(m_NumStaticSamplers <= MaxOffset, "Max offset exceeded"); + Uint32 CurrentOffset = 0; + constexpr Uint32 MaxOffset = std::numeric_limits<OffsetType>::max(); + auto AdvanceOffset = [&CurrentOffset, MaxOffset](Uint32 NumResources) + { + VERIFY(CurrentOffset <= MaxOffset, "Current offser (", CurrentOffset, ") exceeds max allowed value (", MaxOffset, ")"); + auto Offset = static_cast<OffsetType>(CurrentOffset); + CurrentOffset += NumResources; + return Offset; + }; + + auto UniformBufferOffset = AdvanceOffset(Counters.NumUBs); UniformBufferOffset; // To suppress warning + m_StorageBufferOffset = AdvanceOffset(Counters.NumSBs); + m_StorageImageOffset = AdvanceOffset(Counters.NumImgs); + m_SampledImageOffset = AdvanceOffset(Counters.NumSmpldImgs); + m_AtomicCounterOffset = AdvanceOffset(Counters.NumACs); + m_SeparateSamplerOffset = AdvanceOffset(Counters.NumSepSmplrs); + m_SeparateImageOffset = AdvanceOffset(Counters.NumSepImgs); + m_TotalResources = AdvanceOffset(0); + + VERIFY(NumStaticSamplers <= MaxOffset, "Max offset exceeded"); m_NumStaticSamplers = static_cast<OffsetType>(NumStaticSamplers); static_assert(sizeof(SPIRVShaderResourceAttribs) % sizeof(void*) == 0, "Size of SPIRVShaderResourceAttribs struct must be multiple of sizeof(void*)"); static_assert(sizeof(SamplerPtrType) % sizeof(void*) == 0, "Size of SamplerPtrType must be multiple of sizeof(void*)"); - auto MemorySize = m_TotalResources * sizeof(SPIRVShaderResourceAttribs) + - m_NumStaticSamplers * sizeof(SamplerPtrType) + + auto MemorySize = m_TotalResources * sizeof(SPIRVShaderResourceAttribs) + + m_NumStaticSamplers * sizeof(SamplerPtrType) + ResourceNamesPoolSize * sizeof(char); - VERIFY_EXPR(GetNumUBs() == NumUBs); - VERIFY_EXPR(GetNumSBs() == NumSBs); - VERIFY_EXPR(GetNumImgs() == NumImgs); - VERIFY_EXPR(GetNumSmplImgs() == NumSmplImgs); - VERIFY_EXPR(GetNumACs() == NumACs); - VERIFY_EXPR(GetNumSepImgs() == NumSepImgs); - VERIFY_EXPR(GetNumSepSmpls() == NumSepSmpls); + VERIFY_EXPR(GetNumUBs() == Counters.NumUBs); + VERIFY_EXPR(GetNumSBs() == Counters.NumSBs); + VERIFY_EXPR(GetNumImgs() == Counters.NumImgs); + VERIFY_EXPR(GetNumSmpldImgs() == Counters.NumSmpldImgs); + VERIFY_EXPR(GetNumACs() == Counters.NumACs); + VERIFY_EXPR(GetNumSepSmplrs() == Counters.NumSepSmplrs); + VERIFY_EXPR(GetNumSepImgs() == Counters.NumSepImgs); if (MemorySize) { @@ -389,88 +432,83 @@ SPIRVShaderResources::~SPIRVShaderResources() for (Uint32 n = 0; n < GetNumImgs(); ++n) GetImg(n).~SPIRVShaderResourceAttribs(); - for (Uint32 n = 0; n < GetNumSmplImgs(); ++n) - GetSmplImg(n).~SPIRVShaderResourceAttribs(); + for (Uint32 n = 0; n < GetNumSmpldImgs(); ++n) + GetSmpldImg(n).~SPIRVShaderResourceAttribs(); for (Uint32 n = 0; n < GetNumACs(); ++n) GetAC(n).~SPIRVShaderResourceAttribs(); + for (Uint32 n = 0; n < GetNumSepSmplrs(); ++n) + GetSepSmplr(n).~SPIRVShaderResourceAttribs(); + for (Uint32 n = 0; n < GetNumSepImgs(); ++n) GetSepImg(n).~SPIRVShaderResourceAttribs(); - for (Uint32 n = 0; n < GetNumSepSmpls(); ++n) - GetSepSmpl(n).~SPIRVShaderResourceAttribs(); - for (Uint32 n = 0; n < GetNumStaticSamplers(); ++n) GetStaticSampler(n).~SamplerPtrType(); } -void SPIRVShaderResources::CountResources(const SHADER_VARIABLE_TYPE *AllowedVarTypes, - Uint32 NumAllowedTypes, - Uint32& NumUBs, - Uint32& NumSBs, - Uint32& NumImgs, - Uint32& NumSmplImgs, - Uint32& NumACs, - Uint32& NumSepImgs, - Uint32& NumSepSmpls)const noexcept +SPIRVShaderResources::ResourceCounters SPIRVShaderResources::CountResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes)const noexcept { Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - NumUBs = 0; - NumSBs = 0; - NumImgs = 0; - NumSmplImgs = 0; - NumACs = 0; - NumSepImgs = 0; - NumSepSmpls = 0; + ResourceCounters Counters; ProcessResources( AllowedVarTypes, NumAllowedTypes, - [&](const SPIRVShaderResourceAttribs &UB, Uint32) + [&](const SPIRVShaderResourceAttribs& UB, Uint32) { + VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer); VERIFY_EXPR(IsAllowedType(UB.VarType, AllowedTypeBits)); - ++NumUBs; + ++Counters.NumUBs; }, [&](const SPIRVShaderResourceAttribs& SB, Uint32) { + VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::StorageBuffer); VERIFY_EXPR(IsAllowedType(SB.VarType, AllowedTypeBits)); - ++NumSBs; + ++Counters.NumSBs; }, - [&](const SPIRVShaderResourceAttribs &Img, Uint32) + [&](const SPIRVShaderResourceAttribs& Img, Uint32) { + VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer); VERIFY_EXPR(IsAllowedType(Img.VarType, AllowedTypeBits)); - ++NumImgs; + ++Counters.NumImgs; }, - [&](const SPIRVShaderResourceAttribs &SmplImg, Uint32) + [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32) { + VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); VERIFY_EXPR(IsAllowedType(SmplImg.VarType, AllowedTypeBits)); - ++NumSmplImgs; + ++Counters.NumSmpldImgs; }, - [&](const SPIRVShaderResourceAttribs &AC, Uint32) + [&](const SPIRVShaderResourceAttribs& AC, Uint32) { + VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter); VERIFY_EXPR(IsAllowedType(AC.VarType, AllowedTypeBits)); - ++NumACs; + ++Counters.NumACs; }, - [&](const SPIRVShaderResourceAttribs &SepImg, Uint32) + [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) { - VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits)); - ++NumSepImgs; + VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); + VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits)); + ++Counters.NumSepSmplrs; }, - [&](const SPIRVShaderResourceAttribs &SepSmpl, Uint32) + [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) { - VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits)); - ++NumSepSmpls; + VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); + VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits)); + ++Counters.NumSepImgs; } ); + return Counters; } std::string SPIRVShaderResources::DumpResources() { std::stringstream ss; ss << "Resource counters (" << GetTotalResources() << " total):" << std::endl << "UBs: " << GetNumUBs() << "; SBs: " - << GetNumSBs() << "; Imgs: " << GetNumImgs() << "; Smpl Imgs: " << GetNumSmplImgs() << "; ACs: " << GetNumACs() - << "; Sep Imgs: " << GetNumSepImgs() << "; Sep Smpls: " << GetNumSepSmpls() << '.' << std::endl + << GetNumSBs() << "; Imgs: " << GetNumImgs() << "; Smpl Imgs: " << GetNumSmpldImgs() << "; ACs: " << GetNumACs() + << "; Sep Imgs: " << GetNumSepImgs() << "; Sep Smpls: " << GetNumSepSmplrs() << '.' << std::endl << "Num Static Samplers: " << GetNumStaticSamplers() << std::endl << "Resources:"; Uint32 ResNum = 0; @@ -530,17 +568,17 @@ std::string SPIRVShaderResources::DumpResources() ss << std::endl << std::setw(3) << ResNum << " Atomic Cntr "; DumpResource(AC); }, - [&](const SPIRVShaderResourceAttribs &SepImg, Uint32) - { - VERIFY(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage, "Unexpected resource type"); - ss << std::endl << std::setw(3) << ResNum << " Separate Img "; - DumpResource(SepImg); - }, [&](const SPIRVShaderResourceAttribs &SepSmpl, Uint32) { VERIFY(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Unexpected resource type"); ss << std::endl << std::setw(3) << ResNum << " Separate Smpl "; DumpResource(SepSmpl); + }, + [&](const SPIRVShaderResourceAttribs &SepImg, Uint32) + { + VERIFY(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage, "Unexpected resource type"); + ss << std::endl << std::setw(3) << ResNum << " Separate Img "; + DumpResource(SepImg); } ); VERIFY_EXPR(ResNum == GetTotalResources()); @@ -555,10 +593,10 @@ bool SPIRVShaderResources::IsCompatibleWith(const SPIRVShaderResources& Resource if( GetNumUBs() != Resources.GetNumUBs() || GetNumSBs() != Resources.GetNumSBs() || GetNumImgs() != Resources.GetNumImgs() || - GetNumSmplImgs() != Resources.GetNumSmplImgs() || + GetNumSmpldImgs() != Resources.GetNumSmpldImgs() || GetNumACs() != Resources.GetNumACs() || GetNumSepImgs() != Resources.GetNumSepImgs() || - GetNumSepSmpls() != Resources.GetNumSepSmpls() || + GetNumSepSmplrs() != Resources.GetNumSepSmplrs() || GetNumStaticSamplers() != Resources.GetNumStaticSamplers() ) return false; VERIFY_EXPR(GetTotalResources() == Resources.GetTotalResources()); diff --git a/Graphics/GLSLTools/src/GLSL2SPIRV.cpp b/Graphics/GLSLTools/src/SPIRVUtils.cpp index 5ee3d685..a45eaf76 100644 --- a/Graphics/GLSLTools/src/GLSL2SPIRV.cpp +++ b/Graphics/GLSLTools/src/SPIRVUtils.cpp @@ -21,6 +21,11 @@ * of the possibility of such damages. */ +#include <unordered_set> +#include <unordered_map> +#include <memory> +#include <array> + #if PLATFORM_ANDROID // Android specific include files. # include <unordered_map> @@ -36,9 +41,15 @@ # include "SPIRV/GlslangToSpv.h" #endif -#include "GLSL2SPIRV.h" +#include "SPIRVUtils.h" #include "DebugUtilities.h" #include "DataBlobImpl.h" +#include "RefCntAutoPtr.h" + +static const char g_HLSLDefinitions[] = +{ + #include "../../GraphicsEngineD3DBase/include/HLSLDefinitions_inc.fxh" +}; namespace Diligent { @@ -161,6 +172,16 @@ TBuiltInResource InitResources() Resources.maxCullDistances = 8; Resources.maxCombinedClipAndCullDistances = 8; Resources.maxSamples = 4; + Resources.maxMeshOutputVerticesNV = 256; + Resources.maxMeshOutputPrimitivesNV = 512; + Resources.maxMeshWorkGroupSizeX_NV = 32; + Resources.maxMeshWorkGroupSizeY_NV = 1; + Resources.maxMeshWorkGroupSizeZ_NV = 1; + Resources.maxTaskWorkGroupSizeX_NV = 32; + Resources.maxTaskWorkGroupSizeY_NV = 1; + Resources.maxTaskWorkGroupSizeZ_NV = 1; + Resources.maxMeshViewCountNV = 4; + Resources.limits.nonInductiveForLoops = 1; Resources.limits.whileLoops = 1; Resources.limits.doWhileLoops = 1; @@ -268,57 +289,46 @@ public: } }; -static void InitializeCompilerOutputBlob(const char* ShaderSource, const std::string& ErrorLog, IDataBlob** ppCompilerOutput) +static void LogCompilerError(const char* DebugOutputMessage, + const char* InfoLog, + const char* InfoDebugLog, + const char* ShaderSource, + size_t SourceCodeLen, + IDataBlob** ppCompilerOutput) { - VERIFY_EXPR(ppCompilerOutput != nullptr); - auto SourceLen = strlen(ShaderSource); - auto* pOutputDataBlob = MakeNewRCObj<DataBlobImpl>()(SourceLen + 1 + ErrorLog.length() + 1); - char* DataPtr = reinterpret_cast<char*>(pOutputDataBlob->GetDataPtr()); - memcpy(DataPtr, ErrorLog.data(), ErrorLog.length() + 1); - memcpy(DataPtr + ErrorLog.length() + 1, ShaderSource, SourceLen + 1); - pOutputDataBlob->QueryInterface(IID_DataBlob, reinterpret_cast<IObject**>(ppCompilerOutput)); -} - -std::vector<unsigned int> GLSLtoSPIRV(const SHADER_TYPE ShaderType, const char* ShaderSource, IDataBlob** ppCompilerOutput) -{ -#if PLATFORM_ANDROID - - // On Android, use shaderc instead. - shaderc::Compiler compiler; - shaderc::SpvCompilationResult module = - compiler.CompileGlslToSpv(pshader, strlen(pshader), MapShadercType(shader_type), "shader"); - if (module.GetCompilationStatus() != shaderc_compilation_status_success) { - LOGE("Error: Id=%d, Msg=%s", module.GetCompilationStatus(), module.GetErrorMessage().c_str()); - return false; + std::string ErrorLog(InfoLog); + if (*InfoDebugLog != '\0') + { + ErrorLog.push_back('\n'); + ErrorLog.append(InfoDebugLog); } - std::vector<unsigned int> spirv; - spirv.assign(module.cbegin(), module.cend()); - -#else - - EShLanguage ShLang = ShaderTypeToShLanguage(ShaderType); - glslang::TShader Shader(ShLang); - TBuiltInResource Resources = InitResources(); + LOG_ERROR_MESSAGE(DebugOutputMessage, ErrorLog); - // Enable SPIR-V and Vulkan rules when parsing GLSL - EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); + if (ppCompilerOutput != nullptr) + { + auto* pOutputDataBlob = MakeNewRCObj<DataBlobImpl>()(SourceCodeLen + 1 + ErrorLog.length() + 1); + char* DataPtr = reinterpret_cast<char*>(pOutputDataBlob->GetDataPtr()); + memcpy(DataPtr, ErrorLog.data(), ErrorLog.length() + 1); + memcpy(DataPtr + ErrorLog.length() + 1, ShaderSource, SourceCodeLen + 1); + pOutputDataBlob->QueryInterface(IID_DataBlob, reinterpret_cast<IObject**>(ppCompilerOutput)); + } +} - const char* ShaderStrings[] = { ShaderSource }; - Shader.setStrings(ShaderStrings, 1); - +static std::vector<unsigned int> CompileShaderInternal(glslang::TShader& Shader, + EShMessages messages, + glslang::TShader::Includer* pIncluder, + const char* ShaderSource, + size_t SourceCodeLen, + IDataBlob** ppCompilerOutput) +{ Shader.setAutoMapBindings(true); - if (!Shader.parse(&Resources, 100, false, messages)) + TBuiltInResource Resources = InitResources(); + auto ParseResult = pIncluder != nullptr ? + Shader.parse(&Resources, 100, false, messages, *pIncluder) : + Shader.parse(&Resources, 100, false, messages); + if (!ParseResult) { - std::string Log(Shader.getInfoLog()); - if(*Shader.getInfoDebugLog() != '\0') - { - Log.push_back('\n'); - Log.append(Shader.getInfoDebugLog()); - } - LOG_ERROR_MESSAGE("Failed to parse shader source: \n", Log); - if(ppCompilerOutput != nullptr) - InitializeCompilerOutputBlob(ShaderSource, Log, ppCompilerOutput); - + LogCompilerError("Failed to parse shader source: \n", Shader.getInfoLog(), Shader.getInfoDebugLog(), ShaderSource, SourceCodeLen, ppCompilerOutput); return {}; } @@ -326,16 +336,7 @@ std::vector<unsigned int> GLSLtoSPIRV(const SHADER_TYPE ShaderType, const char* Program.addShader(&Shader); if (!Program.link(messages)) { - std::string Log(Shader.getInfoLog()); - if(*Shader.getInfoDebugLog() != '\0') - { - Log.push_back('\n'); - Log.append(Shader.getInfoDebugLog()); - } - LOG_ERROR_MESSAGE("Failed to link program: \n", Log); - if(ppCompilerOutput != nullptr) - InitializeCompilerOutputBlob(ShaderSource, Log, ppCompilerOutput); - + LogCompilerError("Failed to link program: \n", Program.getInfoLog(), Program.getInfoDebugLog(), ShaderSource, SourceCodeLen, ppCompilerOutput); return {}; } @@ -344,10 +345,159 @@ std::vector<unsigned int> GLSLtoSPIRV(const SHADER_TYPE ShaderType, const char* Program.mapIO(&Resovler); std::vector<unsigned int> spirv; - glslang::GlslangToSpv(*Program.getIntermediate(ShLang), spirv); -#endif + glslang::GlslangToSpv(*Program.getIntermediate(Shader.getStage()), spirv); return std::move(spirv); } + +class IncluderImpl : public glslang::TShader::Includer +{ +public: + IncluderImpl(IShaderSourceInputStreamFactory* pInputStreamFactory) : + m_pInputStreamFactory(pInputStreamFactory) + {} + + // For the "system" or <>-style includes; search the "system" paths. + virtual IncludeResult* includeSystem(const char* headerName, + const char* /*includerName*/, + size_t /*inclusionDepth*/) + { + return nullptr; + } + + // For the "local"-only aspect of a "" include. Should not search in the + // "system" paths, because on returning a failure, the parser will + // call includeSystem() to look in the "system" locations. + virtual IncludeResult* includeLocal(const char* headerName, + const char* /*includerName*/, + size_t /*inclusionDepth*/) + { + DEV_CHECK_ERR(m_pInputStreamFactory != nullptr, "The shader source conains #include directives, but no input stream factory was provided"); + RefCntAutoPtr<IFileStream> pSourceStream; + m_pInputStreamFactory->CreateInputStream( headerName, &pSourceStream ); + if( pSourceStream == nullptr ) + { + LOG_ERROR( "Failed to open shader include file \"", headerName, "\". Check that the file exists" ); + return nullptr; + } + + RefCntAutoPtr<IDataBlob> pFileData( MakeNewRCObj<DataBlobImpl>()(0) ); + pSourceStream->Read( pFileData ); + auto* pNewInclude = + new IncludeResult + { + headerName, + reinterpret_cast<const char*>(pFileData->GetDataPtr()), + pFileData->GetSize(), + nullptr + }; + + m_IncludeRes.emplace(pNewInclude); + m_DataBlobs.emplace(pNewInclude, std::move(pFileData)); + return pNewInclude; + } + + // Signals that the parser will no longer use the contents of the + // specified IncludeResult. + virtual void releaseInclude(IncludeResult* IncldRes) + { + m_DataBlobs.erase(IncldRes); + } + +private: + IShaderSourceInputStreamFactory* const m_pInputStreamFactory; + std::unordered_set<std::unique_ptr<IncludeResult>> m_IncludeRes; + std::unordered_map<IncludeResult*, RefCntAutoPtr<IDataBlob>> m_DataBlobs; +}; + +std::vector<unsigned int> HLSLtoSPIRV(const ShaderCreationAttribs& Attribs, IDataBlob** ppCompilerOutput) +{ + EShLanguage ShLang = ShaderTypeToShLanguage(Attribs.Desc.ShaderType); + glslang::TShader Shader(ShLang); + TBuiltInResource Resources = InitResources(); + + EShMessages messages = (EShMessages)(EShMsgReadHlsl | EShMsgHlslLegalization); + + VERIFY_EXPR(Attribs.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL); + + Shader.setEnvInput(glslang::EShSourceHlsl, ShLang, glslang::EShClientVulkan, 100); + Shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); + Shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0); + Shader.setHlslIoMapping(true); + Shader.setSourceEntryPoint(Attribs.EntryPoint); + Shader.setEntryPoint("main"); + + RefCntAutoPtr<IDataBlob> pFileData(MakeNewRCObj<DataBlobImpl>()(0)); + const char* SourceCode = 0; + int SourceCodeLen = 0; + if (Attribs.Source) + { + SourceCode = Attribs.Source; + SourceCodeLen = static_cast<int>(strlen(Attribs.Source)); + } + else + { + VERIFY(Attribs.pShaderSourceStreamFactory, "Input stream factory is null"); + RefCntAutoPtr<IFileStream> pSourceStream; + Attribs.pShaderSourceStreamFactory->CreateInputStream(Attribs.FilePath, &pSourceStream); + if (pSourceStream == nullptr) + LOG_ERROR_AND_THROW("Failed to open shader source file"); + + pSourceStream->Read(pFileData); + SourceCode = reinterpret_cast<char*>(pFileData->GetDataPtr()); + SourceCodeLen = static_cast<int>(pFileData->GetSize()); + } + + int NumShaderStrings = 0; + constexpr size_t MaxShaderStrings = 3; + std::array<const char*, MaxShaderStrings> ShaderStrings; + std::array<int, MaxShaderStrings> ShaderStringLenghts; + + std::string HLSLDefinitions(g_HLSLDefinitions); + ShaderStrings [NumShaderStrings] = HLSLDefinitions.c_str(); + ShaderStringLenghts[NumShaderStrings] = HLSLDefinitions.length(); + ++NumShaderStrings; + + std::string Defines; + if (Attribs.Macros != nullptr) + { + auto* pMacro = Attribs.Macros; + while (pMacro->Name != nullptr && pMacro->Definition != nullptr) + { + Defines += "#define "; + Defines += pMacro->Name; + Defines += ' '; + Defines += pMacro->Definition; + Defines += "\n"; + ++pMacro; + } + ShaderStrings [NumShaderStrings] = Defines.c_str(); + ShaderStringLenghts[NumShaderStrings] = static_cast<int>(Defines.length()); + ++NumShaderStrings; + } + ShaderStrings [NumShaderStrings] = SourceCode; + ShaderStringLenghts[NumShaderStrings] = SourceCodeLen; + ++NumShaderStrings; + Shader.setStringsWithLengths(ShaderStrings.data(), ShaderStringLenghts.data(), NumShaderStrings); + + IncluderImpl Includer(Attribs.pShaderSourceStreamFactory); + return CompileShaderInternal(Shader, messages, &Includer, SourceCode, SourceCodeLen, ppCompilerOutput); +} + +std::vector<unsigned int> GLSLtoSPIRV(const SHADER_TYPE ShaderType, const char* ShaderSource, int SourceCodeLen, IDataBlob** ppCompilerOutput) +{ + EShLanguage ShLang = ShaderTypeToShLanguage(ShaderType); + glslang::TShader Shader(ShLang); + + // Enable SPIR-V and Vulkan rules when parsing GLSL + EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); + + const char* ShaderStrings[] = {ShaderSource }; + int Lenghts[] = {SourceCodeLen}; + Shader.setStringsWithLengths(ShaderStrings, Lenghts, 1); + + return CompileShaderInternal(Shader, messages, nullptr, ShaderSource, SourceCodeLen, ppCompilerOutput); +} + } diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h index 937a992d..3a5bbbe2 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h @@ -211,13 +211,28 @@ public: Uint32 GetVariableIndex(const ShaderVariableD3D11Base& Variable)const; Uint32 GetTotalResourceCount()const { - auto ResourceCount = m_NumCBs + m_NumTexSRVs + m_NumTexUAVs + m_NumBufUAVs + m_NumBufSRVs; + auto ResourceCount = GetNumCBs() + GetNumTexSRVs() + GetNumTexUAVs() + GetNumBufUAVs() + GetNumBufSRVs(); // Do not expose sampler variables when using combined texture samplers if (!m_pResources->IsUsingCombinedTextureSamplers()) - ResourceCount += m_NumSamplers; + ResourceCount += GetNumSamplers(); return ResourceCount; } + Uint32 GetNumCBs() const { return (m_TexSRVsOffset - 0 ) / sizeof(ConstBuffBindInfo);} + Uint32 GetNumTexSRVs() const { return (m_TexUAVsOffset - m_TexSRVsOffset ) / sizeof(TexSRVBindInfo); } + Uint32 GetNumTexUAVs() const { return (m_BuffSRVsOffset - m_TexUAVsOffset ) / sizeof(TexUAVBindInfo) ; } + Uint32 GetNumBufSRVs() const { return (m_BuffUAVsOffset - m_BuffSRVsOffset) / sizeof(BuffSRVBindInfo); } + Uint32 GetNumBufUAVs() const { return (m_SamplerOffset - m_BuffUAVsOffset) / sizeof(BuffUAVBindInfo); } + Uint32 GetNumSamplers() const { return (m_MemorySize - m_SamplerOffset ) / sizeof(SamplerBindInfo); } + + template<typename ResourceType> Uint32 GetNumResources()const; + template<> Uint32 GetNumResources<ConstBuffBindInfo>() const { return GetNumCBs(); } + template<> Uint32 GetNumResources<TexSRVBindInfo> () const { return GetNumTexSRVs(); } + template<> Uint32 GetNumResources<TexUAVBindInfo> () const { return GetNumTexUAVs(); } + template<> Uint32 GetNumResources<BuffSRVBindInfo> () const { return GetNumBufSRVs(); } + template<> Uint32 GetNumResources<BuffUAVBindInfo> () const { return GetNumBufUAVs(); } + template<> Uint32 GetNumResources<SamplerBindInfo> () const { return GetNumSamplers(); } + private: const Char* GetShaderName()const @@ -232,84 +247,40 @@ private: std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer; // Offsets in bytes - Uint16 m_TexSRVsOffset = 0; - Uint16 m_TexUAVsOffset = 0; - Uint16 m_BuffUAVsOffset = 0; - Uint16 m_BuffSRVsOffset = 0; - Uint16 m_SamplerOffset = 0; + using OffsetType = Uint16; + OffsetType m_TexSRVsOffset = 0; + OffsetType m_TexUAVsOffset = 0; + OffsetType m_BuffSRVsOffset = 0; + OffsetType m_BuffUAVsOffset = 0; + OffsetType m_SamplerOffset = 0; + OffsetType m_MemorySize = 0; - Uint8 m_NumCBs = 0; // Max == 14 - Uint8 m_NumTexSRVs = 0; // Max == 128 - Uint8 m_NumTexUAVs = 0; // Max == 8 - Uint8 m_NumBufUAVs = 0; // Max == 8 - Uint8 m_NumBufSRVs = 0; // Max == 128 - Uint8 m_NumSamplers = 0; // Max == 16 - - ConstBuffBindInfo& GetCB(Uint32 cb) - { - VERIFY_EXPR(cb<m_NumCBs); - return reinterpret_cast<ConstBuffBindInfo*>(m_ResourceBuffer.get())[cb]; - } - const ConstBuffBindInfo& GetCB(Uint32 cb)const - { - VERIFY_EXPR(cb<m_NumCBs); - return reinterpret_cast<const ConstBuffBindInfo*>(m_ResourceBuffer.get())[cb]; - } - - TexSRVBindInfo& GetTexSRV(Uint32 t) - { - VERIFY_EXPR(t<m_NumTexSRVs); - return reinterpret_cast<TexSRVBindInfo*>( reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + m_TexSRVsOffset)[t]; - } - const TexSRVBindInfo& GetTexSRV(Uint32 t)const - { - VERIFY_EXPR(t<m_NumTexSRVs); - return reinterpret_cast<const TexSRVBindInfo*>( reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + m_TexSRVsOffset)[t]; - } - - TexUAVBindInfo& GetTexUAV(Uint32 u) - { - VERIFY_EXPR(u < m_NumTexUAVs); - return reinterpret_cast<TexUAVBindInfo*>( reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + m_TexUAVsOffset)[u]; - } - const TexUAVBindInfo& GetTexUAV(Uint32 u)const - { - VERIFY_EXPR(u < m_NumTexUAVs); - return reinterpret_cast<const TexUAVBindInfo*>( reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + m_TexUAVsOffset)[u]; - } - - BuffUAVBindInfo& GetBufUAV(Uint32 u) - { - VERIFY_EXPR(u < m_NumBufUAVs); - return reinterpret_cast<BuffUAVBindInfo*>( reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + m_BuffUAVsOffset)[u]; - } - const BuffUAVBindInfo& GetBufUAV(Uint32 u)const - { - VERIFY_EXPR(u < m_NumBufUAVs); - return reinterpret_cast<const BuffUAVBindInfo*>( reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + m_BuffUAVsOffset)[u]; - } - - BuffSRVBindInfo& GetBufSRV(Uint32 s) - { - VERIFY_EXPR(s < m_NumBufSRVs); - return reinterpret_cast<BuffSRVBindInfo*>( reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + m_BuffSRVsOffset)[s]; - } - const BuffSRVBindInfo& GetBufSRV(Uint32 s)const - { - VERIFY_EXPR(s < m_NumBufSRVs); - return reinterpret_cast<const BuffSRVBindInfo*>( reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + m_BuffSRVsOffset)[s]; - } - - SamplerBindInfo& GetSampler(Uint32 s) + template<typename ResourceType> OffsetType GetResourceOffset()const; + template<> OffsetType GetResourceOffset<ConstBuffBindInfo>() const { return 0; } + template<> OffsetType GetResourceOffset<TexSRVBindInfo> () const { return m_TexSRVsOffset; } + template<> OffsetType GetResourceOffset<TexUAVBindInfo> () const { return m_TexUAVsOffset; } + template<> OffsetType GetResourceOffset<BuffSRVBindInfo> () const { return m_BuffSRVsOffset; } + template<> OffsetType GetResourceOffset<BuffUAVBindInfo> () const { return m_BuffUAVsOffset; } + template<> OffsetType GetResourceOffset<SamplerBindInfo> () const { return m_SamplerOffset; } + + template<typename ResourceType> + ResourceType& GetResource(Uint32 ResIndex) { - VERIFY_EXPR(s < m_NumSamplers); - return reinterpret_cast<SamplerBindInfo*>( reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + m_SamplerOffset)[s]; + VERIFY(ResIndex < GetNumResources<ResourceType>(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources<ResourceType>(), ")"); + auto Offset = GetResourceOffset<ResourceType>(); + return reinterpret_cast<ResourceType*>( reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + Offset)[ResIndex]; } - const SamplerBindInfo& GetSampler(Uint32 s)const + + template<typename ResourceType> + const ResourceType& GetConstResource(Uint32 ResIndex)const { - VERIFY_EXPR(s < m_NumSamplers); - return reinterpret_cast<const SamplerBindInfo*>( reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + m_SamplerOffset)[s]; + VERIFY(ResIndex < GetNumResources<ResourceType>(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources<ResourceType>(), ")"); + auto Offset = GetResourceOffset<ResourceType>(); + return reinterpret_cast<const ResourceType*>( reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + Offset)[ResIndex]; } + + template<typename ResourceType> + IShaderVariable* GetResourceByName( const Char* Name ); template<typename THandleCB, typename THandleTexSRV, @@ -324,22 +295,30 @@ private: THandleBufUAV HandleBufUAV, THandleSampler HandleSampler) { - for (Uint32 cb = 0; cb < m_NumCBs; ++cb) - HandleCB(GetCB(cb)); - for (Uint32 t = 0; t < m_NumTexSRVs; ++t) - HandleTexSRV(GetTexSRV(t)); - for (Uint32 u = 0; u < m_NumTexUAVs; ++u) - HandleTexUAV(GetTexUAV(u)); - for (Uint32 s = 0; s < m_NumBufSRVs; ++s) - HandleBufSRV(GetBufSRV(s)); - for (Uint32 u = 0; u < m_NumBufUAVs; ++u) - HandleBufUAV(GetBufUAV(u)); - for (Uint32 s = 0; s < m_NumSamplers; ++s) - HandleSampler(GetSampler(s)); + for (Uint32 cb = 0; cb < GetNumResources<ConstBuffBindInfo>(); ++cb) + HandleCB(GetResource<ConstBuffBindInfo>(cb)); + + for (Uint32 t = 0; t < GetNumResources<TexSRVBindInfo>(); ++t) + HandleTexSRV(GetResource<TexSRVBindInfo>(t)); + + for (Uint32 u = 0; u < GetNumResources<TexUAVBindInfo>(); ++u) + HandleTexUAV(GetResource<TexUAVBindInfo>(u)); + + for (Uint32 s = 0; s < GetNumResources<BuffSRVBindInfo>(); ++s) + HandleBufSRV(GetResource<BuffSRVBindInfo>(s)); + + for (Uint32 u = 0; u < GetNumResources<BuffUAVBindInfo>(); ++u) + HandleBufUAV(GetResource<BuffUAVBindInfo>(u)); + + for (Uint32 s = 0; s < GetNumResources<SamplerBindInfo>(); ++s) + HandleSampler(GetResource<SamplerBindInfo>(s)); } std::shared_ptr<const ShaderResourcesD3D11> m_pResources; IObject& m_Owner; + + friend class ShaderVariableIndexLocator; + friend class ShaderVariableLocator; }; } diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index 1a175e38..d0e5f982 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -81,14 +81,13 @@ size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D const SHADER_VARIABLE_TYPE* VarTypes,
Uint32 NumVarTypes)
{
- Uint32 NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers;
- SrcResources.CountResources(VarTypes, NumVarTypes, NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers);
- auto MemSize = NumCBs * sizeof(ConstBuffBindInfo) +
- NumTexSRVs * sizeof(TexSRVBindInfo) +
- NumTexUAVs * sizeof(TexUAVBindInfo) +
- NumBufUAVs * sizeof(BuffUAVBindInfo) +
- NumBufSRVs * sizeof(BuffSRVBindInfo) +
- NumSamplers * sizeof(SamplerBindInfo);
+ auto ResCounters = SrcResources.CountResources(VarTypes, NumVarTypes);
+ auto MemSize = ResCounters.NumCBs * sizeof(ConstBuffBindInfo) +
+ ResCounters.NumTexSRVs * sizeof(TexSRVBindInfo) +
+ ResCounters.NumTexUAVs * sizeof(TexUAVBindInfo) +
+ ResCounters.NumBufSRVs * sizeof(BuffSRVBindInfo) +
+ ResCounters.NumBufUAVs * sizeof(BuffUAVBindInfo) +
+ ResCounters.NumSamplers * sizeof(SamplerBindInfo);
return MemSize;
}
@@ -107,37 +106,41 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResources auto AllowedTypeBits = GetAllowedTypeBits(VarTypes, NumVarTypes);
// Count total number of resources of allowed types
- Uint32 NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers;
- m_pResources->CountResources(VarTypes, NumVarTypes, NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers);
+ auto ResCounters = m_pResources->CountResources(VarTypes, NumVarTypes);
// Initialize offsets
- m_TexSRVsOffset = 0 + static_cast<Uint16>( NumCBs * sizeof(ConstBuffBindInfo));
- m_TexUAVsOffset = m_TexSRVsOffset + static_cast<Uint16>( NumTexSRVs * sizeof(TexSRVBindInfo) );
- m_BuffUAVsOffset = m_TexUAVsOffset + static_cast<Uint16>( NumTexUAVs * sizeof(TexUAVBindInfo) );
- m_BuffSRVsOffset = m_BuffUAVsOffset + static_cast<Uint16>( NumBufUAVs * sizeof(BuffUAVBindInfo) );
- m_SamplerOffset = m_BuffSRVsOffset + static_cast<Uint16>( NumBufSRVs * sizeof(BuffSRVBindInfo) );
- auto MemorySize = m_SamplerOffset + NumSamplers * sizeof(SamplerBindInfo) ;
-
- VERIFY_EXPR(MemorySize == GetRequiredMemorySize(*m_pResources, VarTypes, NumVarTypes));
-
- if( MemorySize )
+ size_t CurrentOffset = 0;
+ auto AdvanceOffset = [&CurrentOffset](size_t NumResources)
+ {
+ constexpr size_t MaxOffset = std::numeric_limits<OffsetType>::max();
+ VERIFY(CurrentOffset <= MaxOffset, "Current offser (", CurrentOffset, ") exceeds max allowed value (", MaxOffset, ")");
+ auto Offset = static_cast<OffsetType>(CurrentOffset);
+ CurrentOffset += NumResources;
+ return Offset;
+ };
+
+ auto CBOffset = AdvanceOffset(ResCounters.NumCBs * sizeof(ConstBuffBindInfo)); CBOffset; // To suppress warning
+ m_TexSRVsOffset = AdvanceOffset(ResCounters.NumTexSRVs * sizeof(TexSRVBindInfo) );
+ m_TexUAVsOffset = AdvanceOffset(ResCounters.NumTexUAVs * sizeof(TexUAVBindInfo) );
+ m_BuffSRVsOffset = AdvanceOffset(ResCounters.NumBufSRVs * sizeof(BuffSRVBindInfo) );
+ m_BuffUAVsOffset = AdvanceOffset(ResCounters.NumBufUAVs * sizeof(BuffUAVBindInfo) );
+ m_SamplerOffset = AdvanceOffset(ResCounters.NumSamplers * sizeof(SamplerBindInfo) );
+ m_MemorySize = AdvanceOffset(0);
+
+ VERIFY_EXPR(m_MemorySize == GetRequiredMemorySize(*m_pResources, VarTypes, NumVarTypes));
+
+ if (m_MemorySize)
{
- auto *pRawMem = ALLOCATE(ResLayoutDataAllocator, "Raw memory buffer for shader resource layout resources", MemorySize);
+ auto *pRawMem = ALLOCATE(ResLayoutDataAllocator, "Raw memory buffer for shader resource layout resources", m_MemorySize);
m_ResourceBuffer = std::unique_ptr<void, STDDeleterRawMem<void> >(pRawMem, ResLayoutDataAllocator);
}
- VERIFY_EXPR(NumCBs < 255);
- VERIFY_EXPR(NumTexSRVs < 255);
- VERIFY_EXPR(NumTexUAVs < 255);
- VERIFY_EXPR(NumBufSRVs < 255);
- VERIFY_EXPR(NumBufUAVs < 255);
- VERIFY_EXPR(NumSamplers< 255);
- m_NumCBs = static_cast<Uint8>(NumCBs);
- m_NumTexSRVs = static_cast<Uint8>(NumTexSRVs);
- m_NumTexUAVs = static_cast<Uint8>(NumTexUAVs);
- m_NumBufSRVs = static_cast<Uint8>(NumBufSRVs);
- m_NumBufUAVs = static_cast<Uint8>(NumBufUAVs);
- m_NumSamplers = static_cast<Uint8>(NumSamplers);
+ VERIFY_EXPR(ResCounters.NumCBs == GetNumCBs() );
+ VERIFY_EXPR(ResCounters.NumTexSRVs == GetNumTexSRVs() );
+ VERIFY_EXPR(ResCounters.NumTexUAVs == GetNumTexUAVs() );
+ VERIFY_EXPR(ResCounters.NumBufSRVs == GetNumBufSRVs() );
+ VERIFY_EXPR(ResCounters.NumBufUAVs == GetNumBufUAVs() );
+ VERIFY_EXPR(ResCounters.NumSamplers== GetNumSamplers());
// Current resource index for every resource type
Uint32 cb = 0;
@@ -159,7 +162,7 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResources VERIFY_EXPR( CB.IsAllowedType(AllowedTypeBits) );
// Initialize current CB in place, increment CB counter
- new (&GetCB(cb++)) ConstBuffBindInfo( CB, *this );
+ new (&GetResource<ConstBuffBindInfo>(cb++)) ConstBuffBindInfo( CB, *this );
NumCBSlots = std::max(NumCBSlots, Uint32{CB.BindPoint} + Uint32{CB.BindCount});
},
@@ -171,7 +174,7 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResources if (!Sampler.IsStaticSampler())
{
// Initialize current sampler in place, increment sampler counter
- new (&GetSampler(sam++)) SamplerBindInfo( Sampler, *this );
+ new (&GetResource<SamplerBindInfo>(sam++)) SamplerBindInfo( Sampler, *this );
NumSamplerSlots = std::max(NumSamplerSlots, Uint32{Sampler.BindPoint} + Uint32{Sampler.BindCount});
}
},
@@ -179,7 +182,8 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResources [&](const D3DShaderResourceAttribs& TexSRV, Uint32)
{
VERIFY_EXPR( TexSRV.IsAllowedType(AllowedTypeBits) );
- VERIFY(sam == m_NumSamplers, "All samplers must be initialized before texture SRVs");
+ auto NumSamplers = GetNumSamplers();
+ VERIFY(sam == NumSamplers, "All samplers must be initialized before texture SRVs");
Uint32 AssignedSamplerIndex = TexSRVBindInfo::InvalidSamplerIndex;
if (TexSRV.ValidSamplerAssigned())
@@ -192,18 +196,18 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResources // Do not assign static sampler to texture SRV as it is initialized directly in the shader resource cache
if (!AssignedSamplerAttribs.IsStaticSampler())
{
- for (AssignedSamplerIndex = 0; AssignedSamplerIndex < m_NumSamplers; ++AssignedSamplerIndex)
+ for (AssignedSamplerIndex = 0; AssignedSamplerIndex < NumSamplers; ++AssignedSamplerIndex)
{
- const auto& Sampler = GetSampler(AssignedSamplerIndex);
+ const auto& Sampler = GetResource<SamplerBindInfo>(AssignedSamplerIndex);
if (strcmp(Sampler.Attribs.Name, AssignedSamplerAttribs.Name) == 0)
break;
}
- VERIFY(AssignedSamplerIndex < m_NumSamplers, "Unable to find assigned sampler");
+ VERIFY(AssignedSamplerIndex < NumSamplers, "Unable to find assigned sampler");
}
}
// Initialize tex SRV in place, increment counter of tex SRVs
- new (&GetTexSRV(texSrv++)) TexSRVBindInfo( TexSRV, AssignedSamplerIndex, *this );
+ new (&GetResource<TexSRVBindInfo>(texSrv++)) TexSRVBindInfo( TexSRV, AssignedSamplerIndex, *this );
NumSRVSlots = std::max(NumSRVSlots, Uint32{TexSRV.BindPoint} + Uint32{TexSRV.BindCount});
},
@@ -212,7 +216,7 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResources VERIFY_EXPR( TexUAV.IsAllowedType(AllowedTypeBits) );
// Initialize tex UAV in place, increment counter of tex UAVs
- new (&GetTexUAV(texUav++)) TexUAVBindInfo( TexUAV, *this );
+ new (&GetResource<TexUAVBindInfo>(texUav++)) TexUAVBindInfo( TexUAV, *this );
NumUAVSlots = std::max(NumUAVSlots, Uint32{TexUAV.BindPoint} + Uint32{TexUAV.BindCount});
},
@@ -221,7 +225,7 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResources VERIFY_EXPR(BuffSRV.IsAllowedType(AllowedTypeBits));
// Initialize buff SRV in place, increment counter of buff SRVs
- new (&GetBufSRV(bufSrv++)) BuffSRVBindInfo( BuffSRV, *this );
+ new (&GetResource<BuffSRVBindInfo>(bufSrv++)) BuffSRVBindInfo( BuffSRV, *this );
NumSRVSlots = std::max(NumSRVSlots, Uint32{BuffSRV.BindPoint} + Uint32{BuffSRV.BindCount});
},
@@ -230,17 +234,17 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResources VERIFY_EXPR(BuffUAV.IsAllowedType(AllowedTypeBits));
// Initialize buff UAV in place, increment counter of buff UAVs
- new (&GetBufUAV(bufUav++)) BuffUAVBindInfo( BuffUAV, *this );
+ new (&GetResource<BuffUAVBindInfo>(bufUav++)) BuffUAVBindInfo( BuffUAV, *this );
NumUAVSlots = std::max(NumUAVSlots, Uint32{BuffUAV.BindPoint} + Uint32{BuffUAV.BindCount});
}
);
- VERIFY(cb == m_NumCBs, "Not all CBs are initialized which will cause a crash when dtor is called");
- VERIFY(texSrv == m_NumTexSRVs, "Not all Tex SRVs are initialized which will cause a crash when dtor is called");
- VERIFY(texUav == m_NumTexUAVs, "Not all Tex UAVs are initialized which will cause a crash when dtor is called");
- VERIFY(bufSrv == m_NumBufSRVs, "Not all Buf SRVs are initialized which will cause a crash when dtor is called");
- VERIFY(bufUav == m_NumBufUAVs, "Not all Buf UAVs are initialized which will cause a crash when dtor is called");
- VERIFY(sam == m_NumSamplers, "Not all samplers are initialized which will cause a crash when dtor is called");
+ VERIFY(cb == GetNumCBs(), "Not all CBs are initialized which will cause a crash when dtor is called");
+ VERIFY(texSrv == GetNumTexSRVs(), "Not all Tex SRVs are initialized which will cause a crash when dtor is called");
+ VERIFY(texUav == GetNumTexUAVs(), "Not all Tex UAVs are initialized which will cause a crash when dtor is called");
+ VERIFY(bufSrv == GetNumBufSRVs(), "Not all Buf SRVs are initialized which will cause a crash when dtor is called");
+ VERIFY(bufUav == GetNumBufUAVs(), "Not all Buf UAVs are initialized which will cause a crash when dtor is called");
+ VERIFY(sam == GetNumSamplers(), "Not all samplers are initialized which will cause a crash when dtor is called");
// Shader resource cache in the SRB is initialized by the constructor of ShaderResourceBindingD3D11Impl to
// hold all variable types. The corresponding layout in the SRB is initialized to keep mutable and dynamic
@@ -467,7 +471,7 @@ void ShaderResourceLayoutD3D11::TexSRVBindInfo::BindResource(IDeviceObject* pVie if (ValidSamplerAssigned())
{
- auto& Sampler = m_ParentResLayout.GetSampler(SamplerIndex);
+ auto& Sampler = m_ParentResLayout.GetResource<SamplerBindInfo>(SamplerIndex);
VERIFY(!Sampler.Attribs.IsStaticSampler(), "Static samplers are not assigned to texture SRVs as they are initialized directly in the shader resource cache");
VERIFY_EXPR(Sampler.Attribs.BindCount == Attribs.BindCount || Sampler.Attribs.BindCount == 1);
auto SamplerBindPoint = Sampler.Attribs.BindPoint + (Sampler.Attribs.BindCount != 1 ? ArrayIndex : 0);
@@ -771,34 +775,87 @@ void ShaderResourceLayoutD3D11::BindResources( IResourceMapping* pResourceMappin );
}
+template<typename ResourceType>
+IShaderVariable* ShaderResourceLayoutD3D11::GetResourceByName( const Char* Name )
+{
+ auto NumResources = GetNumResources<ResourceType>();
+ for (Uint32 res = 0; res < NumResources; ++res)
+ {
+ auto& Resource = GetResource<ResourceType>(res);
+ if (strcmp(Resource.Attribs.Name, Name) == 0)
+ return &Resource;
+ }
+
+ return nullptr;
+}
+
IShaderVariable* ShaderResourceLayoutD3D11::GetShaderVariable(const Char* Name)
{
- for (Uint32 cb = 0; cb < m_NumCBs; ++cb)
- if (strcmp(GetCB(cb).Attribs.Name, Name) == 0)
- return &GetCB(cb);
- for (Uint32 t = 0; t < m_NumTexSRVs; ++t)
- if (strcmp(GetTexSRV(t).Attribs.Name, Name) == 0 )
- return &GetTexSRV(t);
- for (Uint32 u = 0; u < m_NumTexUAVs; ++u)
- if (strcmp(GetTexUAV(u).Attribs.Name, Name) == 0 )
- return &GetTexUAV(u);
- for (Uint32 s = 0; s < m_NumBufSRVs; ++s)
- if (strcmp(GetBufSRV(s).Attribs.Name, Name) == 0 )
- return &GetBufSRV(s);
- for (Uint32 u = 0; u < m_NumBufUAVs; ++u)
- if (strcmp(GetBufUAV(u).Attribs.Name, Name) == 0 )
- return &GetBufUAV(u);
-
+ if(auto* pCB = GetResourceByName<ConstBuffBindInfo>(Name))
+ return pCB;
+
+ if(auto* pTexSRV = GetResourceByName<TexSRVBindInfo>(Name))
+ return pTexSRV;
+
+ if(auto* pTexUAV = GetResourceByName<TexUAVBindInfo>(Name))
+ return pTexUAV;
+
+ if(auto* pBuffSRV = GetResourceByName<BuffSRVBindInfo>(Name))
+ return pBuffSRV;
+
+ if(auto* pBuffUAV = GetResourceByName<BuffUAVBindInfo>(Name))
+ return pBuffUAV;
+
if (!m_pResources->IsUsingCombinedTextureSamplers())
{
- for (Uint32 s = 0; s < m_NumSamplers; ++s)
- if (strcmp(GetSampler(s).Attribs.Name, Name) == 0 )
- return &GetSampler(s);
+ if(auto* pSampler = GetResourceByName<SamplerBindInfo>(Name))
+ return pSampler;
}
return nullptr;
}
+class ShaderVariableIndexLocator
+{
+public:
+ ShaderVariableIndexLocator(const ShaderResourceLayoutD3D11& _Layout, const ShaderResourceLayoutD3D11::ShaderVariableD3D11Base& Variable) :
+ Layout (_Layout),
+ VarOffset(reinterpret_cast<const Uint8*>(&Variable) - reinterpret_cast<const Uint8*>(_Layout.m_ResourceBuffer.get()))
+ {}
+
+ template<typename ResourceType>
+ bool TryResource(ShaderResourceLayoutD3D11::OffsetType NextResourceTypeOffset)
+ {
+#ifdef _DEBUG
+ VERIFY(Layout.GetResourceOffset<ResourceType>() >= dbgPreviousResourceOffset, "Resource types are processed out of order!");
+ dbgPreviousResourceOffset = Layout.GetResourceOffset<ResourceType>();
+ VERIFY_EXPR(NextResourceTypeOffset >= Layout.GetResourceOffset<ResourceType>());
+#endif
+ if (VarOffset < NextResourceTypeOffset)
+ {
+ auto RelativeOffset = VarOffset - Layout.GetResourceOffset<ResourceType>();
+ DEV_CHECK_ERR( RelativeOffset % sizeof(ResourceType) == 0, "Offset is not multiple of resource type (", sizeof(ResourceType), ")");
+ Index += static_cast<Uint32>(RelativeOffset / sizeof(ResourceType));
+ return true;
+ }
+ else
+ {
+ Index += Layout.GetNumResources<ResourceType>();
+ return false;
+ }
+ }
+
+ Uint32 GetIndex() const {return Index;}
+
+private:
+ const ShaderResourceLayoutD3D11& Layout;
+ const size_t VarOffset;
+ Uint32 Index = 0;
+#ifdef _DEBUG
+ Uint32 dbgPreviousResourceOffset = 0;
+#endif
+};
+
Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base& Variable)const
{
if (!m_ResourceBuffer)
@@ -806,105 +863,94 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base LOG_ERROR("This shader resource layout does not have resources");
return static_cast<Uint32>(-1);
}
+
+ ShaderVariableIndexLocator IdxLocator(*this, Variable);
+ if (IdxLocator.TryResource<ConstBuffBindInfo>(m_TexSRVsOffset))
+ return IdxLocator.GetIndex();
- auto Offset = reinterpret_cast<const Uint8*>(&Variable) - reinterpret_cast<Uint8*>(m_ResourceBuffer.get());
- Uint32 Index = 0;
- if (Offset < m_TexSRVsOffset)
- {
- DEV_CHECK_ERR(Offset % sizeof(ConstBuffBindInfo) == 0, "Offset is not multiple of sizeof(ConstBuffBindInfo)");
- return Index + static_cast<Uint32>(Offset / sizeof(ConstBuffBindInfo));
- }
- else
- Index += m_NumCBs;
+ if (IdxLocator.TryResource<TexSRVBindInfo>(m_TexUAVsOffset))
+ return IdxLocator.GetIndex();
- if (Offset < m_TexUAVsOffset)
- {
- DEV_CHECK_ERR( (Offset - m_TexSRVsOffset) % sizeof(TexSRVBindInfo) == 0, "Offset is not multiple of sizeof(TexSRVBindInfo)");
- return Index + static_cast<Uint32>((Offset - m_TexSRVsOffset) / sizeof(TexSRVBindInfo));
- }
- else
- Index += m_NumTexSRVs;
+ if (IdxLocator.TryResource<TexUAVBindInfo>(m_BuffSRVsOffset))
+ return IdxLocator.GetIndex();
- if (Offset < m_BuffUAVsOffset)
- {
- DEV_CHECK_ERR( (Offset - m_TexUAVsOffset) % sizeof(TexUAVBindInfo) == 0, "Offset is not multiple of sizeof(TexUAVBindInfo)");
- return Index + static_cast<Uint32>((Offset - m_TexUAVsOffset) / sizeof(TexUAVBindInfo));
- }
- else
- Index += m_NumTexUAVs;
+ if (IdxLocator.TryResource<BuffSRVBindInfo>(m_BuffUAVsOffset))
+ return IdxLocator.GetIndex();
- if (Offset < m_BuffSRVsOffset)
- {
- DEV_CHECK_ERR( (Offset - m_BuffUAVsOffset) % sizeof(BuffUAVBindInfo) == 0, "Offset is not multiple of sizeof(BuffUAVBindInfo)" );
- return Index + static_cast<Uint32>((Offset - m_BuffUAVsOffset) / sizeof(BuffUAVBindInfo));
- }
- else
- Index += m_NumBufUAVs;
+ if (IdxLocator.TryResource<BuffUAVBindInfo>(m_SamplerOffset))
+ return IdxLocator.GetIndex();
- if (Offset < static_cast<std::ptrdiff_t>(m_BuffSRVsOffset + m_NumBufSRVs * sizeof(BuffSRVBindInfo)))
+ if (!m_pResources->IsUsingCombinedTextureSamplers())
{
- DEV_CHECK_ERR( (Offset - m_BuffSRVsOffset) % sizeof(BuffSRVBindInfo) == 0, "Offset is not multiple of sizeof(BuffSRVBindInfo)" );
- return Index + static_cast<Uint32>((Offset - m_BuffSRVsOffset) / sizeof(BuffSRVBindInfo));
+ if (IdxLocator.TryResource<SamplerBindInfo>(m_MemorySize))
+ return IdxLocator.GetIndex();
}
- else
- Index += m_NumBufSRVs;
- if (!m_pResources->IsUsingCombinedTextureSamplers() &&
- Offset < static_cast<std::ptrdiff_t>(m_SamplerOffset + m_NumSamplers * sizeof(SamplerBindInfo)))
+ LOG_ERROR("Failed to get variable index. The variable ", &Variable, " does not belong to this shader resource layout");
+ return static_cast<Uint32>(-1);
+}
+
+class ShaderVariableLocator
+{
+public:
+ ShaderVariableLocator(ShaderResourceLayoutD3D11& _Layout, Uint32 _Index) :
+ Layout(_Layout),
+ Index (_Index)
{
- DEV_CHECK_ERR( (Offset - m_SamplerOffset) % sizeof(SamplerBindInfo) == 0, "Offset is not multiple of sizeof(SamplerBindInfo)" );
- return Index + static_cast<Uint32>((Offset - m_SamplerOffset) / sizeof(SamplerBindInfo));
}
- else
+
+ template<typename ResourceType>
+ IShaderVariable* TryResource()
{
- LOG_ERROR("Failed to get variable index. The variable ", &Variable, " does not belong to this shader resource layout");
- return static_cast<Uint32>(-1);
+#ifdef _DEBUG
+ VERIFY(Layout.GetResourceOffset<ResourceType>() >= dbgPreviousResourceOffset, "Resource types are processed out of order!");
+ dbgPreviousResourceOffset = Layout.GetResourceOffset<ResourceType>();
+#endif
+ auto NumResources = Layout.GetNumResources<ResourceType>();
+ if (Index < NumResources)
+ return &Layout.GetResource<ResourceType>(Index);
+ else
+ {
+ Index -= NumResources;
+ return nullptr;
+ }
}
-}
+
+private:
+ ShaderResourceLayoutD3D11& Layout;
+ Uint32 Index;
+#ifdef _DEBUG
+ Uint32 dbgPreviousResourceOffset = 0;
+#endif
+};
IShaderVariable* ShaderResourceLayoutD3D11::GetShaderVariable( Uint32 Index )
{
- if (Index >= GetTotalResourceCount())
- {
- LOG_ERROR("Invalid resource index ", Index);
- return nullptr;
- }
+ ShaderVariableLocator VarLocator(*this, Index);
- if (Index < m_NumCBs)
- return &GetCB(Index);
- else
- Index -= m_NumCBs;
+ if(auto* pCB = VarLocator.TryResource<ConstBuffBindInfo>())
+ return pCB;
- if (Index < m_NumTexSRVs)
- return &GetTexSRV(Index);
- else
- Index -= m_NumTexSRVs;
-
- if (Index < m_NumTexUAVs)
- return &GetTexUAV(Index);
- else
- Index -= m_NumTexUAVs;
+ if(auto* pTexSRV = VarLocator.TryResource<TexSRVBindInfo>())
+ return pTexSRV;
- if (Index < m_NumBufUAVs)
- return &GetBufUAV(Index);
- else
- Index -= m_NumBufUAVs;
+ if(auto* pTexUAV = VarLocator.TryResource<TexUAVBindInfo>())
+ return pTexUAV;
+
+ if(auto* pBuffSRV = VarLocator.TryResource<BuffSRVBindInfo>())
+ return pBuffSRV;
+
+ if(auto* pBuffUAV = VarLocator.TryResource<BuffUAVBindInfo>())
+ return pBuffUAV;
- if (Index < m_NumBufSRVs)
- return &GetBufSRV(Index);
- else
- Index -= m_NumBufSRVs;
-
if (!m_pResources->IsUsingCombinedTextureSamplers())
{
- if (Index < m_NumSamplers)
- return &GetSampler(Index);
- else
- Index -= m_NumSamplers;
+ if(auto* pSampler = VarLocator.TryResource<SamplerBindInfo>())
+ return pSampler;
}
-
+
auto TotalResCount = GetTotalResourceCount();
- LOG_ERROR(Index + TotalResCount, " is not a valid variable index. Maximum allowed index: ", TotalResCount);
+ LOG_ERROR(Index, " is not a valid variable index. Total resource count: ", TotalResCount);
return nullptr;
}
@@ -944,7 +990,7 @@ do{ \ if (ts.ValidSamplerAssigned())
{
- const auto& Sampler = GetSampler(ts.SamplerIndex);
+ const auto& Sampler = GetConstResource<SamplerBindInfo>(ts.SamplerIndex);
VERIFY_EXPR(Sampler.Attribs.BindCount == ts.Attribs.BindCount || Sampler.Attribs.BindCount == 1);
// Verify that if single sampler is used for all texture array elements, all samplers set in the resource views are consistent
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index 8d167663..c1f29af4 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -271,7 +271,11 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* if (strcmp(Sampler.Attribs.Name, SamplerAttribs.Name) == 0) break; } - VERIFY(SamplerId < SamplerCount, "Unable to find assigned sampler"); + if (SamplerId == SamplerCount) + { + LOG_ERROR("Unable to find sampler '", SamplerAttribs.Name, "' assigned to texture SRV '", TexSRV.Name, "' in the list of already created resources. This seems to be a bug."); + SamplerId = D3D12Resource::InvalidSamplerId; + } VERIFY(SamplerId <= D3D12Resource::MaxSamplerId, "Sampler index excceeds allowed limit"); } } diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h index c053d39e..346917ea 100644 --- a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h +++ b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h @@ -35,6 +35,16 @@ namespace Diligent { + struct D3DShaderResourceCounters + { + Uint32 NumCBs = 0; + Uint32 NumTexSRVs = 0; + Uint32 NumTexUAVs = 0; + Uint32 NumBufSRVs = 0; + Uint32 NumBufUAVs = 0; + Uint32 NumSamplers = 0; + }; + template<typename D3D_SHADER_DESC, typename D3D_SHADER_INPUT_BIND_DESC, typename TShaderReflection, @@ -72,7 +82,7 @@ namespace Diligent const bool UseCombinedTextureSamplers = SamplerSuffix != nullptr; - Uint32 NumCBs = 0, NumTexSRVs = 0, NumTexUAVs = 0, NumBufSRVs = 0, NumBufUAVs = 0, NumSamplers = 0; + D3DShaderResourceCounters RC; size_t ResourceNamesPoolSize = 0; // Number of resources to skip (used for array resources) UINT SkipCount = 1; @@ -174,18 +184,18 @@ namespace Diligent switch( BindingDesc.Type ) { - case D3D_SIT_CBUFFER: ++NumCBs; break; - case D3D_SIT_TBUFFER: UNSUPPORTED( "TBuffers are not supported" ); break; - case D3D_SIT_TEXTURE: ++(BindingDesc.Dimension == D3D_SRV_DIMENSION_BUFFER ? NumBufSRVs : NumTexSRVs); break; - case D3D_SIT_SAMPLER: ++NumSamplers; break; - case D3D_SIT_UAV_RWTYPED: ++(BindingDesc.Dimension == D3D_SRV_DIMENSION_BUFFER ? NumBufUAVs : NumTexUAVs); break; - case D3D_SIT_STRUCTURED: ++NumBufSRVs; break; - case D3D_SIT_UAV_RWSTRUCTURED: ++NumBufUAVs; break; - case D3D_SIT_BYTEADDRESS: ++NumBufSRVs; break; - case D3D_SIT_UAV_RWBYTEADDRESS: ++NumBufUAVs; break; - case D3D_SIT_UAV_APPEND_STRUCTURED: UNSUPPORTED( "Append structured buffers are not supported" ); break; - case D3D_SIT_UAV_CONSUME_STRUCTURED: UNSUPPORTED( "Consume structured buffers are not supported" ); break; - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: UNSUPPORTED( "RW structured buffers with counter are not supported" ); break; + case D3D_SIT_CBUFFER: ++RC.NumCBs; break; + case D3D_SIT_TBUFFER: UNSUPPORTED( "TBuffers are not supported" ); break; + case D3D_SIT_TEXTURE: ++(BindingDesc.Dimension == D3D_SRV_DIMENSION_BUFFER ? RC.NumBufSRVs : RC.NumTexSRVs); break; + case D3D_SIT_SAMPLER: ++RC.NumSamplers; break; + case D3D_SIT_UAV_RWTYPED: ++(BindingDesc.Dimension == D3D_SRV_DIMENSION_BUFFER ? RC.NumBufUAVs : RC.NumTexUAVs); break; + case D3D_SIT_STRUCTURED: ++RC.NumBufSRVs; break; + case D3D_SIT_UAV_RWSTRUCTURED: ++RC.NumBufUAVs; break; + case D3D_SIT_BYTEADDRESS: ++RC.NumBufSRVs; break; + case D3D_SIT_UAV_RWBYTEADDRESS: ++RC.NumBufUAVs; break; + case D3D_SIT_UAV_APPEND_STRUCTURED: UNSUPPORTED( "Append structured buffers are not supported" ); break; + case D3D_SIT_UAV_CONSUME_STRUCTURED: UNSUPPORTED( "Consume structured buffers are not supported" ); break; + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: UNSUPPORTED( "RW structured buffers with counter are not supported" ); break; default: UNEXPECTED("Unexpected resource type"); } ResourceNamesPoolSize += Name.length() + 1; @@ -251,10 +261,10 @@ namespace Diligent } #endif - OnResourcesCounted(NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers, ResourceNamesPoolSize); + OnResourcesCounted(RC, ResourceNamesPoolSize); std::vector<size_t, STDAllocatorRawMem<size_t> > TexSRVInds( STD_ALLOCATOR_RAW_MEM(size_t, GetRawAllocator(), "Allocator for vector<size_t>") ); - TexSRVInds.reserve(NumTexSRVs); + TexSRVInds.reserve(RC.NumTexSRVs); for(size_t ResInd = 0; ResInd < Resources.size(); ++ResInd) { diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h index ec016324..b13e5e18 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h @@ -316,15 +316,8 @@ public: const D3DShaderResourceAttribs& GetBufUAV (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } const D3DShaderResourceAttribs& GetSampler(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } - - void CountResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - Uint32& NumCBs, - Uint32& NumTexSRVs, - Uint32& NumTexUAVs, - Uint32& NumBufSRVs, - Uint32& NumBufUAVs, - Uint32& NumSamplers)const noexcept; + D3DShaderResourceCounters CountResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes)const noexcept; SHADER_TYPE GetShaderType()const noexcept{return m_ShaderType;} @@ -428,14 +421,9 @@ protected: D3DShaderResourceAttribs& GetSampler(Uint32 n)noexcept{ return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } private: - void AllocateMemory(IMemoryAllocator& Allocator, - Uint32 NumCBs, - Uint32 NumTexSRVs, - Uint32 NumTexUAVs, - Uint32 NumBufSRVs, - Uint32 NumBufUAVs, - Uint32 NumSamplers, - size_t ResourceNamesPoolSize); + void AllocateMemory(IMemoryAllocator& Allocator, + const D3DShaderResourceCounters& ResCounters, + size_t ResourceNamesPoolSize); Uint32 FindAssignedSamplerId(const D3DShaderResourceAttribs& TexSRV, const char* SamplerSuffix)const; @@ -472,12 +460,12 @@ void ShaderResources::Initialize(ID3DBlob* pShaderByteCode, LoadD3DShaderResources<D3D_SHADER_DESC, D3D_SHADER_INPUT_BIND_DESC, TShaderReflection>( pShaderByteCode, - [&](Uint32 NumCBs, Uint32 NumTexSRVs, Uint32 NumTexUAVs, Uint32 NumBufSRVs, Uint32 NumBufUAVs, Uint32 NumSamplers, size_t ResourceNamesPoolSize) + [&](const D3DShaderResourceCounters& ResCounters, size_t ResourceNamesPoolSize) { if (CombinedSamplerSuffix != nullptr) ResourceNamesPoolSize += strlen(CombinedSamplerSuffix)+1; - AllocateMemory(GetRawAllocator(), NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers, ResourceNamesPoolSize); + AllocateMemory(GetRawAllocator(), ResCounters, ResourceNamesPoolSize); }, [&](const D3DShaderResourceAttribs& CBAttribs) diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp index 0e70d7fa..177d1f3f 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp @@ -33,7 +33,7 @@ namespace Diligent { -const Char* g_HLSLDefinitions = +static const Char* g_HLSLDefinitions = { #include "HLSLDefinitions_inc.fxh" }; diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 52527697..5b2b2d4e 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -51,42 +51,36 @@ ShaderResources::~ShaderResources() GetSampler(n).~D3DShaderResourceAttribs(); } -void ShaderResources::AllocateMemory(IMemoryAllocator& Allocator, - Uint32 NumCBs, - Uint32 NumTexSRVs, - Uint32 NumTexUAVs, - Uint32 NumBufSRVs, - Uint32 NumBufUAVs, - Uint32 NumSamplers, - size_t ResourceNamesPoolSize) +void ShaderResources::AllocateMemory(IMemoryAllocator& Allocator, + const D3DShaderResourceCounters& ResCounters, + size_t ResourceNamesPoolSize) { - const auto MaxOffset = static_cast<Uint32>(std::numeric_limits<OffsetType>::max()); - VERIFY(NumCBs <= MaxOffset, "Max offset exceeded"); - m_TexSRVOffset = 0 + static_cast<OffsetType>(NumCBs); - - VERIFY(m_TexSRVOffset + NumTexSRVs <= MaxOffset, "Max offset exceeded"); - m_TexUAVOffset = m_TexSRVOffset + static_cast<OffsetType>(NumTexSRVs); - - VERIFY(m_TexUAVOffset + NumTexUAVs <= MaxOffset, "Max offset exceeded"); - m_BufSRVOffset = m_TexUAVOffset + static_cast<OffsetType>(NumTexUAVs); - - VERIFY(m_BufSRVOffset + NumBufSRVs <= MaxOffset, "Max offset exceeded"); - m_BufUAVOffset = m_BufSRVOffset + static_cast<OffsetType>(NumBufSRVs); - - VERIFY(m_BufUAVOffset + NumBufUAVs <= MaxOffset, "Max offset exceeded"); - m_SamplersOffset = m_BufUAVOffset + static_cast<OffsetType>(NumBufUAVs); - - VERIFY(m_SamplersOffset + NumSamplers<= MaxOffset, "Max offset exceeded"); - m_TotalResources = m_SamplersOffset + static_cast<OffsetType>(NumSamplers); + Uint32 CurrentOffset = 0; + auto AdvanceOffset = [&CurrentOffset](Uint32 NumResources) + { + constexpr Uint32 MaxOffset = std::numeric_limits<OffsetType>::max(); + VERIFY(CurrentOffset <= MaxOffset, "Current offser (", CurrentOffset, ") exceeds max allowed value (", MaxOffset, ")"); + auto Offset = static_cast<OffsetType>(CurrentOffset); + CurrentOffset += NumResources; + return Offset; + }; + + auto CBOffset = AdvanceOffset(ResCounters.NumCBs); CBOffset; // To suppress warning + m_TexSRVOffset = AdvanceOffset(ResCounters.NumTexSRVs); + m_TexUAVOffset = AdvanceOffset(ResCounters.NumTexUAVs); + m_BufSRVOffset = AdvanceOffset(ResCounters.NumBufSRVs); + m_BufUAVOffset = AdvanceOffset(ResCounters.NumBufUAVs); + m_SamplersOffset = AdvanceOffset(ResCounters.NumSamplers); + m_TotalResources = AdvanceOffset(0); auto MemorySize = m_TotalResources * sizeof(D3DShaderResourceAttribs) + ResourceNamesPoolSize * sizeof(char); - VERIFY_EXPR(GetNumCBs() == NumCBs); - VERIFY_EXPR(GetNumTexSRV() == NumTexSRVs); - VERIFY_EXPR(GetNumTexUAV() == NumTexUAVs); - VERIFY_EXPR(GetNumBufSRV() == NumBufSRVs); - VERIFY_EXPR(GetNumBufUAV() == NumBufUAVs); - VERIFY_EXPR(GetNumSamplers()== NumSamplers); + VERIFY_EXPR(GetNumCBs() == ResCounters.NumCBs); + VERIFY_EXPR(GetNumTexSRV() == ResCounters.NumTexSRVs); + VERIFY_EXPR(GetNumTexUAV() == ResCounters.NumTexUAVs); + VERIFY_EXPR(GetNumBufSRV() == ResCounters.NumBufSRVs); + VERIFY_EXPR(GetNumBufUAV() == ResCounters.NumBufUAVs); + VERIFY_EXPR(GetNumSamplers()== ResCounters.NumSamplers); if( MemorySize ) { @@ -102,59 +96,50 @@ ShaderResources::ShaderResources(SHADER_TYPE ShaderType): { } -void ShaderResources::CountResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - Uint32& NumCBs, - Uint32& NumTexSRVs, - Uint32& NumTexUAVs, - Uint32& NumBufSRVs, - Uint32& NumBufUAVs, - Uint32& NumSamplers)const noexcept +D3DShaderResourceCounters ShaderResources::CountResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes)const noexcept { auto AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - NumCBs = 0; - NumTexSRVs = 0; - NumTexUAVs = 0; - NumBufSRVs = 0; - NumBufUAVs = 0; - NumSamplers = 0; + D3DShaderResourceCounters Counters; ProcessResources( AllowedVarTypes, NumAllowedTypes, [&](const D3DShaderResourceAttribs& CB, Uint32) { VERIFY_EXPR(CB.IsAllowedType(AllowedTypeBits)); - ++NumCBs; + ++Counters.NumCBs; }, [&](const D3DShaderResourceAttribs& Sam, Uint32) { VERIFY_EXPR(Sam.IsAllowedType(AllowedTypeBits)); // Skip static samplers if (!Sam.IsStaticSampler()) - ++NumSamplers; + ++Counters.NumSamplers; }, [&](const D3DShaderResourceAttribs& TexSRV, Uint32) { VERIFY_EXPR(TexSRV.IsAllowedType(AllowedTypeBits)); - ++NumTexSRVs; + ++Counters.NumTexSRVs; }, [&](const D3DShaderResourceAttribs& TexUAV, Uint32) { VERIFY_EXPR(TexUAV.IsAllowedType(AllowedTypeBits)); - ++NumTexUAVs; + ++Counters.NumTexUAVs; }, [&](const D3DShaderResourceAttribs& BufSRV, Uint32) { VERIFY_EXPR(BufSRV.IsAllowedType(AllowedTypeBits)); - ++NumBufSRVs; + ++Counters.NumBufSRVs; }, [&](const D3DShaderResourceAttribs& BufUAV, Uint32) { VERIFY_EXPR(BufUAV.IsAllowedType(AllowedTypeBits)); - ++NumBufUAVs; + ++Counters.NumBufUAVs; } ); + + return Counters; } diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h index 3ce40f5b..dc72d609 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h @@ -144,9 +144,15 @@ public: VkResource& operator = (const VkResource&) = delete; VkResource& operator = (VkResource&&) = delete; + static constexpr const Uint32 CacheOffsetBits = 24; + static constexpr const Uint32 SamplerIndBits = 8; + static constexpr const Uint32 InvalidSamplerInd = (1 << SamplerIndBits)-1; + const Uint16 Binding; const Uint16 DescriptorSet; - const Uint32 CacheOffset; // Offset from the beginning of the cached descriptor set + const Uint32 CacheOffset : CacheOffsetBits; // Offset from the beginning of the cached descriptor set + const Uint32 SamplerInd : SamplerIndBits; // When using combined texture samplers, index of the separate sampler + // assigned to separate image const SPIRVShaderResourceAttribs& SpirvAttribs; const ShaderResourceLayoutVk& ParentResLayout; @@ -154,15 +160,19 @@ public: const SPIRVShaderResourceAttribs& _SpirvAttribs, uint32_t _Binding, uint32_t _DescriptorSet, - Uint32 _CacheOffset)noexcept : + Uint32 _CacheOffset, + Uint32 _SamplerInd)noexcept : Binding (static_cast<decltype(Binding)>(_Binding)), DescriptorSet (static_cast<decltype(DescriptorSet)>(_DescriptorSet)), CacheOffset (_CacheOffset), + SamplerInd (_SamplerInd), SpirvAttribs (_SpirvAttribs), ParentResLayout (_ParentLayout) { - VERIFY(_Binding <= std::numeric_limits<decltype(Binding)>::max(), "Binding (", _Binding, ") exceeds representable max value", std::numeric_limits<decltype(Binding)>::max() ); - VERIFY(_DescriptorSet <= std::numeric_limits<decltype(DescriptorSet)>::max(), "Descriptor set (", _DescriptorSet, ") exceeds representable max value", std::numeric_limits<decltype(DescriptorSet)>::max()); + VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) ); + VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) ); + VERIFY(_Binding <= std::numeric_limits<decltype(Binding)>::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits<decltype(Binding)>::max() ); + VERIFY(_DescriptorSet <= std::numeric_limits<decltype(DescriptorSet)>::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits<decltype(DescriptorSet)>::max()); } // Checks if a resource is bound in ResourceCache at the given ArrayIndex @@ -193,11 +203,13 @@ public: ShaderResourceCacheVk::Resource& DstRes, VkDescriptorSet vkDescrSet, Uint32 ArrayInd)const; - + + template<typename TCacheSampler> void CacheImage(IDeviceObject* pTexView, ShaderResourceCacheVk::Resource& DstRes, VkDescriptorSet vkDescrSet, - Uint32 ArrayInd)const; + Uint32 ArrayInd, + TCacheSampler CacheSampler)const; void CacheSeparateSampler(IDeviceObject* pSampler, ShaderResourceCacheVk::Resource& DstRes, @@ -242,6 +254,8 @@ public: return Resources[GetResourceOffset(VarType,r)]; } + bool IsUsingSeparateSamplers()const {return !m_pResources->IsUsingCombinedSamplers();} + private: Uint32 GetResourceOffset(SHADER_VARIABLE_TYPE VarType, Uint32 r)const { @@ -276,6 +290,8 @@ private: const SHADER_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes); + Uint32 FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg, Uint32 CurrResourceCount)const; + IObject& m_Owner; const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index fc986cf7..9bc21a7e 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -68,7 +68,7 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes m_pResources->ProcessResources( AllowedVarTypes, NumAllowedTypes, - [&](const SPIRVShaderResourceAttribs &ResAttribs, Uint32) + [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) { VERIFY_EXPR(IsAllowedType(ResAttribs.VarType, AllowedTypeBits)); VERIFY( Uint32{m_NumResources[ResAttribs.VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds max representable value"); @@ -104,13 +104,21 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons m_pResources->ProcessResources( &AllowedVarType, 1, - [&](const SPIRVShaderResourceAttribs &Attribs, Uint32) + [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) { Uint32 Binding = Attribs.Type; Uint32 DescriptorSet = 0; Uint32 CacheOffset = StaticResCacheSize; StaticResCacheSize += Attribs.ArraySize; - ::new (&GetResource(Attribs.VarType, CurrResInd[Attribs.VarType]++)) VkResource(*this, Attribs, Binding, DescriptorSet, CacheOffset); + + Uint32 SamplerInd = VkResource::InvalidSamplerInd; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) + { + // Separate samplers are enumerated before separate images, so the sampler + // assigned to this separate image must already be created. + SamplerInd = FindAssignedSampler(Attribs, CurrResInd[Attribs.VarType]); + } + ::new (&GetResource(Attribs.VarType, CurrResInd[Attribs.VarType]++)) VkResource(*this, Attribs, Binding, DescriptorSet, CacheOffset, SamplerInd); } ); @@ -148,10 +156,11 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, std::unordered_map<Uint32, std::pair<Uint32, Uint32>> dbgBindings_CacheOffsets; #endif - auto AddResource = [&](Uint32 ShaderInd, - ShaderResourceLayoutVk& ResLayout, - const SPIRVShaderResources& Resources, - const SPIRVShaderResourceAttribs& Attribs) + auto AddResource = [&](Uint32 ShaderInd, + ShaderResourceLayoutVk& ResLayout, + const SPIRVShaderResources& Resources, + const SPIRVShaderResourceAttribs& Attribs, + Uint32 SamplerInd = VkResource::InvalidSamplerInd) { Uint32 Binding = 0; Uint32 DescriptorSet = 0; @@ -179,7 +188,7 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, #endif auto& ResInd = CurrResInd[ShaderInd][Attribs.VarType]; - ::new (&ResLayout.GetResource(Attribs.VarType, ResInd++)) VkResource(ResLayout, Attribs, Binding, DescriptorSet, CacheOffset); + ::new (&ResLayout.GetResource(Attribs.VarType, ResInd++)) VkResource(ResLayout, Attribs, Binding, DescriptorSet, CacheOffset, SamplerInd); }; // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set @@ -220,41 +229,48 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, Resources.ProcessResources( AllowedVarTypes, NumAllowedTypes, - [&](const SPIRVShaderResourceAttribs &UB, Uint32) + [&](const SPIRVShaderResourceAttribs& UB, Uint32) { + VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer); VERIFY_EXPR(IsAllowedType(UB.VarType, AllowedTypeBits)); // Skip }, [&](const SPIRVShaderResourceAttribs& SB, Uint32) { + VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::StorageBuffer); VERIFY_EXPR(IsAllowedType(SB.VarType, AllowedTypeBits)); // Skip }, - [&](const SPIRVShaderResourceAttribs &Img, Uint32) + [&](const SPIRVShaderResourceAttribs& Img, Uint32) { + VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer); VERIFY_EXPR(IsAllowedType(Img.VarType, AllowedTypeBits)); AddResource(s, Layout, Resources, Img); }, - [&](const SPIRVShaderResourceAttribs &SmplImg, Uint32) + [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32) { + VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); VERIFY_EXPR(IsAllowedType(SmplImg.VarType, AllowedTypeBits)); AddResource(s, Layout, Resources, SmplImg); }, - [&](const SPIRVShaderResourceAttribs &AC, Uint32) + [&](const SPIRVShaderResourceAttribs& AC, Uint32) { + VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter); VERIFY_EXPR(IsAllowedType(AC.VarType, AllowedTypeBits)); AddResource(s, Layout, Resources, AC); }, - [&](const SPIRVShaderResourceAttribs &SepImg, Uint32) - { - VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits)); - AddResource(s, Layout, Resources, SepImg); - }, - - [&](const SPIRVShaderResourceAttribs &SepSmpl, Uint32) + [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) { + VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits)); AddResource(s, Layout, Resources, SepSmpl); + }, + [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) + { + VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); + VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits)); + Uint32 SamplerInd = Layout.FindAssignedSampler(SepImg, CurrResInd[s][SepImg.VarType]); + AddResource(s, Layout, Resources, SepImg, SamplerInd); } ); } @@ -271,11 +287,43 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, #endif } + +Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg, Uint32 CurrResourceCount)const +{ + VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); + + Uint32 SamplerInd = VkResource::InvalidSamplerInd; + if (m_pResources->IsUsingCombinedSamplers() && SepImg.ValidSepSamplerAssigned()) + { + const auto& SepSampler = m_pResources->GetSepSmplr(SepImg.SepSmplrOrImgInd); + DEV_CHECK_ERR(SepImg.VarType == SepSampler.VarType, + "The type (", GetShaderVariableTypeLiteralName(SepImg.VarType),") of separate image variable '", SepImg.Name, + "' is not consistent with the type (", GetShaderVariableTypeLiteralName(SepSampler.VarType), + ") of the separate sampler '", SepSampler.Name, "' that is assigned to it."); + + for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd) + { + const auto& Res = GetResource(SepSampler.VarType, SamplerInd); + if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0) + { + break; + } + } + if (SamplerInd == CurrResourceCount) + { + LOG_ERROR("Unable to find separate sampler '", SepSampler.Name, "' assigned to separate image '", SepImg.Name, "' in the list of already created resources. This seems to be a bug."); + SamplerInd = VkResource::InvalidSamplerInd; + } + } + return SamplerInd; +} + #define LOG_RESOURCE_BINDING_ERROR(ResType, pResource, VarName, ShaderName, ...)\ -{ \ - const auto &ResName = pResource->GetDesc().Name; \ - LOG_ERROR_MESSAGE( "Failed to bind ", ResType, " \"", ResName, "\" to variable \"", VarName, \ - "\" in shader \"", ShaderName, "\". ", __VA_ARGS__ ); \ +{ \ + const auto &ResName = pResource->GetDesc().Name; \ + LOG_ERROR_MESSAGE( "Failed to bind ", ResType, " '", ResName, "' to variable '", VarName, \ + "' in shader '", ShaderName, "'. ", __VA_ARGS__ ); \ } void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, @@ -319,7 +367,7 @@ bool ShaderResourceLayoutVk::VkResource::UpdateCachedResource(ShaderResourceCach if (DstRes.pObject != pResource) { auto VarTypeStr = GetShaderVariableTypeLiteralName(SpirvAttribs.VarType); - LOG_ERROR_MESSAGE("Non-null resource is already bound to ", VarTypeStr, " shader variable \"", SpirvAttribs.GetPrintName(ArrayInd), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempring to bind another resource is an error and will be ignored. Use another shader resource binding instance or label the variable as dynamic."); + LOG_ERROR_MESSAGE("Non-null resource is already bound to ", VarTypeStr, " shader variable '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "'. Attempring to bind another resource is an error and will be ignored. Use another shader resource binding instance or label the variable as dynamic."); } // Do not update resource if one is already bound unless it is dynamic. This may be @@ -441,20 +489,23 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* } } +template<typename TCacheSampler> void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* pTexView, ShaderResourceCacheVk::Resource& DstRes, VkDescriptorSet vkDescrSet, - Uint32 ArrayInd)const + Uint32 ArrayInd, + TCacheSampler CacheSampler)const { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || + VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage, "Storage image, separate image or sampled image resource is expected"); if (UpdateCachedResource(DstRes, ArrayInd, pTexView, IID_TextureViewVk, "texture view") ) { -#ifdef DEVELOPMENT + // We can do RawPtr here safely since UpdateCachedResource() returned true auto* pTexViewVk = DstRes.pObject.RawPtr<TextureViewVkImpl>(); +#ifdef DEVELOPMENT const auto ViewType = pTexViewVk->GetDesc().ViewType; const bool IsStorageImage = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage; const auto dbgExpectedViewType = IsStorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE; @@ -472,7 +523,7 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* { if(pTexViewVk->GetSampler() == nullptr) { - LOG_RESOURCE_BINDING_ERROR("resource", pTexView, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "No sampler assigned to texture view."); + LOG_RESOURCE_BINDING_ERROR("resource", pTexView, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "No sampler assigned to texture view '", pTexViewVk->GetDesc().Name, "'"); } } #endif @@ -484,6 +535,24 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* VkDescriptorImageInfo DescrImgInfo = DstRes.GetImageDescriptorWriteInfo(SpirvAttribs.StaticSamplerInd >= 0); UpdateDescriptorHandle(vkDescrSet, ArrayInd, &DescrImgInfo, nullptr, nullptr); } + + if (SamplerInd != InvalidSamplerInd) + { + VERIFY_EXPR(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); + VERIFY_EXPR(SpirvAttribs.StaticSamplerInd < 0); + auto* pSampler = pTexViewVk->GetSampler(); + const auto& SamplerAttribs = ParentResLayout.GetResource(SpirvAttribs.VarType, SamplerInd); + if (pSampler != nullptr) + { + CacheSampler(SamplerAttribs, pSampler); + } + else + { + LOG_ERROR_MESSAGE( "Failed to bind sampler to sampler variable '", SamplerAttribs.SpirvAttribs.Name, + "' assigned to separate image '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '", + ParentResLayout.GetShaderName(), "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\''); \ + } + } } } @@ -554,7 +623,17 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3 case SPIRVShaderResourceAttribs::ResourceType::StorageImage: case SPIRVShaderResourceAttribs::ResourceType::SeparateImage: case SPIRVShaderResourceAttribs::ResourceType::SampledImage: - CacheImage(pObj, DstRes, vkDescrSet, ArrayIndex); + CacheImage(pObj, DstRes, vkDescrSet, ArrayIndex, + [&](const VkResource& SeparateSampler, ISampler* pSampler) + { + DEV_CHECK_ERR(SeparateSampler.SpirvAttribs.ArraySize == 1 || SeparateSampler.SpirvAttribs.ArraySize == SpirvAttribs.ArraySize, + "Array size (", SeparateSampler.SpirvAttribs.ArraySize,") of separate sampler variable '", + SeparateSampler.SpirvAttribs.Name, "' must be one or same as the array size (", SpirvAttribs.ArraySize, + ") of separate image variable '", SpirvAttribs.Name, "' it is assigned to"); + Uint32 SamplerArrInd = SeparateSampler.SpirvAttribs.ArraySize == 0 ? ArrayIndex : 0; + SeparateSampler.BindResource(pSampler, SamplerArrInd, ResourceCache); + } + ); break; case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler: @@ -577,7 +656,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3 { if (DstRes.pObject && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC) { - LOG_ERROR_MESSAGE( "Shader variable \"", SpirvAttribs.Name, "\" in shader \"", ParentResLayout.GetShaderName(), "\" is not dynamic but being unbound. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource." ); + LOG_ERROR_MESSAGE( "Shader variable '", SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but being unbound. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource." ); } DstRes.pObject.Release(); @@ -628,7 +707,7 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou auto SrcOffset = SrcRes.CacheOffset + ArrInd; IDeviceObject* pObject = SrcResourceCache.GetDescriptorSet(SrcRes.DescriptorSet).GetResource(SrcOffset).pObject; if (!pObject) - LOG_ERROR_MESSAGE("No resource assigned to static shader variable \"", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"."); + LOG_ERROR_MESSAGE("No resource assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); auto DstOffset = DstRes.CacheOffset + ArrInd; IDeviceObject* pCachedResource = DstResourceCache.GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).pObject; @@ -659,7 +738,7 @@ void ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& Reso if(CachedRes.pObject == nullptr && !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.SpirvAttribs.StaticSamplerInd >= 0)) { - LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.SpirvAttribs.VarType), " variable \"", Res.SpirvAttribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\""); + LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.SpirvAttribs.VarType), " variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); } #ifdef _DEBUG auto vkDescSet = CachedDescrSet.GetVkDescriptorSet(); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp index 10ca267f..e27445f9 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp @@ -28,22 +28,27 @@ #include "RenderDeviceVkImpl.h" #include "DataBlobImpl.h" #include "GLSLSourceBuilder.h" -#include "GLSL2SPIRV.h" - -using namespace Diligent; +#include "SPIRVUtils.h" namespace Diligent { - ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, const ShaderCreationAttribs& CreationAttribs) : - TShaderBase(pRefCounters, pRenderDeviceVk, CreationAttribs.Desc), - m_StaticResLayout(*this, pRenderDeviceVk->GetLogicalDevice()), - m_StaticResCache(ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources), - m_StaticVarsMgr(*this) + TShaderBase (pRefCounters, pRenderDeviceVk, CreationAttribs.Desc), + m_StaticResLayout (*this, pRenderDeviceVk->GetLogicalDevice()), + m_StaticResCache (ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources), + m_StaticVarsMgr (*this) { - auto GLSLSource = BuildGLSLSourceString(CreationAttribs, TargetGLSLCompiler::glslang, "#define TARGET_API_VULKAN 1\n"); - m_SPIRV = GLSLtoSPIRV(m_Desc.ShaderType, GLSLSource.c_str(), CreationAttribs.ppCompilerOutput); + if (CreationAttribs.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL) + { + m_SPIRV = HLSLtoSPIRV(CreationAttribs, CreationAttribs.ppCompilerOutput); + } + else + { + auto GLSLSource = BuildGLSLSourceString(CreationAttribs, TargetGLSLCompiler::glslang, "#define TARGET_API_VULKAN 1\n"); + m_SPIRV = GLSLtoSPIRV(m_Desc.ShaderType, GLSLSource.c_str(), static_cast<int>(GLSLSource.length()), CreationAttribs.ppCompilerOutput); + } + if (m_SPIRV.empty()) { LOG_ERROR_AND_THROW("Failed to compile shader"); @@ -51,16 +56,16 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* // We cannot create shader module here because resource bindings are assigned when // pipeline state is created - + // Load shader resources - auto &Allocator = GetRawAllocator(); - auto *pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", sizeof(SPIRVShaderResources)); - auto *pResources = new (pRawMem) SPIRVShaderResources(Allocator, pRenderDeviceVk, m_SPIRV, m_Desc); + auto& Allocator = GetRawAllocator(); + auto* pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", sizeof(SPIRVShaderResources)); + auto* pResources = new (pRawMem) SPIRVShaderResources(Allocator, pRenderDeviceVk, m_SPIRV, m_Desc, CreationAttribs.UseCombinedTextureSamplers ? CreationAttribs.CombinedSamplerSuffix : nullptr); m_pShaderResources.reset(pResources, STDDeleterRawMem<SPIRVShaderResources>(Allocator)); m_StaticResLayout.InitializeStaticResourceLayout(m_pShaderResources, GetRawAllocator(), m_StaticResCache); // m_StaticResLayout only contains static resources, so reference all of them - m_StaticVarsMgr.Initialize(m_StaticResLayout, GetRawAllocator(), nullptr, 0, m_StaticResCache); + m_StaticVarsMgr.Initialize(m_StaticResLayout, GetRawAllocator(), nullptr, 0, m_StaticResCache); } ShaderVkImpl::~ShaderVkImpl() diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp index f084577f..b7f992f4 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp @@ -26,7 +26,7 @@ #include "VulkanErrors.h" #include "VulkanUtilities/VulkanInstance.h" #include "VulkanUtilities/VulkanDebug.h" -#include "GLSL2SPIRV.h" +#include "SPIRVUtils.h" namespace VulkanUtilities { |
