From 176e4de5f14b5332d58f02dc6088ea751189ebba Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 7 Mar 2021 10:11:56 -0800 Subject: Reworked non-separable programs in GL; added more PSO and PRS validation --- .../GraphicsEngine/include/PipelineStateBase.hpp | 23 +++-- .../src/PipelineResourceSignatureBase.cpp | 33 ++++-- Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 111 +++++++++++++++++---- .../GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp | 3 +- .../src/PipelineResourceSignatureD3D12Impl.cpp | 8 +- .../GraphicsEngineD3D12/src/TextureD3D12Impl.cpp | 6 +- .../include/PipelineResourceSignatureGLImpl.hpp | 6 -- .../src/PipelineResourceSignatureGLImpl.cpp | 35 +------ .../src/PipelineStateGLImpl.cpp | 53 ++++------ 9 files changed, 164 insertions(+), 114 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index dcdd82d9..e8743e0f 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -48,9 +48,19 @@ namespace Diligent { -void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false); -void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false); -void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, Uint32 MaxRecursion, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false); +// Validates graphics pipeline create attributes and throws an exception in case of an error. +void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo, + const DeviceFeatures& Features) noexcept(false); + +// Validates compute pipeline create attributes and throws an exception in case of an error. +void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo, + const DeviceFeatures& Features) noexcept(false); + +// Validates ray-tracing pipeline create attributes and throws an exception in case of an error. +void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, + Uint32 MaxRecursion, + const RayTracingPipelineStateCreateInfo& CreateInfo, + const DeviceFeatures& Features) noexcept(false); /// Validates that pipeline resource description 'ResDesc' is compatible with the actual resource /// attributes and throws an exception in case of an error. @@ -138,7 +148,7 @@ public: { try { - ValidateGraphicsPipelineCreateInfo(GraphicsPipelineCI); + ValidateGraphicsPipelineCreateInfo(GraphicsPipelineCI, pDevice->GetDeviceCaps().Features); } catch (...) { @@ -162,7 +172,7 @@ public: { try { - ValidateComputePipelineCreateInfo(ComputePipelineCI); + ValidateComputePipelineCreateInfo(ComputePipelineCI, pDevice->GetDeviceCaps().Features); } catch (...) { @@ -186,7 +196,8 @@ public: { try { - ValidateRayTracingPipelineCreateInfo(pDevice, pDevice->GetProperties().MaxRayTracingRecursionDepth, RayTracingPipelineCI); + ValidateRayTracingPipelineCreateInfo(pDevice, pDevice->GetProperties().MaxRayTracingRecursionDepth, + RayTracingPipelineCI, pDevice->GetDeviceCaps().Features); } catch (...) { diff --git a/Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp b/Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp index ae41e2ba..46eb61e6 100644 --- a/Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp @@ -64,16 +64,16 @@ void ValidatePipelineResourceSignatureDesc(const PipelineResourceSignatureDesc& const auto& Res = Desc.Resources[i]; if (Res.Name == nullptr) - LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].Name must not be null"); + LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].Name must not be null."); if (Res.Name[0] == '\0') - LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].Name must not be empty"); + LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].Name must not be empty."); if (Res.ShaderStages == SHADER_TYPE_UNKNOWN) - LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].ShaderStages must not be SHADER_TYPE_UNKNOWN"); + LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].ShaderStages must not be SHADER_TYPE_UNKNOWN."); if (Res.ArraySize == 0) - LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].ArraySize must not be 0"); + LOG_PRS_ERROR_AND_THROW("Desc.Resources[", i, "].ArraySize must not be 0."); auto& UsedStages = ResourceShaderStages[Res.Name]; if ((UsedStages & Res.ShaderStages) != 0) @@ -82,6 +82,15 @@ void ValidatePipelineResourceSignatureDesc(const PipelineResourceSignatureDesc& "' specify overlapping shader stages. There may be multiple resources with the same name in different shader stages, " "but the stages must not overlap."); } + if (Features.SeparablePrograms == DEVICE_FEATURE_STATE_DISABLED && UsedStages != SHADER_TYPE_UNKNOWN) + { + LOG_PRS_ERROR_AND_THROW("This device does not support separable programs, but there are separate resources with the name '", + Res.Name, "' in shader stages ", + GetShaderStagesString(Res.ShaderStages), " and ", + GetShaderStagesString(UsedStages), + ". When separable programs are not supported, every resource is always shared between all stages. " + "Use distinct resource names for each stage or define a single resource for all stages."); + } UsedStages |= Res.ShaderStages; if ((Res.Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0 && !Features.ShaderResourceRuntimeArray) @@ -174,10 +183,13 @@ void ValidatePipelineResourceSignatureDesc(const PipelineResourceSignatureDesc& { const auto& SamDesc = Desc.ImmutableSamplers[i]; if (SamDesc.SamplerOrTextureName == nullptr) - LOG_PRS_ERROR_AND_THROW("Desc.ImmutableSamplers[", i, "].SamplerOrTextureName must not be null"); + LOG_PRS_ERROR_AND_THROW("Desc.ImmutableSamplers[", i, "].SamplerOrTextureName must not be null."); if (SamDesc.SamplerOrTextureName[0] == '\0') - LOG_PRS_ERROR_AND_THROW("Desc.ImmutableSamplers[", i, "].SamplerOrTextureName must not be empty"); + LOG_PRS_ERROR_AND_THROW("Desc.ImmutableSamplers[", i, "].SamplerOrTextureName must not be empty."); + + if (SamDesc.ShaderStages == SHADER_TYPE_UNKNOWN) + LOG_PRS_ERROR_AND_THROW("Desc.ImmutableSamplers[", i, "].ShaderStages must not be SHADER_TYPE_UNKNOWN."); auto& UsedStages = ImtblSamShaderStages[SamDesc.SamplerOrTextureName]; if ((UsedStages & SamDesc.ShaderStages) != 0) @@ -186,6 +198,15 @@ void ValidatePipelineResourceSignatureDesc(const PipelineResourceSignatureDesc& "' specify overlapping shader stages. There may be multiple immutable samplers with the same name in different shader stages, " "but the stages must not overlap."); } + if (Features.SeparablePrograms == DEVICE_FEATURE_STATE_DISABLED && UsedStages != SHADER_TYPE_UNKNOWN) + { + LOG_PRS_ERROR_AND_THROW("This device does not support separable programs, but there are separate immutable samplers with the name '", + SamDesc.SamplerOrTextureName, "' in shader stages ", + GetShaderStagesString(SamDesc.ShaderStages), " and ", + GetShaderStagesString(UsedStages), + ". When separable programs are not supported, every resource is always shared between all stages. " + "Use distinct immutable sampler names for each stage or define a single sampler for all stages."); + } UsedStages |= SamDesc.ShaderStages; } } diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp index 4c095669..c7cb1427 100644 --- a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include "HashUtils.hpp" #include "StringTools.hpp" @@ -160,7 +159,8 @@ void CorrectBlendStateDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept } -void ValidatePipelineResourceSignatures(const PipelineStateCreateInfo& CreateInfo) noexcept(false) +void ValidatePipelineResourceSignatures(const PipelineStateCreateInfo& CreateInfo, + const DeviceFeatures& Features) noexcept(false) { const auto& PSODesc = CreateInfo.PSODesc; @@ -191,8 +191,8 @@ void ValidatePipelineResourceSignatures(const PipelineStateCreateInfo& CreateInf } - std::unordered_map>, HashMapStringKey::Hasher> AllResources; - std::unordered_map>, HashMapStringKey::Hasher> AllImtblSamplers; + std::unordered_multimap, HashMapStringKey::Hasher> AllResources; + std::unordered_multimap, HashMapStringKey::Hasher> AllImtblSamplers; std::array ppSignatures = {}; for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i) @@ -216,10 +216,13 @@ void ValidatePipelineResourceSignatures(const PipelineStateCreateInfo& CreateInf for (Uint32 res = 0; res < SignDesc.NumResources; ++res) { const auto& ResDesc = SignDesc.Resources[res]; + VERIFY(ResDesc.Name != nullptr && ResDesc.Name[0] != '\0', "Resource name can't be null or empty. This should've been caught by ValidatePipelineResourceSignatureDesc()"); + VERIFY(ResDesc.ShaderStages != SHADER_TYPE_UNKNOWN, "Shader stages can't be UNKNOWN. This should've been caught by ValidatePipelineResourceSignatureDesc()"); - auto& StageSignatures = AllResources[ResDesc.Name]; - for (auto& StageSig : StageSignatures) + auto range = AllResources.equal_range(ResDesc.Name); + for (auto it = range.first; it != range.second; ++it) { + const auto& StageSig = it->second; if ((StageSig.first & ResDesc.ShaderStages) != 0) { VERIFY(StageSig.second != pSignature, "Overlapping resources in one signature should've been caught by ValidatePipelineResourceSignatureDesc()"); @@ -228,17 +231,31 @@ void ValidatePipelineResourceSignatures(const PipelineStateCreateInfo& CreateInf "' and '", StageSig.second->GetDesc().Name, "') in the same shader stage. Every shader resource in the PSO must be unambiguously defined by only one resource signature."); } + + if (Features.SeparablePrograms == DEVICE_FEATURE_STATE_DISABLED) + { + VERIFY_EXPR(StageSig.first != SHADER_TYPE_UNKNOWN); + VERIFY(StageSig.second != pSignature, "Resources with the same name in one signature should've been caught by ValidatePipelineResourceSignatureDesc()"); + + LOG_PSO_ERROR_AND_THROW("This device does not support separable programs, but shader resource '", ResDesc.Name, "' is found in more than one resource signature ('", + SignDesc.Name, "' and '", StageSig.second->GetDesc().Name, + "') in different stages. When separable programs are not supported, every resource is always shared between all stages. " + "Use distinct resource names for each stage or define a single resource for all stages."); + } } - StageSignatures.emplace_back(ResDesc.ShaderStages, pSignature); + AllResources.emplace(ResDesc.Name, std::make_pair(ResDesc.ShaderStages, pSignature)); } for (Uint32 res = 0; res < SignDesc.NumImmutableSamplers; ++res) { const auto& SamDesc = SignDesc.ImmutableSamplers[res]; + VERIFY(SamDesc.SamplerOrTextureName != nullptr && SamDesc.SamplerOrTextureName[0] != '\0', "Sampler name can't be null or empty. This should've been caught by ValidatePipelineResourceSignatureDesc()"); + VERIFY(SamDesc.ShaderStages != SHADER_TYPE_UNKNOWN, "Shader stage can't be UNKNOWN. This should've been caught by ValidatePipelineResourceSignatureDesc()"); - auto& StageSignatures = AllImtblSamplers[SamDesc.SamplerOrTextureName]; - for (auto& StageSig : StageSignatures) + auto range = AllImtblSamplers.equal_range(SamDesc.SamplerOrTextureName); + for (auto it = range.first; it != range.second; ++it) { + const auto& StageSig = it->second; if ((StageSig.first & SamDesc.ShaderStages) != 0) { VERIFY(StageSig.second != pSignature, "Overlapping immutable samplers in one signature should've been caught by ValidatePipelineResourceSignatureDesc()"); @@ -247,13 +264,24 @@ void ValidatePipelineResourceSignatures(const PipelineStateCreateInfo& CreateInf "' and '", StageSig.second->GetDesc().Name, "') in the same stage. Every immutable sampler in the PSO must be unambiguously defined by only one resource signature."); } + + if (Features.SeparablePrograms == DEVICE_FEATURE_STATE_DISABLED) + { + VERIFY_EXPR(StageSig.first != SHADER_TYPE_UNKNOWN); + VERIFY(StageSig.second != pSignature, "Immutable samplers with the same name in one signature should've been caught by ValidatePipelineResourceSignatureDesc()"); + + LOG_PSO_ERROR_AND_THROW("This device does not support separable programs, but immutable sampler '", SamDesc.SamplerOrTextureName, "' is found in more than one resource signature ('", + SignDesc.Name, "' and '", StageSig.second->GetDesc().Name, + "') in different stages. When separable programs are not supported, every resource is always shared between all stages. " + "Use distinct resource names for each stage or define a single immutable sampler for all stages."); + } } - StageSignatures.emplace_back(SamDesc.ShaderStages, pSignature); + AllImtblSamplers.emplace(SamDesc.SamplerOrTextureName, std::make_pair(SamDesc.ShaderStages, pSignature)); } } } -void ValidatePipelineResourceLayoutDesc(const PipelineStateDesc& PSODesc) noexcept(false) +void ValidatePipelineResourceLayoutDesc(const PipelineStateDesc& PSODesc, const DeviceFeatures& Features) noexcept(false) { const auto& Layout = PSODesc.ResourceLayout; { @@ -262,6 +290,15 @@ void ValidatePipelineResourceLayoutDesc(const PipelineStateDesc& PSODesc) noexce { const auto& Var = Layout.Variables[i]; + if (Var.Name == nullptr) + LOG_PSO_ERROR_AND_THROW("ResourceLayout.Variables[", i, "].Name must not be null."); + + if (Var.Name[0] == '\0') + LOG_PSO_ERROR_AND_THROW("ResourceLayout.Variables[", i, "].Name must not be empty."); + + if (Var.ShaderStages == SHADER_TYPE_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("ResourceLayout.Variables[", i, "].ShaderStages must not be SHADER_TYPE_UNKNOWN."); + auto range = UniqueVariables.equal_range(Var.Name); for (auto it = range.first; it != range.second; ++it) { @@ -271,6 +308,16 @@ void ValidatePipelineResourceLayoutDesc(const PipelineStateDesc& PSODesc) noexce " and ", GetShaderStagesString(it->second), "). Multiple variables with the same name are allowed, but shader stages they use must not overlap."); } + if (Features.SeparablePrograms == DEVICE_FEATURE_STATE_DISABLED) + { + VERIFY_EXPR(it->second != SHADER_TYPE_UNKNOWN); + LOG_PSO_ERROR_AND_THROW("This device does not support separable programs, but there are separate resources with the name '", + Var.Name, "' in shader stages ", + GetShaderStagesString(Var.ShaderStages), " and ", + GetShaderStagesString(it->second), + ". When separable programs are not supported, every resource is always shared between all stages. " + "Use distinct resource names for each stage or define a single resource for all stages."); + } } UniqueVariables.emplace(Var.Name, Var.ShaderStages); } @@ -281,6 +328,15 @@ void ValidatePipelineResourceLayoutDesc(const PipelineStateDesc& PSODesc) noexce { const auto& Sam = Layout.ImmutableSamplers[i]; + if (Sam.SamplerOrTextureName == nullptr) + LOG_PSO_ERROR_AND_THROW("ResourceLayout.ImmutableSamplers[", i, "].SamplerOrTextureName must not be null."); + + if (Sam.SamplerOrTextureName[0] == '\0') + LOG_PSO_ERROR_AND_THROW("ResourceLayout.ImmutableSamplers[", i, "].SamplerOrTextureName must not be empty."); + + if (Sam.ShaderStages == SHADER_TYPE_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("ResourceLayout.ImmutableSamplers[", i, "].ShaderStages must not be SHADER_TYPE_UNKNOWN."); + auto range = UniqueSamplers.equal_range(Sam.SamplerOrTextureName); for (auto it = range.first; it != range.second; ++it) { @@ -290,6 +346,16 @@ void ValidatePipelineResourceLayoutDesc(const PipelineStateDesc& PSODesc) noexce " and ", GetShaderStagesString(it->second), "). Multiple immutable samplers with the same name are allowed, but shader stages they use must not overlap."); } + if (Features.SeparablePrograms == DEVICE_FEATURE_STATE_DISABLED) + { + VERIFY_EXPR(it->second != SHADER_TYPE_UNKNOWN); + LOG_PSO_ERROR_AND_THROW("This device does not support separable programs, but there are separate immutable samplers with the name '", + Sam.SamplerOrTextureName, "' in shader stages ", + GetShaderStagesString(Sam.ShaderStages), " and ", + GetShaderStagesString(it->second), + ". When separable programs are not supported, every resource is always shared between all stages. " + "Use distinct immutable sampler names for each stage or define a single sampler for all stages."); + } } UniqueSamplers.emplace(Sam.SamplerOrTextureName, Sam.ShaderStages); } @@ -304,20 +370,21 @@ void ValidatePipelineResourceLayoutDesc(const PipelineStateDesc& PSODesc) noexce LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \ } -void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false) +void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo, + const DeviceFeatures& Features) noexcept(false) { const auto& PSODesc = CreateInfo.PSODesc; if (PSODesc.PipelineType != PIPELINE_TYPE_GRAPHICS && PSODesc.PipelineType != PIPELINE_TYPE_MESH) LOG_PSO_ERROR_AND_THROW("Pipeline type must be GRAPHICS or MESH."); - ValidatePipelineResourceSignatures(CreateInfo); + ValidatePipelineResourceSignatures(CreateInfo, Features); const auto& GraphicsPipeline = CreateInfo.GraphicsPipeline; ValidateBlendStateDesc(PSODesc, GraphicsPipeline); ValidateRasterizerStateDesc(PSODesc, GraphicsPipeline); ValidateDepthStencilDesc(PSODesc, GraphicsPipeline); - ValidatePipelineResourceLayoutDesc(PSODesc); + ValidatePipelineResourceLayoutDesc(PSODesc, Features); if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) @@ -384,14 +451,15 @@ void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& C } } -void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false) +void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo, + const DeviceFeatures& Features) noexcept(false) { const auto& PSODesc = CreateInfo.PSODesc; if (PSODesc.PipelineType != PIPELINE_TYPE_COMPUTE) LOG_PSO_ERROR_AND_THROW("Pipeline type must be COMPUTE."); - ValidatePipelineResourceSignatures(CreateInfo); - ValidatePipelineResourceLayoutDesc(PSODesc); + ValidatePipelineResourceSignatures(CreateInfo, Features); + ValidatePipelineResourceLayoutDesc(PSODesc, Features); if (CreateInfo.pCS == nullptr) LOG_PSO_ERROR_AND_THROW("Compute shader must not be null."); @@ -399,14 +467,17 @@ void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& Cre VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute") } -void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, Uint32 MaxRecursion, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false) +void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, + Uint32 MaxRecursion, + const RayTracingPipelineStateCreateInfo& CreateInfo, + const DeviceFeatures& Features) noexcept(false) { const auto& PSODesc = CreateInfo.PSODesc; if (PSODesc.PipelineType != PIPELINE_TYPE_RAY_TRACING) LOG_PSO_ERROR_AND_THROW("Pipeline type must be RAY_TRACING."); - ValidatePipelineResourceSignatures(CreateInfo); - ValidatePipelineResourceLayoutDesc(PSODesc); + ValidatePipelineResourceSignatures(CreateInfo, Features); + ValidatePipelineResourceLayoutDesc(PSODesc, Features); if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12) { diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp index 03f52354..aac0bf87 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp @@ -58,7 +58,8 @@ D3D12DynamicPage::D3D12DynamicPage(ID3D12Device* pd3d12Device, Uint64 Size) ResourceDesc.Width = Size; auto hr = pd3d12Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &ResourceDesc, - DefaultUsage, nullptr, __uuidof(m_pd3d12Buffer), reinterpret_cast(static_cast(&m_pd3d12Buffer))); + DefaultUsage, nullptr, __uuidof(m_pd3d12Buffer), + reinterpret_cast(static_cast(&m_pd3d12Buffer))); if (FAILED(hr)) { LOG_D3D_ERROR(hr, "Failed to create dynamic page"); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp index 7d913990..088a052e 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp @@ -63,7 +63,7 @@ inline bool ResourcesCompatible(const PipelineResourceSignatureD3D12Impl::Resour // clang-format on } -void ValidateD3D12PipelineResourceSignatureDesc(const PipelineResourceSignatureDesc& Desc) noexcept(false) +void ValidatePipelineResourceSignatureDescD3D12(const PipelineResourceSignatureDesc& Desc) noexcept(false) { { std::unordered_multimap ResNameToShaderStages; @@ -113,7 +113,7 @@ void ValidateD3D12PipelineResourceSignatureDesc(const PipelineResourceSignatureD else { LOG_ERROR_AND_THROW("Pipeline resource signature '", (Desc.Name != nullptr ? Desc.Name : ""), - "' defines immutable sampler with the name '", Name, "' in shader stages ", + "' defines separate immutable samplers with the name '", Name, "' in shader stages ", GetShaderStagesString(multi_stage_it->second), " and ", GetShaderStagesString(it->second), ". In Direct3D12 backend, only one immutable sampler in the group of samplers with the same name can be shared between more than " @@ -135,10 +135,10 @@ PipelineResourceSignatureD3D12Impl::PipelineResourceSignatureD3D12Impl(IReferenc TPipelineResourceSignatureBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}, m_SRBMemAllocator{GetRawAllocator()} { - ValidateD3D12PipelineResourceSignatureDesc(Desc); - try { + ValidatePipelineResourceSignatureDescD3D12(Desc); + auto& RawAllocator{GetRawAllocator()}; auto MemPool = ReserveSpace(RawAllocator, Desc, [&Desc](FixedLinearAllocator& MemPool) // diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp index ce8b702f..9958d158 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp @@ -229,7 +229,8 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters, CComPtr UploadBuffer; hr = pd3d12Device->CreateCommittedResource(&UploadHeapProps, D3D12_HEAP_FLAG_NONE, &BufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, __uuidof(UploadBuffer), reinterpret_cast(static_cast(&UploadBuffer))); + nullptr, __uuidof(UploadBuffer), + reinterpret_cast(static_cast(&UploadBuffer))); if (FAILED(hr)) LOG_ERROR_AND_THROW("Failed to create committed resource in an upload heap"); @@ -333,7 +334,8 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters, // on some ARM systems, to marshal data between the CPU and GPU through memory addresses with write-back behavior. // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12resource-map auto hr = pd3d12Device->CreateCommittedResource(&StaginHeapProps, D3D12_HEAP_FLAG_NONE, &BufferDesc, D3D12State, - nullptr, __uuidof(m_pd3d12Resource), reinterpret_cast(static_cast(&m_pd3d12Resource))); + nullptr, __uuidof(m_pd3d12Resource), + reinterpret_cast(static_cast(&m_pd3d12Resource))); if (FAILED(hr)) LOG_ERROR_AND_THROW("Failed to create staging buffer"); diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp index f4a4cefb..9c37301f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp @@ -190,12 +190,6 @@ public: #endif private: - PipelineResourceSignatureGLImpl(IReferenceCounters* pRefCounters, - RenderDeviceGLImpl* pDevice, - const PipelineResourceSignatureDesc& Desc, - bool bIsDeviceInternal, - int Internal); - // Copies static resources from the static resource cache to the destination cache void CopyStaticResources(ShaderResourceCacheGL& ResourceCache) const; diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineResourceSignatureGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineResourceSignatureGLImpl.cpp index 60cae558..1373c446 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineResourceSignatureGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineResourceSignatureGLImpl.cpp @@ -33,6 +33,7 @@ namespace Diligent { + namespace { @@ -46,32 +47,6 @@ inline bool ResourcesCompatible(const PipelineResourceSignatureGLImpl::ResourceA // clang-format on } -struct PatchedPipelineResourceSignatureDesc : PipelineResourceSignatureDesc -{ - std::vector m_ImmutableSamplers; - - PatchedPipelineResourceSignatureDesc(RenderDeviceGLImpl* pDeviceGL, const PipelineResourceSignatureDesc& Desc) : - PipelineResourceSignatureDesc{Desc} - { - if (NumImmutableSamplers > 0 && ImmutableSamplers != nullptr && !pDeviceGL->GetDeviceCaps().Features.SeparablePrograms) - { - m_ImmutableSamplers.resize(NumImmutableSamplers); - - SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN; - for (Uint32 r = 0; r < NumResources; ++r) - ActiveStages |= Resources[r].ShaderStages; - - for (Uint32 s = 0; s < NumImmutableSamplers; ++s) - { - m_ImmutableSamplers[s] = ImmutableSamplers[s]; - m_ImmutableSamplers[s].ShaderStages |= ActiveStages; - } - - ImmutableSamplers = m_ImmutableSamplers.data(); - } - } -}; - } // namespace @@ -117,14 +92,6 @@ PipelineResourceSignatureGLImpl::PipelineResourceSignatureGLImpl(IReferenceCount RenderDeviceGLImpl* pDeviceGL, const PipelineResourceSignatureDesc& Desc, bool bIsDeviceInternal) : - PipelineResourceSignatureGLImpl{pRefCounters, pDeviceGL, PatchedPipelineResourceSignatureDesc{pDeviceGL, Desc}, bIsDeviceInternal, 0} -{} - -PipelineResourceSignatureGLImpl::PipelineResourceSignatureGLImpl(IReferenceCounters* pRefCounters, - RenderDeviceGLImpl* pDeviceGL, - const PipelineResourceSignatureDesc& Desc, - bool bIsDeviceInternal, - int) : TPipelineResourceSignatureBase{pRefCounters, pDeviceGL, Desc, bIsDeviceInternal}, m_SRBMemAllocator{GetRawAllocator()} { diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 334b20d7..cc1d115d 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -48,9 +48,8 @@ RefCntAutoPtr PipelineStateGLImpl::CreateDefaul { std::vector Resources; - const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout; - const auto DefaultVarType = LayoutDesc.DefaultVariableType; - ShaderResourcesGL ProgramResources; + const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout; + const auto DefaultVarType = LayoutDesc.DefaultVariableType; struct UniqueResource { @@ -83,42 +82,25 @@ RefCntAutoPtr PipelineStateGLImpl::CreateDefaul ResDesc.VarType = DefaultVarType; ResDesc.Flags = Flags; - if (m_IsProgramPipelineSupported) + const auto VarIndex = FindPipelineResourceLayoutVariable(LayoutDesc, Attribs.Name, ResDesc.ShaderStages, nullptr); + if (VarIndex != InvalidPipelineResourceLayoutVariableIndex) { - const auto VarIndex = FindPipelineResourceLayoutVariable(LayoutDesc, Attribs.Name, ResDesc.ShaderStages, nullptr); - if (VarIndex != InvalidPipelineResourceLayoutVariableIndex) - { - const auto& Var = LayoutDesc.Variables[VarIndex]; - ResDesc.ShaderStages = Var.ShaderStages; - ResDesc.VarType = Var.Type; - } + const auto& Var = LayoutDesc.Variables[VarIndex]; + ResDesc.ShaderStages = Var.ShaderStages; + ResDesc.VarType = Var.Type; + } - auto IterAndAssigned = UniqueResources.emplace(UniqueResource{Attribs, ResDesc.ShaderStages}); - if (IterAndAssigned.second) - { - Resources.push_back(ResDesc); - } - else - { - DEV_CHECK_ERR(IterAndAssigned.first->Attribs.ResourceType == Attribs.ResourceType, - "Shader variable '", Attribs.Name, - "' exists in multiple shaders from the same shader stage, but its type is not consistent between " - "shaders. All variables with the same name from the same shader stage must have the same type."); - } + auto IterAndAssigned = UniqueResources.emplace(UniqueResource{Attribs, ResDesc.ShaderStages}); + if (IterAndAssigned.second) + { + Resources.push_back(ResDesc); } else { - for (Uint32 i = 0; i < LayoutDesc.NumVariables; ++i) - { - const auto& Var = LayoutDesc.Variables[i]; - if ((Var.ShaderStages & Attribs.ShaderStages) != 0 && - std::strcmp(Attribs.Name, Var.Name) == 0) - { - ResDesc.VarType = Var.Type; - break; - } - } - Resources.push_back(ResDesc); + DEV_CHECK_ERR(IterAndAssigned.first->Attribs.ResourceType == Attribs.ResourceType, + "Shader variable '", Attribs.Name, + "' exists in multiple shaders from the same shader stage, but its type is not consistent between " + "shaders. All variables with the same name from the same shader stage must have the same type."); } }; const auto HandleUB = [&](const ShaderResourcesGL::UniformBufferInfo& Attribs) { @@ -134,6 +116,7 @@ RefCntAutoPtr PipelineStateGLImpl::CreateDefaul HandleResource(Attribs, PIPELINE_RESOURCE_FLAG_UNKNOWN); }; + ShaderResourcesGL ProgramResources; if (m_IsProgramPipelineSupported) { for (size_t i = 0; i < ShaderStages.size(); ++i) @@ -325,7 +308,7 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* ShaderCI.Source = "void main(){}"; ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; ShaderCI.Desc.Name = "Dummy fragment shader"; - pDeviceGL->CreateShader(ShaderCI, reinterpret_cast(static_cast(&pTempPS))); + pDeviceGL->CreateShader(ShaderCI, pTempPS.DblPtr()); Shaders.emplace_back(pTempPS); } -- cgit v1.2.3