From 8dad2a0be3016a1fb9c5720ff17674a9e8205a8e Mon Sep 17 00:00:00 2001 From: hzqst <113660872@qq.com> Date: Mon, 12 Jan 2026 11:44:11 +0800 Subject: [PATCH 1/5] Add CrossSignatureSRB test --- .../src/InlineConstantsTest.cpp | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp b/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp index ea976cf0f..12c1fdbac 100644 --- a/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp +++ b/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp @@ -839,6 +839,180 @@ TEST_F(InlineConstants, TwoResourceSignatures) TestSignatures(2); } +// Test for "Inline Constants Cross-Signature Commit Inconsistency" fix. +// +// This test verifies that inline constants work correctly when an SRB created +// from one signature is used with a PSO created from a different but compatible +// signature instance. +// +// Bug scenario: +// 1. PSO is created with Signature A +// 2. SRB is created from Signature B (compatible but different instance) +// 3. Inline constants are set through SRB +// 4. BindResources() binds buffers from SRB cache (pointing to Signature B's buffers) +// 5. BUG (fixed): UpdateInlineConstantBuffers() was updating Signature A's buffers +// instead of the buffers from SRB cache +// +// The fix ensures that UpdateInlineConstantBuffers() updates the buffer from +// SRB cache - the same buffer that was bound during BindResources(). +// +// In Vulkan, only the first inline constant uses push constants (always works). +// The second inline constant uses buffer-emulated path where this bug manifested. +// Therefore, this test uses TWO inline constant buffers to ensure we test both paths. +TEST_F(InlineConstants, CrossSignatureSRB) +{ + GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance(); + IRenderDevice* pDevice = pEnv->GetDevice(); + IDeviceContext* pContext = pEnv->GetDeviceContext(); + ISwapChain* pSwapChain = pEnv->GetSwapChain(); + + // Test all variable types to ensure complete coverage + for (Uint32 pos_type = 0; pos_type < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; ++pos_type) + { + for (Uint32 col_type = 0; col_type < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; ++col_type) + { + const float ClearColor[] = {sm_Rnd(), sm_Rnd(), sm_Rnd(), sm_Rnd()}; + RenderDrawCommandReference(pSwapChain, ClearColor); + + SHADER_RESOURCE_VARIABLE_TYPE PosType = static_cast(pos_type); + SHADER_RESOURCE_VARIABLE_TYPE ColType = static_cast(col_type); + + // Create TWO IDENTICAL but SEPARATE signature instances + // This is the key to reproducing the cross-signature issue: + // - pSign1 and pSign2 are compatible (same resources) + // - But they are different instances with separate internal buffers + RefCntAutoPtr pSign1, pSign2; + + PipelineResourceSignatureDescX SignDesc{"Cross-Signature Test"}; + SignDesc + // First inline constant (Vulkan: push constants path) + .AddResource(SHADER_TYPE_VERTEX, "cbInlinePositions", kNumPosConstants, + SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, PosType, + PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS) + // Second inline constant (Vulkan: buffer-emulated path - where the bug was) + .AddResource(SHADER_TYPE_VS_PS, "cbInlineColors", kNumColConstants, + SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, ColType, + PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS); + SignDesc.SetSRBAllocationGranularity(4); + + // Create first signature instance + pDevice->CreatePipelineResourceSignature(SignDesc, &pSign1); + ASSERT_TRUE(pSign1); + + // Create second signature instance with identical descriptor + // This creates a separate instance with its own internal buffers + pDevice->CreatePipelineResourceSignature(SignDesc, &pSign2); + ASSERT_TRUE(pSign2); + + // IMPORTANT: pSign1 and pSign2 are compatible but have separate buffer allocations + // Using an SRB from pSign2 with a PSO from pSign1 tests the cross-signature path + + // Create PSO using signature 1 + GraphicsPipelineStateCreateInfoX PsoCI{"Cross-Signature Test"}; + PsoCI + .AddRenderTarget(pSwapChain->GetDesc().ColorBufferFormat) + .SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) + .AddShader(sm_Res.pVS) + .AddShader(sm_Res.pPS) + .AddSignature(pSign1); // PSO uses signature 1 + PsoCI.GraphicsPipeline.DepthStencilDesc.DepthEnable = False; + + RefCntAutoPtr pPSO; + pDevice->CreateGraphicsPipelineState(PsoCI, &pPSO); + ASSERT_TRUE(pPSO); + + // For STATIC variables, set on signature 2 (which will be used for SRB) + if (PosType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC) + { + IShaderResourceVariable* pVar = pSign2->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions"); + ASSERT_TRUE(pVar); + pVar->SetInlineConstants(g_Positions, 0, kNumPosConstants); + } + + if (ColType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC) + { + IShaderResourceVariable* pVar = pSign2->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors"); + ASSERT_TRUE(pVar); + pVar->SetInlineConstants(g_Colors, 0, kNumColConstants); + } + + // Create SRB from signature 2 (DIFFERENT from PSO's signature!) + // This is the critical part: SRB is from pSign2, PSO is from pSign1 + RefCntAutoPtr pSRB; + pSign2->CreateShaderResourceBinding(&pSRB, true); + ASSERT_TRUE(pSRB); + + // Verify the SRB is compatible with PSO (they should be, since signatures are identical) + // Note: IsCompatibleWith checks signature compatibility + EXPECT_TRUE(pPSO->IsCompatibleWith(pSign2)); + + IShaderResourceVariable* pPosVar = nullptr; + IShaderResourceVariable* pColVarVS = nullptr; + IShaderResourceVariable* pColVarPS = nullptr; + + if (PosType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC) + { + pPosVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions"); + ASSERT_TRUE(pPosVar); + } + + if (ColType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC) + { + pColVarVS = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors"); + ASSERT_TRUE(pColVarVS); + pColVarPS = pSRB->GetVariableByName(SHADER_TYPE_PIXEL, "cbInlineColors"); + ASSERT_TRUE(pColVarPS); + } + + ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()}; + pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pContext->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + + // Set first half of color constants BEFORE CommitShaderResources + if (pColVarVS != nullptr) + { + pColVarVS->SetInlineConstants(g_Colors, 0, kNumColConstants / 2); + } + + pContext->SetPipelineState(pPSO); + pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + + // Set second half of color constants AFTER CommitShaderResources but BEFORE Draw + // This is the specific timing that triggered the original bug: + // - CommitShaderResources binds buffers from SRB cache + // - SetInlineConstants writes to CPU staging + // - Draw triggers UpdateInlineConstantBuffers which must update the CORRECT buffer + if (pColVarPS != nullptr) + { + pColVarPS->SetInlineConstants(g_Colors[0].Data() + kNumColConstants / 2, + kNumColConstants / 2, kNumColConstants / 2); + } + + if (pPosVar == nullptr) + { + // Draw both triangles as positions are static + pContext->Draw({6, DRAW_FLAG_VERIFY_ALL}); + } + else + { + // Draw first triangle + pPosVar->SetInlineConstants(g_Positions, 0, kNumPosConstants / 2); + pContext->Draw({3, DRAW_FLAG_VERIFY_ALL}); + + // Draw second triangle - also tests update after CommitShaderResources + pPosVar->SetInlineConstants(g_Positions[0].Data() + kNumPosConstants / 2, 0, kNumPosConstants / 2); + pContext->Draw({3, DRAW_FLAG_VERIFY_ALL}); + } + + Present(); + + std::cout << TestingEnvironment::GetCurrentTestStatusString() << ' ' + << " Pos " << GetShaderVariableTypeLiteralName(PosType) << ',' + << " Col " << GetShaderVariableTypeLiteralName(ColType) << std::endl; + } + } +} + constexpr Uint32 kCacheContentVersion = 7; RefCntAutoPtr CreateCache(IRenderDevice* pDevice, From b155663f29e3fbc87eec63064298b57a9cfc73d7 Mon Sep 17 00:00:00 2001 From: hzqst <113660872@qq.com> Date: Mon, 12 Jan 2026 11:48:52 +0800 Subject: [PATCH 2/5] Fix typo --- Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp b/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp index 12c1fdbac..70105fadb 100644 --- a/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp +++ b/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp @@ -942,9 +942,8 @@ TEST_F(InlineConstants, CrossSignatureSRB) pSign2->CreateShaderResourceBinding(&pSRB, true); ASSERT_TRUE(pSRB); - // Verify the SRB is compatible with PSO (they should be, since signatures are identical) - // Note: IsCompatibleWith checks signature compatibility - EXPECT_TRUE(pPSO->IsCompatibleWith(pSign2)); + // Verify the signatures are compatible (they should be, since descriptors are identical) + EXPECT_TRUE(pSign1->IsCompatibleWith(pSign2)); IShaderResourceVariable* pPosVar = nullptr; IShaderResourceVariable* pColVarVS = nullptr; From 2335562c1427b0e523f46736fc4d3fbef9756ea8 Mon Sep 17 00:00:00 2001 From: hzqst <113660872@qq.com> Date: Mon, 12 Jan 2026 12:08:25 +0800 Subject: [PATCH 3/5] Fix https://github.com/hzqst/DiligentCore/blob/inline_constants_claude/plan/SetInlineConstants_InconsistencyCommit.md --- .../src/PipelineResourceSignatureVkImpl.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp index c0310ed23..7845a47ab 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp @@ -1146,13 +1146,18 @@ void PipelineResourceSignatureVkImpl::CommitInlineConstants(const CommitInlineCo } else { - VERIFY_EXPR(InlineCBAttr.pBuffer); + // Get the buffer from the SRB cache (not from the signature's InlineCBAttr.pBuffer). - // Map the shared buffer and copy the data + const ShaderResourceCacheVk::DescriptorSet& DescrSet = ResourceCache.GetDescriptorSet(InlineCBAttr.DescrSet); + const ShaderResourceCacheVk::Resource& CachedRes = DescrSet.GetResource(InlineCBAttr.SRBCacheOffset); + BufferVkImpl* pBuffer = CachedRes.pObject.RawPtr(); + VERIFY(pBuffer != nullptr, "Inline constant buffer is null in SRB cache"); + + // Map the buffer from SRB cache and copy the data void* pMappedData = nullptr; - Attribs.Ctx.MapBuffer(InlineCBAttr.pBuffer, MAP_WRITE, MAP_FLAG_DISCARD, pMappedData); + Attribs.Ctx.MapBuffer(pBuffer, MAP_WRITE, MAP_FLAG_DISCARD, pMappedData); memcpy(pMappedData, pInlineConstantData, DataSize); - Attribs.Ctx.UnmapBuffer(InlineCBAttr.pBuffer, MAP_WRITE); + Attribs.Ctx.UnmapBuffer(pBuffer, MAP_WRITE); } } } From 8ee1e0158036beb5e8e9c64ac9873175b7fe9327 Mon Sep 17 00:00:00 2001 From: hzqst <113660872@qq.com> Date: Mon, 12 Jan 2026 13:44:35 +0800 Subject: [PATCH 4/5] simplify CrossSignatureSRB test. --- .../src/InlineConstantsTest.cpp | 197 ++++++------------ 1 file changed, 63 insertions(+), 134 deletions(-) diff --git a/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp b/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp index 70105fadb..bdda47893 100644 --- a/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp +++ b/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp @@ -866,150 +866,79 @@ TEST_F(InlineConstants, CrossSignatureSRB) IDeviceContext* pContext = pEnv->GetDeviceContext(); ISwapChain* pSwapChain = pEnv->GetSwapChain(); - // Test all variable types to ensure complete coverage - for (Uint32 pos_type = 0; pos_type < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; ++pos_type) - { - for (Uint32 col_type = 0; col_type < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; ++col_type) - { - const float ClearColor[] = {sm_Rnd(), sm_Rnd(), sm_Rnd(), sm_Rnd()}; - RenderDrawCommandReference(pSwapChain, ClearColor); - - SHADER_RESOURCE_VARIABLE_TYPE PosType = static_cast(pos_type); - SHADER_RESOURCE_VARIABLE_TYPE ColType = static_cast(col_type); - - // Create TWO IDENTICAL but SEPARATE signature instances - // This is the key to reproducing the cross-signature issue: - // - pSign1 and pSign2 are compatible (same resources) - // - But they are different instances with separate internal buffers - RefCntAutoPtr pSign1, pSign2; - - PipelineResourceSignatureDescX SignDesc{"Cross-Signature Test"}; - SignDesc - // First inline constant (Vulkan: push constants path) - .AddResource(SHADER_TYPE_VERTEX, "cbInlinePositions", kNumPosConstants, - SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, PosType, - PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS) - // Second inline constant (Vulkan: buffer-emulated path - where the bug was) - .AddResource(SHADER_TYPE_VS_PS, "cbInlineColors", kNumColConstants, - SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, ColType, - PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS); - SignDesc.SetSRBAllocationGranularity(4); - - // Create first signature instance - pDevice->CreatePipelineResourceSignature(SignDesc, &pSign1); - ASSERT_TRUE(pSign1); - - // Create second signature instance with identical descriptor - // This creates a separate instance with its own internal buffers - pDevice->CreatePipelineResourceSignature(SignDesc, &pSign2); - ASSERT_TRUE(pSign2); - - // IMPORTANT: pSign1 and pSign2 are compatible but have separate buffer allocations - // Using an SRB from pSign2 with a PSO from pSign1 tests the cross-signature path - - // Create PSO using signature 1 - GraphicsPipelineStateCreateInfoX PsoCI{"Cross-Signature Test"}; - PsoCI - .AddRenderTarget(pSwapChain->GetDesc().ColorBufferFormat) - .SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) - .AddShader(sm_Res.pVS) - .AddShader(sm_Res.pPS) - .AddSignature(pSign1); // PSO uses signature 1 - PsoCI.GraphicsPipeline.DepthStencilDesc.DepthEnable = False; - - RefCntAutoPtr pPSO; - pDevice->CreateGraphicsPipelineState(PsoCI, &pPSO); - ASSERT_TRUE(pPSO); - - // For STATIC variables, set on signature 2 (which will be used for SRB) - if (PosType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC) - { - IShaderResourceVariable* pVar = pSign2->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions"); - ASSERT_TRUE(pVar); - pVar->SetInlineConstants(g_Positions, 0, kNumPosConstants); - } - - if (ColType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC) - { - IShaderResourceVariable* pVar = pSign2->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors"); - ASSERT_TRUE(pVar); - pVar->SetInlineConstants(g_Colors, 0, kNumColConstants); - } - - // Create SRB from signature 2 (DIFFERENT from PSO's signature!) - // This is the critical part: SRB is from pSign2, PSO is from pSign1 - RefCntAutoPtr pSRB; - pSign2->CreateShaderResourceBinding(&pSRB, true); - ASSERT_TRUE(pSRB); - - // Verify the signatures are compatible (they should be, since descriptors are identical) - EXPECT_TRUE(pSign1->IsCompatibleWith(pSign2)); - - IShaderResourceVariable* pPosVar = nullptr; - IShaderResourceVariable* pColVarVS = nullptr; - IShaderResourceVariable* pColVarPS = nullptr; + const float ClearColor[] = {sm_Rnd(), sm_Rnd(), sm_Rnd(), sm_Rnd()}; + RenderDrawCommandReference(pSwapChain, ClearColor); - if (PosType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC) - { - pPosVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions"); - ASSERT_TRUE(pPosVar); - } + // Create TWO IDENTICAL but SEPARATE signature instances. + // This is the key to reproducing the cross-signature issue: + // - pSign1 and pSign2 are compatible (same resources) + // - But they are different instances with separate internal buffers + RefCntAutoPtr pSign1, pSign2; + + PipelineResourceSignatureDescX SignDesc{"Cross-Signature Test"}; + SignDesc + // First inline constant (Vulkan: push constants path) + .AddResource(SHADER_TYPE_VERTEX, "cbInlinePositions", kNumPosConstants, + SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, + PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS) + // Second inline constant (Vulkan: buffer-emulated path - where the bug was) + .AddResource(SHADER_TYPE_VS_PS, "cbInlineColors", kNumColConstants, + SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, + PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS); + + // Create first signature instance + pDevice->CreatePipelineResourceSignature(SignDesc, &pSign1); + ASSERT_TRUE(pSign1); + + // Create second signature instance with identical descriptor. + // This creates a separate instance with its own internal buffers. + pDevice->CreatePipelineResourceSignature(SignDesc, &pSign2); + ASSERT_TRUE(pSign2); + + // IMPORTANT: pSign1 and pSign2 are compatible but have separate buffer allocations. + // Using an SRB from pSign2 with a PSO from pSign1 tests the cross-signature path. + EXPECT_TRUE(pSign1->IsCompatibleWith(pSign2)); + + // Create PSO using signature 1 + GraphicsPipelineStateCreateInfoX PsoCI{"Cross-Signature Test"}; + PsoCI + .AddRenderTarget(pSwapChain->GetDesc().ColorBufferFormat) + .SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) + .AddShader(sm_Res.pVS) + .AddShader(sm_Res.pPS) + .AddSignature(pSign1); // PSO uses signature 1 + PsoCI.GraphicsPipeline.DepthStencilDesc.DepthEnable = False; - if (ColType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC) - { - pColVarVS = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors"); - ASSERT_TRUE(pColVarVS); - pColVarPS = pSRB->GetVariableByName(SHADER_TYPE_PIXEL, "cbInlineColors"); - ASSERT_TRUE(pColVarPS); - } + RefCntAutoPtr pPSO; + pDevice->CreateGraphicsPipelineState(PsoCI, &pPSO); + ASSERT_TRUE(pPSO); - ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()}; - pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pContext->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + // Create SRB from signature 2 (DIFFERENT from PSO's signature!). + // This is the critical part: SRB is from pSign2, PSO is from pSign1. + RefCntAutoPtr pSRB; + pSign2->CreateShaderResourceBinding(&pSRB, true); + ASSERT_TRUE(pSRB); - // Set first half of color constants BEFORE CommitShaderResources - if (pColVarVS != nullptr) - { - pColVarVS->SetInlineConstants(g_Colors, 0, kNumColConstants / 2); - } + IShaderResourceVariable* pPosVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions"); + ASSERT_TRUE(pPosVar); - pContext->SetPipelineState(pPSO); - pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + IShaderResourceVariable* pColVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors"); + ASSERT_TRUE(pColVar); - // Set second half of color constants AFTER CommitShaderResources but BEFORE Draw - // This is the specific timing that triggered the original bug: - // - CommitShaderResources binds buffers from SRB cache - // - SetInlineConstants writes to CPU staging - // - Draw triggers UpdateInlineConstantBuffers which must update the CORRECT buffer - if (pColVarPS != nullptr) - { - pColVarPS->SetInlineConstants(g_Colors[0].Data() + kNumColConstants / 2, - kNumColConstants / 2, kNumColConstants / 2); - } + ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()}; + pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pContext->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - if (pPosVar == nullptr) - { - // Draw both triangles as positions are static - pContext->Draw({6, DRAW_FLAG_VERIFY_ALL}); - } - else - { - // Draw first triangle - pPosVar->SetInlineConstants(g_Positions, 0, kNumPosConstants / 2); - pContext->Draw({3, DRAW_FLAG_VERIFY_ALL}); + pContext->SetPipelineState(pPSO); - // Draw second triangle - also tests update after CommitShaderResources - pPosVar->SetInlineConstants(g_Positions[0].Data() + kNumPosConstants / 2, 0, kNumPosConstants / 2); - pContext->Draw({3, DRAW_FLAG_VERIFY_ALL}); - } + // Set inline constants and draw + pPosVar->SetInlineConstants(g_Positions, 0, kNumPosConstants); + pColVar->SetInlineConstants(g_Colors, 0, kNumColConstants); - Present(); + pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pContext->Draw({6, DRAW_FLAG_VERIFY_ALL}); - std::cout << TestingEnvironment::GetCurrentTestStatusString() << ' ' - << " Pos " << GetShaderVariableTypeLiteralName(PosType) << ',' - << " Col " << GetShaderVariableTypeLiteralName(ColType) << std::endl; - } - } + Present(); } constexpr Uint32 kCacheContentVersion = 7; From 24481a8f3c751b0be3cecae1cc16722b9f3809fe Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 12 Jan 2026 09:47:24 -0800 Subject: [PATCH 5/5] Make the test actually reproduce the problem --- .../src/InlineConstantsTest.cpp | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp b/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp index bdda47893..83d579267 100644 --- a/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp +++ b/Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp @@ -32,7 +32,7 @@ #include "RenderStateCache.hpp" #include "GraphicsTypesX.hpp" #include "FastRand.hpp" - +#include "MapHelper.hpp" namespace Diligent @@ -875,14 +875,14 @@ TEST_F(InlineConstants, CrossSignatureSRB) // - But they are different instances with separate internal buffers RefCntAutoPtr pSign1, pSign2; - PipelineResourceSignatureDescX SignDesc{"Cross-Signature Test"}; + PipelineResourceSignatureDescX SignDesc{"Cross-Signature Test 1"}; SignDesc // First inline constant (Vulkan: push constants path) - .AddResource(SHADER_TYPE_VERTEX, "cbInlinePositions", kNumPosConstants, + .AddResource(SHADER_TYPE_VS_PS, "cbInlineColors", kNumColConstants, SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS) // Second inline constant (Vulkan: buffer-emulated path - where the bug was) - .AddResource(SHADER_TYPE_VS_PS, "cbInlineColors", kNumColConstants, + .AddResource(SHADER_TYPE_VERTEX, "cbInlinePositions", kNumPosConstants, SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS); @@ -892,8 +892,10 @@ TEST_F(InlineConstants, CrossSignatureSRB) // Create second signature instance with identical descriptor. // This creates a separate instance with its own internal buffers. + SignDesc.SetName("Cross-Signature Test 2"); pDevice->CreatePipelineResourceSignature(SignDesc, &pSign2); ASSERT_TRUE(pSign2); + EXPECT_NE(pSign1, pSign2); // IMPORTANT: pSign1 and pSign2 are compatible but have separate buffer allocations. // Using an SRB from pSign2 with a PSO from pSign1 tests the cross-signature path. @@ -925,18 +927,28 @@ TEST_F(InlineConstants, CrossSignatureSRB) IShaderResourceVariable* pColVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors"); ASSERT_TRUE(pColVar); + // Create a dummy dynamic buffer and map it to allocate dynamic space and make sure + // that dynamic offset is non-zero in Vulkan backend. + RefCntAutoPtr pDummyCB = pEnv->CreateBuffer({"InlineConstants - dummy const buffer", 256, BIND_UNIFORM_BUFFER, USAGE_DYNAMIC, CPU_ACCESS_WRITE}); + { + MapHelper pData{pContext, pDummyCB, MAP_WRITE, MAP_FLAG_DISCARD}; + } + ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()}; pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); pContext->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); pContext->SetPipelineState(pPSO); + pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); // Set inline constants and draw - pPosVar->SetInlineConstants(g_Positions, 0, kNumPosConstants); pColVar->SetInlineConstants(g_Colors, 0, kNumColConstants); - pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pContext->Draw({6, DRAW_FLAG_VERIFY_ALL}); + pPosVar->SetInlineConstants(g_Positions, 0, kNumPosConstants / 2); + pContext->Draw({3, DRAW_FLAG_VERIFY_ALL}); + + pPosVar->SetInlineConstants(g_Positions[0].Data() + kNumPosConstants / 2, 0, kNumPosConstants / 2); + pContext->Draw({3, DRAW_FLAG_VERIFY_ALL}); Present(); }