diff options
| author | azhirnov <zh1dron@gmail.com> | 2021-01-26 07:15:53 +0000 |
|---|---|---|
| committer | azhirnov <zh1dron@gmail.com> | 2021-01-26 07:15:53 +0000 |
| commit | 51f876af24d24e923a08af00a69e9f5d9ec6bcfe (patch) | |
| tree | acc2411776b145326d788de99e2ff135e4e604ab | |
| parent | remove assigned samplers from SPIRV resources (diff) | |
| download | DiligentCore-51f876af24d24e923a08af00a69e9f5d9ec6bcfe.tar.gz DiligentCore-51f876af24d24e923a08af00a69e9f5d9ec6bcfe.zip | |
allow to combine graphics PRS with mesh pipeline
7 files changed, 343 insertions, 21 deletions
diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index af4a04ea..0cac3ff5 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -1453,35 +1453,33 @@ SHADER_TYPE GetShaderTypeFromPipelineIndex(Int32 Index, PIPELINE_TYPE PipelineTy PIPELINE_TYPE PipelineTypeFromShaderStages(SHADER_TYPE ShaderStages) { + if ((ShaderStages & ~SHADER_TYPE_PIXEL) & SHADER_TYPE_ALL_MESH) + { + VERIFY((ShaderStages & SHADER_TYPE_ALL_MESH) == ShaderStages, + "Mesh shading pipeline stages can't be combined with other shader stages"); + return PIPELINE_TYPE_MESH; + } if (ShaderStages & SHADER_TYPE_ALL_GRAPHICS) { VERIFY((ShaderStages & SHADER_TYPE_ALL_GRAPHICS) == ShaderStages, "Graphics pipeline stages can't be combined with other shader stages"); return PIPELINE_TYPE_GRAPHICS; } - else if (ShaderStages & SHADER_TYPE_COMPUTE) + if (ShaderStages & SHADER_TYPE_COMPUTE) { VERIFY((ShaderStages & SHADER_TYPE_COMPUTE) == ShaderStages, "Compute stage can't be combined with any other shader stage"); return PIPELINE_TYPE_COMPUTE; } - else if (ShaderStages & SHADER_TYPE_ALL_MESH) - { - VERIFY((ShaderStages & SHADER_TYPE_ALL_MESH) == ShaderStages, - "Mesh shading pipeline stages can't be combined with other shader stages"); - return PIPELINE_TYPE_MESH; - } - else if (ShaderStages & SHADER_TYPE_ALL_RAY_TRACING) + if (ShaderStages & SHADER_TYPE_ALL_RAY_TRACING) { VERIFY((ShaderStages & SHADER_TYPE_ALL_RAY_TRACING) == ShaderStages, "Ray tracing pipeline stages can't be combined with other shader stages"); return PIPELINE_TYPE_RAY_TRACING; } - else - { - UNEXPECTED("Unknown shader stage"); - return PIPELINE_TYPE_INVALID; - } + + UNEXPECTED("Unknown shader stage"); + return PIPELINE_TYPE_INVALID; } Uint32 GetStagingTextureLocationOffset(const TextureDesc& TexDesc, diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index 28207960..063b6777 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -71,7 +71,8 @@ DILIGENT_TYPED_ENUM(SHADER_TYPE, Uint32) /// All mesh shading pipeline stages SHADER_TYPE_ALL_MESH = SHADER_TYPE_AMPLIFICATION | - SHADER_TYPE_MESH, + SHADER_TYPE_MESH | + SHADER_TYPE_PIXEL, /// All ray-tracing pipeline shader stages SHADER_TYPE_ALL_RAY_TRACING = SHADER_TYPE_RAY_GEN | diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp index 660815f6..87cf1da0 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp @@ -46,7 +46,7 @@ public: PipelineLayoutVk(); ~PipelineLayoutVk(); - void Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount); + void Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE PipelineType, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount); void Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask); size_t GetHash() const; @@ -69,10 +69,10 @@ public: struct ResourceInfo { - SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN; - - Uint32 DescrSetIndex = 0; - Uint32 BindingIndex = 0; + IPipelineResourceSignature* Signature = nullptr; + SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN; + Uint32 DescrSetIndex = 0; + Uint32 BindingIndex = 0; }; bool GetResourceInfo(const char* Name, SHADER_TYPE Stage, ResourceInfo& Info) const; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp index 969fe16e..e190c4fd 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp @@ -56,7 +56,7 @@ void PipelineLayoutVk::Release(RenderDeviceVkImpl* pDeviceVk, Uint64 CommandQueu } } -void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount) +void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE PipelineType, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount) { VERIFY(m_SignatureCount == 0 && m_DescrSetCount == 0 && !m_VkPipelineLayout, "This pipeline layout is already initialized"); @@ -68,6 +68,7 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi const Uint8 Index = pSignature->GetDesc().BindingIndex; +#ifdef DILIGENT_DEBUG VERIFY(Index < m_Signatures.size(), "Pipeline resource signature specifies binding index ", Uint32{Index}, " that exceeds the limit (", m_Signatures.size() - 1, "). This error should've been caught by ValidatePipelineResourceSignatureDesc."); @@ -77,6 +78,16 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi " conflicts with another resource signature '", m_Signatures[Index]->GetDesc().Name, "' that uses the same index. This error should've been caught by ValidatePipelineResourceSignatures."); + for (Uint32 s = 0, StageCount = pSignature->GetNumShaderStages(); s < StageCount; ++s) + { + const auto ShaderType = pSignature->GetShaderStageType(s); + VERIFY(IsConsistentShaderType(ShaderType, PipelineType), + "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index}, + " has shader stage '", GetShaderTypeLiteralName(ShaderType), "' that is not compatible with pipeline type '", + GetPipelineTypeString(PipelineType), "'."); + } +#endif + m_SignatureCount = std::max<Uint8>(m_SignatureCount, Index + 1); m_Signatures[Index] = pSignature; } diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 41585909..2817a53a 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -830,7 +830,7 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea } } - m_PipelineLayout.Create(GetDevice(), Signatures.data(), SignatureCount); + m_PipelineLayout.Create(GetDevice(), CreateInfo.PSODesc.PipelineType, Signatures.data(), SignatureCount); // verify that pipeline layout is compatible with shader resources and // remap resource bindings diff --git a/Tests/DiligentCoreAPITest/include/InlineShaders/PipelineResourceSignatureTestHLSL.h b/Tests/DiligentCoreAPITest/include/InlineShaders/PipelineResourceSignatureTestHLSL.h index f7d16192..713a89b2 100644 --- a/Tests/DiligentCoreAPITest/include/InlineShaders/PipelineResourceSignatureTestHLSL.h +++ b/Tests/DiligentCoreAPITest/include/InlineShaders/PipelineResourceSignatureTestHLSL.h @@ -128,6 +128,100 @@ void main(PSInput In, )" }; + +const std::string PRSTest3_VS{ +R"( +struct VSOutput +{ + float4 f4Position : SV_Position; + float2 f2Texcoord : TEXCOORD0; + float3 f3Color : COLOR; +}; + +cbuffer Constants +{ + float4 g_Weight1; + float4 g_Weight2; +}; + +void main(uint uiVertexId : SV_VertexID, + out VSOutput Out) +{ + float4 Positions[3]; + Positions[0] = float4(-0.5, -0.5, 0.0, 1.0) * g_Weight1; + Positions[1] = float4(+0.5, +0.5, 0.0, 1.0) * g_Weight1; + Positions[2] = float4(-0.5, +0.5, 0.0, 1.0) * g_Weight1; + + float3 Color[3]; + Color[0] = float3(0.5, 0.0, 0.0); + Color[1] = float3(0.0, 0.0, 0.5); + Color[2] = float3(0.0, 0.5, 0.0); + + Out.f4Position = Positions[uiVertexId]; + Out.f2Texcoord = Positions[uiVertexId].xy; + Out.f3Color = Color[uiVertexId]; +} +)" +}; + +const std::string PRSTest3_MS{ +R"( +struct MSOutput +{ + float4 f4Position : SV_Position; + float2 f2Texcoord : TEXCOORD0; + float3 f3Color : COLOR; +}; + +static const float3 colors[4] = {float3(1.0,0.0,0.0), float3(0.0,1.0,0.0), float3(0.0,0.0,1.0), float3(1.0,1.0,1.0)}; + +cbuffer Constants +{ + float4 g_Weight1; + float4 g_Weight2; +}; + +[numthreads(4,1,1)] +[outputtopology("triangle")] +void main(uint I : SV_GroupIndex, + out indices uint3 tris[2], + out vertices MSOutput verts[4]) +{ + SetMeshOutputCounts(4, 2); + + if (I == 0) + tris[0] = uint3(0, 1, 2); + + if (I == 3) + tris[1] = uint3(2, 1, 3); + + float2 pos = float2(float(I >> 1), float(I & 1)); + + verts[I].f4Position = float4(pos * 2.0 - 1.0, 0.0, 1.0) * g_Weight1; + verts[I].f2Texcoord = pos * g_Weight2.xy; + verts[I].f3Color = colors[I]; +} +)" +}; + +const std::string PRSTest3_PS{ +R"( +struct PSInput +{ + float4 f4Position : SV_Position; + float2 f2Texcoord : TEXCOORD0; + float3 f3Color : COLOR; +}; + +Texture2D g_Texture; +SamplerState g_Texture_sampler; + +void main(PSInput In, + out float4 Color : SV_Target) +{ +} +)" +}; // clang-format on } // namespace HLSL diff --git a/Tests/DiligentCoreAPITest/src/PipelineResourceSignatureTest.cpp b/Tests/DiligentCoreAPITest/src/PipelineResourceSignatureTest.cpp index 1e09af65..02e705bf 100644 --- a/Tests/DiligentCoreAPITest/src/PipelineResourceSignatureTest.cpp +++ b/Tests/DiligentCoreAPITest/src/PipelineResourceSignatureTest.cpp @@ -789,4 +789,222 @@ TEST_F(PipelineResourceSignatureTest, SRBCompatibility) pContext->Draw(drawAttrs); } + +TEST_F(PipelineResourceSignatureTest, GraphicsAndMeshShader) +{ + auto* pEnv = TestingEnvironment::GetInstance(); + auto* pDevice = pEnv->GetDevice(); + auto* pContext = pEnv->GetDeviceContext(); + if (!pDevice->GetDeviceCaps().Features.MeshShaders) + { + GTEST_SKIP() << "Mesh shader is not supported by this device"; + } + + TestingEnvironment::ScopedReset EnvironmentAutoReset; + + RefCntAutoPtr<IPipelineResourceSignature> pSignaturePS; + { + const PipelineResourceDesc Resources[] = { + {SHADER_TYPE_PIXEL, "g_Texture", 1, SHADER_RESOURCE_TYPE_TEXTURE_SRV, SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE}, + {SHADER_TYPE_PIXEL, "g_Texture_sampler", 1, SHADER_RESOURCE_TYPE_SAMPLER, SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE}}; + + SamplerDesc SamLinearWrapDesc{ + FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, + TEXTURE_ADDRESS_WRAP, TEXTURE_ADDRESS_WRAP, TEXTURE_ADDRESS_WRAP}; + ImmutableSamplerDesc ImmutableSamplers[] = {{SHADER_TYPE_PIXEL, "g_Texture", SamLinearWrapDesc}}; + + PipelineResourceSignatureDesc Desc; + Desc.Resources = Resources; + Desc.NumResources = _countof(Resources); + Desc.ImmutableSamplers = ImmutableSamplers; + Desc.NumImmutableSamplers = _countof(ImmutableSamplers); + Desc.UseCombinedTextureSamplers = true; + Desc.CombinedSamplerSuffix = "_sampler"; + Desc.BindingIndex = 0; + + pDevice->CreatePipelineResourceSignature(Desc, &pSignaturePS); + ASSERT_NE(pSignaturePS, nullptr); + } + + RefCntAutoPtr<IPipelineResourceSignature> pSignatureVS; + { + const PipelineResourceDesc Resources[] = { + {SHADER_TYPE_VERTEX, "Constants", 1, SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE}}; + + PipelineResourceSignatureDesc Desc; + Desc.Resources = Resources; + Desc.NumResources = _countof(Resources); + Desc.BindingIndex = 1; + + pDevice->CreatePipelineResourceSignature(Desc, &pSignatureVS); + ASSERT_NE(pSignatureVS, nullptr); + } + + RefCntAutoPtr<IPipelineResourceSignature> pSignatureMS; + { + const PipelineResourceDesc Resources[] = { + {SHADER_TYPE_MESH, "Constants", 1, SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}}; + + PipelineResourceSignatureDesc Desc; + Desc.Resources = Resources; + Desc.NumResources = _countof(Resources); + Desc.BindingIndex = 1; + + pDevice->CreatePipelineResourceSignature(Desc, &pSignatureMS); + ASSERT_NE(pSignatureMS, nullptr); + } + + GraphicsPipelineStateCreateInfo PSOCreateInfo; + + auto& PSODesc = PSOCreateInfo.PSODesc; + auto& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline; + + PSODesc.Name = "Graphics PSO"; + + PSODesc.PipelineType = PIPELINE_TYPE_GRAPHICS; + GraphicsPipeline.NumRenderTargets = 1; + GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM; + GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE; + GraphicsPipeline.DepthStencilDesc.DepthEnable = False; + + ShaderCreateInfo ShaderCI; + ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; + ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC; + ShaderCI.UseCombinedTextureSamplers = true; + + RefCntAutoPtr<IShader> pVS; + { + ShaderCI.Desc.ShaderType = SHADER_TYPE_VERTEX; + ShaderCI.EntryPoint = "main"; + ShaderCI.Desc.Name = "PRS test - VS"; + ShaderCI.Source = HLSL::PRSTest3_VS.c_str(); + pDevice->CreateShader(ShaderCI, &pVS); + ASSERT_NE(pVS, nullptr); + } + + RefCntAutoPtr<IShader> pPS; + { + ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; + ShaderCI.EntryPoint = "main"; + ShaderCI.Desc.Name = "PRS test - PS"; + ShaderCI.Source = HLSL::PRSTest3_PS.c_str(); + pDevice->CreateShader(ShaderCI, &pPS); + ASSERT_NE(pPS, nullptr); + } + + PSOCreateInfo.pVS = pVS; + PSOCreateInfo.pPS = pPS; + + IPipelineResourceSignature* GraphicsSignatures[] = {pSignatureVS, pSignaturePS}; + + PSOCreateInfo.ppResourceSignatures = GraphicsSignatures; + PSOCreateInfo.ResourceSignaturesCount = _countof(GraphicsSignatures); + + RefCntAutoPtr<IPipelineState> pGraphicsPSO; + pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pGraphicsPSO); + ASSERT_NE(pGraphicsPSO, nullptr); + + ASSERT_EQ(pGraphicsPSO->GetResourceSignatureCount(), 2u); + ASSERT_EQ(pGraphicsPSO->GetResourceSignature(0), pSignaturePS); + ASSERT_EQ(pGraphicsPSO->GetResourceSignature(1), pSignatureVS); + + + RefCntAutoPtr<IShader> pMS; + { + ShaderCI.Desc.ShaderType = SHADER_TYPE_MESH; + ShaderCI.EntryPoint = "main"; + ShaderCI.Desc.Name = "PRS test - MS"; + ShaderCI.Source = HLSL::PRSTest3_MS.c_str(); + pDevice->CreateShader(ShaderCI, &pMS); + ASSERT_NE(pMS, nullptr); + } + + PSODesc.PipelineType = PIPELINE_TYPE_MESH; + GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_UNDEFINED; // unused + + PSOCreateInfo.pVS = nullptr; + PSOCreateInfo.pMS = pMS; + PSOCreateInfo.pPS = pPS; + + IPipelineResourceSignature* MeshSignatures[] = {pSignatureMS, pSignaturePS}; + + PSOCreateInfo.ppResourceSignatures = MeshSignatures; + PSOCreateInfo.ResourceSignaturesCount = _countof(MeshSignatures); + + RefCntAutoPtr<IPipelineState> pMeshPSO; + pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pMeshPSO); + ASSERT_NE(pMeshPSO, nullptr); + + ASSERT_EQ(pMeshPSO->GetResourceSignatureCount(), 2u); + ASSERT_EQ(pMeshPSO->GetResourceSignature(0), pSignaturePS); + ASSERT_EQ(pMeshPSO->GetResourceSignature(1), pSignatureMS); + + + RefCntAutoPtr<IBuffer> pConstBuf; + { + float ConstData[8] = {}; + BufferDesc BuffDesc; + BuffDesc.uiSizeInBytes = sizeof(ConstData); + BuffDesc.BindFlags = BIND_UNIFORM_BUFFER; + BuffDesc.Usage = USAGE_IMMUTABLE; + BufferData BuffData{ConstData, sizeof(ConstData)}; + pDevice->CreateBuffer(BuffDesc, &BuffData, &pConstBuf); + ASSERT_NE(pConstBuf, nullptr); + } + + RefCntAutoPtr<ITexture> pTexture; + { + TextureDesc TexDesc; + TexDesc.Type = RESOURCE_DIM_TEX_2D; + TexDesc.Width = 256; + TexDesc.Height = 256; + TexDesc.Usage = USAGE_IMMUTABLE; + TexDesc.Format = TEX_FORMAT_RGBA8_UNORM; + TexDesc.BindFlags = BIND_SHADER_RESOURCE; + + std::vector<Uint8> Data(TexDesc.Width * TexDesc.Height * 4, 128); + TextureSubResData TexSubData{Data.data(), TexDesc.Width * 4}; + TextureData TexData{&TexSubData, 1}; + pDevice->CreateTexture(TexDesc, &TexData, &pTexture); + ASSERT_NE(pTexture, nullptr); + } + + RefCntAutoPtr<IShaderResourceBinding> PixelSRB; + pSignaturePS->CreateShaderResourceBinding(&PixelSRB, true); + ASSERT_NE(PixelSRB, nullptr); + + RefCntAutoPtr<IShaderResourceBinding> VertexSRB; + pSignatureVS->CreateShaderResourceBinding(&VertexSRB, true); + ASSERT_NE(VertexSRB, nullptr); + + RefCntAutoPtr<IShaderResourceBinding> MeshSRB; + pSignatureMS->CreateShaderResourceBinding(&MeshSRB, true); + ASSERT_NE(MeshSRB, nullptr); + + PixelSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_Texture")->Set(pTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); + VertexSRB->GetVariableByName(SHADER_TYPE_VERTEX, "Constants")->Set(pConstBuf); + MeshSRB->GetVariableByName(SHADER_TYPE_MESH, "Constants")->Set(pConstBuf); + + ITextureView* ppRTVs[] = {pRTV}; + pContext->SetRenderTargets(1, ppRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + + // draw triangles + pContext->CommitShaderResources(PixelSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pContext->CommitShaderResources(VertexSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + + pContext->SetPipelineState(pGraphicsPSO); + + DrawAttribs drawAttrs(3, DRAW_FLAG_VERIFY_ALL); + pContext->Draw(drawAttrs); + + // draw meshes + pContext->CommitShaderResources(MeshSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + // reuse PixelSRB + + pContext->SetPipelineState(pMeshPSO); + + DrawMeshAttribs drawMeshAttrs(1, DRAW_FLAG_VERIFY_ALL); + pContext->DrawMesh(drawMeshAttrs); +} } // namespace Diligent |
