diff --git a/renderdoc/driver/vulkan/vk_pixelhistory.cpp b/renderdoc/driver/vulkan/vk_pixelhistory.cpp index 40ce891b3..b6c452df6 100644 --- a/renderdoc/driver/vulkan/vk_pixelhistory.cpp +++ b/renderdoc/driver/vulkan/vk_pixelhistory.cpp @@ -448,17 +448,15 @@ protected: const VulkanCreationInfo::Pipeline &p = m_pDriver->GetDebugManager()->GetPipelineInfo(pipe); m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(pipeCreateInfo, pipe); + // make state we want to control dynamic + AddDynamicStates(pipeCreateInfo); + VkPipelineRasterizationStateCreateInfo *rs = (VkPipelineRasterizationStateCreateInfo *)pipeCreateInfo.pRasterizationState; VkPipelineDepthStencilStateCreateInfo *ds = (VkPipelineDepthStencilStateCreateInfo *)pipeCreateInfo.pDepthStencilState; VkPipelineMultisampleStateCreateInfo *ms = (VkPipelineMultisampleStateCreateInfo *)pipeCreateInfo.pMultisampleState; - VkPipelineViewportStateCreateInfo *vs = - (VkPipelineViewportStateCreateInfo *)pipeCreateInfo.pViewportState; - - VkRect2D newScissors[16]; - memset(newScissors, 0, sizeof(newScissors)); // TODO: should leave in the original state. ds->depthTestEnable = VK_FALSE; @@ -489,22 +487,6 @@ protected: // Narrow on the specific pixel and sample. { ms->pSampleMask = &m_CallbackInfo.sampleMask; - - // Change scissors unless they are set dynamically. - if(p.dynamicStates[VkDynamicScissor]) - { - VulkanRenderState &pipestate = m_pDriver->GetCmdRenderState(); - for(uint32_t i = 0; i < pipestate.views.size(); i++) - ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); - } - else - { - for(uint32_t i = 0; i < vs->viewportCount; i++) - { - ScissorToPixel(vs->pViewports[i], newScissors[i]); - } - vs->pScissors = newScissors; - } } // Turn off all color modifications. @@ -543,6 +525,34 @@ protected: pipeCreateInfo.pStages = stages.data(); } + // ensures the state we want to control is dynamic, whether or not it was dynamic in the original + // pipeline + void AddDynamicStates(VkGraphicsPipelineCreateInfo &pipeCreateInfo) + { + // we need to add it. Check if the dynamic state is already pointing to our internal array (in + // the case of adding multiple dynamic states in a row), and otherwise initialise our array from + // it and repoint. Then we can add the new state + VkPipelineDynamicStateCreateInfo *dynState = + (VkPipelineDynamicStateCreateInfo *)pipeCreateInfo.pDynamicState; + + // copy over the original dynamic states + m_DynamicStates.assign(dynState->pDynamicStates, dynState->dynamicStateCount); + + // add the ones we want + if(!m_DynamicStates.contains(VK_DYNAMIC_STATE_SCISSOR)) + m_DynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR); + if(!m_DynamicStates.contains(VK_DYNAMIC_STATE_STENCIL_REFERENCE)) + m_DynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE); + if(!m_DynamicStates.contains(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK)) + m_DynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK); + if(!m_DynamicStates.contains(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)) + m_DynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK); + + // now point at our storage for the array + dynState->pDynamicStates = m_DynamicStates.data(); + dynState->dynamicStateCount = (uint32_t)m_DynamicStates.size(); + } + // CreateRenderPass creates a new VkRenderPass based on the original that has a separate // depth-stencil attachment, and covers a single subpass. This will be used to replay // a single draw. The new renderpass also replaces the depth stencil attachment, so @@ -873,6 +883,7 @@ protected: VkQueryPool m_OcclusionPool; rdcarray m_RpsToDestroy; rdcarray m_FbsToDestroy; + rdcarray m_DynamicStates; }; // VulkanOcclusionCallback callback is used to determine which draw events might have @@ -900,8 +911,6 @@ struct VulkanOcclusionCallback : public VulkanPixelHistoryCallback return; VulkanRenderState prevState = m_pDriver->GetCmdRenderState(); VulkanRenderState &pipestate = m_pDriver->GetCmdRenderState(); - const VulkanCreationInfo::Pipeline &p = - m_pDriver->GetDebugManager()->GetPipelineInfo(pipestate.graphics.pipeline); uint32_t framebufferIndex = 0; const rdcarray &atts = pipestate.GetFramebufferAttachments(); @@ -915,9 +924,13 @@ struct VulkanOcclusionCallback : public VulkanPixelHistoryCallback } } VkPipeline pipe = GetPixelOcclusionPipeline(eid, prevState.graphics.pipeline, framebufferIndex); - if(p.dynamicStates[VkDynamicScissor]) - for(uint32_t i = 0; i < pipestate.views.size(); i++) - ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); + // set the scissor + for(uint32_t i = 0; i < pipestate.views.size(); i++) + ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); + // set stencil state (though it's unused here) + pipestate.front.compare = pipestate.front.write = 0xff; + pipestate.front.ref = 0; + pipestate.back = pipestate.front; pipestate.graphics.pipeline = GetResID(pipe); ReplayDrawWithQuery(cmd, eid); @@ -1099,11 +1112,8 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback PipelineReplacements replacements = GetPipelineReplacements(eid, pipestate.graphics.pipeline, newRp, framebufferIndex); - const VulkanCreationInfo::Pipeline &p = - m_pDriver->GetDebugManager()->GetPipelineInfo(pipestate.graphics.pipeline); - if(p.dynamicStates[VkDynamicScissor]) - for(uint32_t i = 0; i < pipestate.views.size(); i++) - ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); + for(uint32_t i = 0; i < pipestate.views.size(); i++) + ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); // TODO: should fill depth value from the original DS attachment. @@ -1114,6 +1124,9 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback pipestate.renderPass = GetResID(newRp); pipestate.subpass = 0; pipestate.graphics.pipeline = GetResID(replacements.fixedShaderStencil); + pipestate.front.compare = pipestate.front.write = 0xff; + pipestate.front.ref = 0; + pipestate.back = pipestate.front; ReplayDraw(cmd, eid, true); CopyPixelParams params = {}; @@ -1685,20 +1698,17 @@ private: m_ShaderCache->GetShaderWithoutSideEffects(p.shaders[i].module, p.shaders[i].entryPoint); } - bool dynamicScissor = p.dynamicStates[VkDynamicScissor]; VulkanRenderState &pipestate = m_pDriver->GetCmdRenderState(); rdcarray prevScissors = pipestate.scissors; - if(dynamicScissor) - for(uint32_t i = 0; i < pipestate.views.size(); i++) - ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); + for(uint32_t i = 0; i < pipestate.views.size(); i++) + ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); if(eventFlags & TestEnabled_Culling) { uint32_t pipeFlags = PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_DisableDepthBoundsTest | PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_FixedColorShader; - VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders, - framebufferIndex); + VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, framebufferIndex); ReplayDraw(cmd, pipe, eid, TestEnabled_Culling); } @@ -1712,13 +1722,11 @@ private: PipelineCreationFlags_IntersectOriginalScissor | PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_DisableDepthBoundsTest | PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_FixedColorShader; - VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders, - framebufferIndex); - // This will change the dynamic scissor state for the later tests, but since those + VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, framebufferIndex); + // This will change the scissor for the later tests, but since those // tests happen later in the pipeline, it does not matter. - if(dynamicScissor) - for(uint32_t i = 0; i < pipestate.views.size(); i++) - IntersectScissors(prevScissors[i], pipestate.scissors[i]); + for(uint32_t i = 0; i < pipestate.views.size(); i++) + IntersectScissors(prevScissors[i], pipestate.scissors[i]); ReplayDraw(cmd, pipe, eid, TestEnabled_Scissor); } @@ -1731,8 +1739,7 @@ private: uint32_t pipeFlags = PipelineCreationFlags_DisableDepthBoundsTest | PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_FixedColorShader; - VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders, - framebufferIndex); + VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, framebufferIndex); ReplayDraw(cmd, pipe, eid, TestEnabled_SampleMask); } @@ -1742,8 +1749,7 @@ private: uint32_t pipeFlags = PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_FixedColorShader; - VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders, - framebufferIndex); + VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, framebufferIndex); ReplayDraw(cmd, pipe, eid, TestEnabled_DepthBounds); } @@ -1755,8 +1761,7 @@ private: { uint32_t pipeFlags = PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_FixedColorShader; - VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders, - framebufferIndex); + VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, framebufferIndex); ReplayDraw(cmd, pipe, eid, TestEnabled_StencilTesting); } @@ -1771,8 +1776,7 @@ private: uint32_t pipeFlags = PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_FixedColorShader; - VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders, - framebufferIndex); + VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, framebufferIndex); ReplayDraw(cmd, pipe, eid, TestEnabled_DepthTesting); } @@ -1785,8 +1789,7 @@ private: uint32_t pipeFlags = PipelineCreationFlags_DisableDepthBoundsTest | PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_DisableDepthTest; - VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders, - framebufferIndex); + VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, framebufferIndex); ReplayDraw(cmd, pipe, eid, TestEnabled_FragmentDiscard); } } @@ -1794,7 +1797,7 @@ private: // Creates a pipeline that is based on the given pipeline and the given // pipeline flags. Modifies the base pipeline according to the flags, and // leaves the original pipeline behavior if a flag is not set. - VkPipeline CreatePipeline(ResourceId basePipeline, uint32_t pipeCreateFlags, bool dynamicScissor, + VkPipeline CreatePipeline(ResourceId basePipeline, uint32_t pipeCreateFlags, const rdcarray &replacementShaders, uint32_t framebufferIndex) { @@ -1810,10 +1813,11 @@ private: (VkPipelineRasterizationStateCreateInfo *)ci.pRasterizationState; VkPipelineDepthStencilStateCreateInfo *ds = (VkPipelineDepthStencilStateCreateInfo *)ci.pDepthStencilState; - VkPipelineViewportStateCreateInfo *vs = (VkPipelineViewportStateCreateInfo *)ci.pViewportState; VkPipelineMultisampleStateCreateInfo *ms = (VkPipelineMultisampleStateCreateInfo *)ci.pMultisampleState; + AddDynamicStates(ci); + // Only interested in a single sample. ms->pSampleMask = &m_CallbackInfo.sampleMask; // We are going to replay a draw multiple times, don't want to modify the @@ -1848,17 +1852,6 @@ private: } ci.pStages = stages.data(); - if(!dynamicScissor) - { - VkRect2D *pScissors = (VkRect2D *)vs->pScissors; - for(uint32_t i = 0; i < vs->viewportCount; i++) - { - ScissorToPixel(vs->pViewports[i], pScissors[i]); - if(pipeCreateFlags & PipelineCreationFlags_IntersectOriginalScissor) - IntersectScissors(vs->pScissors[i], pScissors[i]); - } - } - VkPipeline pipe; VkResult vkr = m_pDriver->vkCreateGraphicsPipelines(m_pDriver->GetDev(), VK_NULL_HANDLE, 1, &ci, NULL, &pipe); @@ -1965,7 +1958,10 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback } } - Pipelines pipes = CreatePerFragmentPipelines(curPipeline, newRp, eid, false, 0, framebufferIndex); + Pipelines pipes = CreatePerFragmentPipelines(curPipeline, newRp, eid, 0, framebufferIndex); + + for(uint32_t i = 0; i < state.views.size(); i++) + ScissorToPixel(state.views[i], state.scissors[i]); state.renderPass = GetResID(newRp); state.SetFramebuffer(m_pDriver, GetResID(newFb)); @@ -2035,6 +2031,8 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback // Update stencil reference to the current fragment index, so that we get values // for a single fragment only. + ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff); + ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff); ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, f); const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eid); if(drawcall->flags & DrawFlags::Indexed) @@ -2112,6 +2110,8 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback ObjDisp(cmd)->CmdClearAttachments(Unwrap(cmd), 2, clearAtts, 1, &rect); } + ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff); + ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff); ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, f); const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eid); if(drawcall->flags & DrawFlags::Indexed) @@ -2150,20 +2150,19 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback void PostRedraw(uint32_t eid, VkCommandBuffer cmd) {} // CreatePerFragmentPipelines for getting per fragment information. Pipelines CreatePerFragmentPipelines(ResourceId pipe, VkRenderPass rp, uint32_t eid, - bool dynamicScissor, uint32_t fragmentIndex, - uint32_t framebufferIndex) + uint32_t fragmentIndex, uint32_t framebufferIndex) { const VulkanCreationInfo::Pipeline &p = m_pDriver->GetDebugManager()->GetPipelineInfo(pipe); VkGraphicsPipelineCreateInfo pipeCreateInfo = {}; rdcarray stages; m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(pipeCreateInfo, pipe); + AddDynamicStates(pipeCreateInfo); + VkPipelineDepthStencilStateCreateInfo *ds = (VkPipelineDepthStencilStateCreateInfo *)pipeCreateInfo.pDepthStencilState; VkPipelineMultisampleStateCreateInfo *ms = (VkPipelineMultisampleStateCreateInfo *)pipeCreateInfo.pMultisampleState; - VkPipelineViewportStateCreateInfo *vs = - (VkPipelineViewportStateCreateInfo *)pipeCreateInfo.pViewportState; VkRect2D newScissors[16]; memset(newScissors, 0, sizeof(newScissors)); @@ -2180,22 +2179,6 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback ds->back = ds->front; ms->pSampleMask = &m_CallbackInfo.sampleMask; - - // Change scissors unless they are set dynamically. - if(p.dynamicStates[VkDynamicScissor]) - { - VulkanRenderState &pipestate = m_pDriver->GetCmdRenderState(); - for(uint32_t i = 0; i < pipestate.views.size(); i++) - ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); - } - else - { - for(uint32_t i = 0; i < vs->viewportCount; i++) - { - ScissorToPixel(vs->pViewports[i], newScissors[i]); - } - vs->pScissors = newScissors; - } } // TODO: this is wrong, should take into account subpass. @@ -2377,6 +2360,8 @@ struct VulkanPixelHistoryDiscardedFragmentsCallback : VulkanPixelHistoryCallback VulkanRenderState &state = m_pDriver->GetCmdRenderState(); // Create a pipeline with a scissor and colorWriteMask = 0, and disable all tests. VkPipeline newPipe = CreatePipeline(state.graphics.pipeline, eid); + for(uint32_t i = 0; i < state.views.size(); i++) + ScissorToPixel(state.views[i], state.scissors[i]); state.graphics.pipeline = GetResID(newPipe); state.BindPipeline(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); for(uint32_t i = 0; i < primIds.size(); i++) diff --git a/util/test/demos/vk/vk_pixel_history_test.cpp b/util/test/demos/vk/vk_pixel_history_test.cpp index 425d9b116..284a8cb76 100644 --- a/util/test/demos/vk/vk_pixel_history_test.cpp +++ b/util/test/demos/vk/vk_pixel_history_test.cpp @@ -178,6 +178,23 @@ void main() {Vec3f(0.0f, -0.7f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, {Vec3f(0.0f, -0.725f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, {Vec3f(0.025f, -0.7f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + + // dynamic triangles + {Vec3f(-0.6f, 0.75f, 0.5f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, + {Vec3f(-0.5f, 0.65f, 0.5f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, + {Vec3f(-0.4f, 0.75f, 0.5f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + + {Vec3f(-0.6f, 0.75f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, + {Vec3f(-0.5f, 0.65f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, + {Vec3f(-0.4f, 0.75f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + + {Vec3f(-0.6f, 0.75f, 0.5f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, + {Vec3f(-0.5f, 0.65f, 0.5f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, + {Vec3f(-0.4f, 0.75f, 0.5f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + + {Vec3f(-0.6f, 0.75f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, + {Vec3f(-0.5f, 0.65f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, + {Vec3f(-0.4f, 0.75f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, }; // negate y if we're using negative viewport height @@ -264,6 +281,40 @@ void main() pipeCreateInfo.depthStencilState.depthCompareOp = VK_COMPARE_OP_ALWAYS; VkPipeline depthWritePipe = createGraphicsPipeline(pipeCreateInfo); + VkPipeline dynamicScissorPipe, fixedScissorPassPipe, fixedScissorFailPipe, + dynamicStencilRefPipe, dynamicStencilMaskPipe; + { + vkh::GraphicsPipelineCreateInfo dynamicPipe = pipeCreateInfo; + dynamicPipe.depthStencilState.depthWriteEnable = VK_FALSE; + dynamicPipe.depthStencilState.depthTestEnable = VK_FALSE; + + dynamicScissorPipe = createGraphicsPipeline(dynamicPipe); + setName(dynamicScissorPipe, "dynamicScissorPipe"); + + dynamicPipe.dynamicState.dynamicStates = {VK_DYNAMIC_STATE_VIEWPORT}; + dynamicPipe.viewportState.scissors = {{{95, 245}, {10, 10}}}; + + fixedScissorPassPipe = createGraphicsPipeline(dynamicPipe); + setName(fixedScissorPassPipe, "fixedScissorPassPipe"); + + dynamicPipe.viewportState.scissors = {{{95, 245}, {4, 4}}}; + + fixedScissorFailPipe = createGraphicsPipeline(dynamicPipe); + setName(fixedScissorFailPipe, "fixedScissorFailPipe"); + + dynamicPipe.dynamicState.dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR); + dynamicPipe.dynamicState.dynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE); + + dynamicStencilRefPipe = createGraphicsPipeline(dynamicPipe); + setName(dynamicStencilRefPipe, "dynamicStencilRefPipe"); + + dynamicPipe.dynamicState.dynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK); + dynamicPipe.dynamicState.dynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK); + + dynamicStencilMaskPipe = createGraphicsPipeline(dynamicPipe); + setName(dynamicStencilMaskPipe, "dynamicStencilMaskPipe"); + } + pipeCreateInfo.depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; pipeCreateInfo.depthStencilState.stencilTestEnable = VK_TRUE; VkPipeline stencilWritePipe = createGraphicsPipeline(pipeCreateInfo); @@ -391,6 +442,26 @@ void main() vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); vkCmdDraw(cmd, 24, 1, 9, 0); + setMarker(cmd, "Fixed Scissor Fail"); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, fixedScissorFailPipe); + vkCmdDraw(cmd, 3, 1, 33, 0); + + setMarker(cmd, "Fixed Scissor Pass"); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, fixedScissorPassPipe); + vkCmdDraw(cmd, 3, 1, 36, 0); + + setMarker(cmd, "Dynamic Stencil Ref"); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dynamicStencilRefPipe); + vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor); + vkCmdSetStencilReference(cmd, VK_STENCIL_FACE_FRONT_AND_BACK, 0x67); + vkCmdDraw(cmd, 3, 1, 39, 0); + + setMarker(cmd, "Dynamic Stencil Mask"); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dynamicStencilMaskPipe); + vkCmdSetStencilCompareMask(cmd, VK_STENCIL_FACE_FRONT_AND_BACK, 0); + vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FACE_FRONT_AND_BACK, 0); + vkCmdDraw(cmd, 3, 1, 42, 0); + vkCmdEndRenderPass(cmd); { diff --git a/util/test/tests/Vulkan/VK_Pixel_History.py b/util/test/tests/Vulkan/VK_Pixel_History.py index 164b72bf2..acef96405 100644 --- a/util/test/tests/Vulkan/VK_Pixel_History.py +++ b/util/test/tests/Vulkan/VK_Pixel_History.py @@ -1,11 +1,13 @@ import renderdoc as rd import rdtest +from typing import List def value_selector(x): return x.floatValue def passed(x): return x.Passed() def event_id(x): return x.eventId def culled(x): return x.backfaceCulled def depth_test_failed(x): return x.depthTestFailed +def scissor_clipped(x): return x.scissorClipped def stencil_test_failed(x): return x.stencilTestFailed def shader_discarded(x): return x.shaderDiscarded def shader_out_col(x): return value_selector(x.shaderOut.col) @@ -53,6 +55,10 @@ class VK_Pixel_History(rdtest.TestCase): background_eid = self.find_draw("Background").next.eventId cull_eid = self.find_draw("Cull Front").next.eventId test_eid = self.find_draw("Test").next.eventId + fixed_scissor_fail_eid = self.find_draw("Fixed Scissor Fail").next.eventId + fixed_scissor_pass_eid = self.find_draw("Fixed Scissor Pass").next.eventId + dynamic_stencil_ref_eid = self.find_draw("Dynamic Stencil Ref").next.eventId + dynamic_stencil_mask_eid = self.find_draw("Dynamic Stencil Mask").next.eventId # For pixel 190, 149 inside the red triangle x, y = 190, 149 @@ -102,6 +108,23 @@ class VK_Pixel_History(rdtest.TestCase): self.check_events(events, modifs, False) self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast) + rdtest.log.print("Testing dynamic state pipelines") + self.controller.SetFrameEvent(dynamic_stencil_mask_eid, True) + + x, y = 100, 250 + rdtest.log.print("Testing pixel {}, {}".format(x, y)) + modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast) + events = [ + [[event_id, begin_renderpass_eid], [passed, True]], + [[event_id, background_eid], [passed, True]], + [[event_id, fixed_scissor_fail_eid], [scissor_clipped, True]], + [[event_id, fixed_scissor_pass_eid], [passed, True], [shader_out_col, (0.0, 1.0, 0.0, 1.0)]], + [[event_id, dynamic_stencil_ref_eid], [passed, True], [shader_out_col, (0.0, 0.0, 1.0, 1.0)]], + [[event_id, dynamic_stencil_mask_eid], [passed, True], [shader_out_col, (0.0, 1.0, 1.0, 1.0)]], + ] + self.check_events(events, modifs, False) + self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast) + def multisampled_image_test(self): test_marker: rd.DrawcallDescription = self.find_draw("Multisampled: test") draw_eid = test_marker.next.eventId