From 0dcd19c43d9ef2d336c4235477a06fe41b4d805c Mon Sep 17 00:00:00 2001 From: Jasmine Hansen Date: Tue, 7 May 2024 14:58:29 -0700 Subject: [PATCH] Add support for binding shader object state in replay. Co-authored-by: James Sumihiro --- renderdoc/api/replay/vk_pipestate.h | 3 + renderdoc/driver/vulkan/vk_core.cpp | 21 +- renderdoc/driver/vulkan/vk_core.h | 1 + renderdoc/driver/vulkan/vk_state.cpp | 808 ++++++++++-------- renderdoc/driver/vulkan/vk_state.h | 13 + .../driver/vulkan/wrappers/vk_cmd_funcs.cpp | 25 + renderdoc/replay/renderdoc_serialise.inl | 6 +- 7 files changed, 527 insertions(+), 350 deletions(-) diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index 091bcd415..a3d58df5c 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -363,6 +363,9 @@ and size into specializationData can be obtained from the reflection info. :type: List[int] )") rdcarray specializationIds; + + DOCUMENT("Whether the shader is a shader object or shader module."); + bool shaderObject = false; }; DOCUMENT("Describes the state of the fixed-function tessellator."); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index f984d58e7..639ae8749 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -4303,7 +4303,19 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay else { // even outside of render passes, we need to restore the state - m_RenderState.BindPipeline(this, cmd, VulkanRenderState::BindInitial, false); + if(m_RenderState.compute.shaderObject || m_RenderState.graphics.shaderObject) + { + m_RenderState.BindShaderObjects(this, cmd, VulkanRenderState::BindInitial); + + if(m_RenderState.compute.pipeline != ResourceId()) + m_RenderState.BindPipeline(this, cmd, VulkanRenderState::BindCompute, false); + if(m_RenderState.graphics.pipeline != ResourceId()) + m_RenderState.BindPipeline(this, cmd, VulkanRenderState::BindGraphics, false); + } + else + { + m_RenderState.BindPipeline(this, cmd, VulkanRenderState::BindInitial, false); + } } m_RenderState.subpassContents = subpassContents; @@ -5169,7 +5181,12 @@ void WrappedVulkan::AddUsage(VulkanActionTreeNode &actionNode, rdcarrayCmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(vk->GetDebugManager()->GetDummyPipeline())); - if(pushLayout != ResourceId()) - { - // set push constants with the last layout used - VkPipelineLayout layout = - vk->GetResourceManager()->GetCurrentHandle(pushLayout); - - const rdcarray &pushRanges = - vk->GetDebugManager()->GetPipelineLayoutInfo(pushLayout).pushRanges; - - // only set push constant ranges that the layout uses - for(size_t i = 0; i < pushRanges.size(); i++) - ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags, - pushRanges[i].offset, pushRanges[i].size, - pushconsts + pushRanges[i].offset); - } - } - - if(!views.empty() && dynamicStates[VkDynamicViewport]) - ObjDisp(cmd)->CmdSetViewport(Unwrap(cmd), 0, (uint32_t)views.size(), &views[0]); - if(!scissors.empty() && dynamicStates[VkDynamicScissor]) - ObjDisp(cmd)->CmdSetScissor(Unwrap(cmd), 0, (uint32_t)scissors.size(), &scissors[0]); - - if(vk->DynamicColorWrite()) - { - if(!colorWriteEnable.empty() && dynamicStates[VkDynamicColorWriteEXT]) - ObjDisp(cmd)->CmdSetColorWriteEnableEXT(Unwrap(cmd), (uint32_t)colorWriteEnable.size(), - colorWriteEnable.data()); - } - - if(vk->ExtendedDynamicState()) - { - if(!views.empty() && dynamicStates[VkDynamicViewportCount]) - ObjDisp(cmd)->CmdSetViewportWithCountEXT(Unwrap(cmd), (uint32_t)views.size(), views.data()); - if(!scissors.empty() && dynamicStates[VkDynamicScissorCount]) - ObjDisp(cmd)->CmdSetScissorWithCountEXT(Unwrap(cmd), (uint32_t)scissors.size(), - scissors.data()); - - if(dynamicStates[VkDynamicCullMode]) - ObjDisp(cmd)->CmdSetCullModeEXT(Unwrap(cmd), cullMode); - if(dynamicStates[VkDynamicFrontFace]) - ObjDisp(cmd)->CmdSetFrontFaceEXT(Unwrap(cmd), frontFace); - if(dynamicStates[VkDynamicPrimitiveTopology]) - ObjDisp(cmd)->CmdSetPrimitiveTopologyEXT(Unwrap(cmd), primitiveTopology); - - if(dynamicStates[VkDynamicDepthBoundsTestEnable]) - ObjDisp(cmd)->CmdSetDepthBoundsTestEnableEXT(Unwrap(cmd), depthBoundsTestEnable); - - if(dynamicStates[VkDynamicDepthTestEnable]) - ObjDisp(cmd)->CmdSetDepthTestEnableEXT(Unwrap(cmd), depthTestEnable); - if(dynamicStates[VkDynamicDepthWriteEnable]) - ObjDisp(cmd)->CmdSetDepthWriteEnableEXT(Unwrap(cmd), depthWriteEnable); - if(dynamicStates[VkDynamicDepthCompareOp]) - ObjDisp(cmd)->CmdSetDepthCompareOpEXT(Unwrap(cmd), depthCompareOp); - - if(dynamicStates[VkDynamicStencilTestEnable]) - ObjDisp(cmd)->CmdSetStencilTestEnableEXT(Unwrap(cmd), stencilTestEnable); - - if(dynamicStates[VkDynamicStencilOp]) - { - ObjDisp(cmd)->CmdSetStencilOpEXT(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.failOp, - front.passOp, front.depthFailOp, front.compareOp); - ObjDisp(cmd)->CmdSetStencilOpEXT(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, front.failOp, - front.passOp, front.depthFailOp, front.compareOp); - } - } - - if(vk->ExtendedDynamicState2()) - { - if(dynamicStates[VkDynamicDepthBiasEnable]) - ObjDisp(cmd)->CmdSetDepthBiasEnableEXT(Unwrap(cmd), depthBiasEnable); - if(dynamicStates[VkDynamicPrimRestart]) - ObjDisp(cmd)->CmdSetPrimitiveRestartEnableEXT(Unwrap(cmd), primRestartEnable); - if(dynamicStates[VkDynamicRastDiscard]) - ObjDisp(cmd)->CmdSetRasterizerDiscardEnableEXT(Unwrap(cmd), rastDiscardEnable); - } - if(vk->ExtendedDynamicState2Logic()) - { - if(dynamicStates[VkDynamicLogicOpEXT]) - ObjDisp(cmd)->CmdSetLogicOpEXT(Unwrap(cmd), logicOp); - } - if(vk->ExtendedDynamicState2CPs()) - { - if(dynamicStates[VkDynamicControlPointsEXT]) - ObjDisp(cmd)->CmdSetPatchControlPointsEXT(Unwrap(cmd), patchControlPoints); - } - - if(vk->ExtendedDynamicState3AlphaToCover()) - { - if(dynamicStates[VkDynamicAlphaToCoverageEXT]) - ObjDisp(cmd)->CmdSetAlphaToCoverageEnableEXT(Unwrap(cmd), alphaToCoverageEnable); - } - if(vk->ExtendedDynamicState3AlphaToOne()) - { - if(dynamicStates[VkDynamicAlphaToOneEXT]) - ObjDisp(cmd)->CmdSetAlphaToOneEnableEXT(Unwrap(cmd), alphaToOneEnable); - } - if(vk->ExtendedDynamicState3CBEnable()) - { - if(!colorBlendEnable.empty() && dynamicStates[VkDynamicColorBlendEnableEXT]) - ObjDisp(cmd)->CmdSetColorBlendEnableEXT(Unwrap(cmd), 0, (uint32_t)colorBlendEnable.size(), - colorBlendEnable.data()); - } - if(vk->ExtendedDynamicState3CBEquation()) - { - if(!colorBlendEquation.empty() && dynamicStates[VkDynamicColorBlendEquationEXT]) - ObjDisp(cmd)->CmdSetColorBlendEquationEXT( - Unwrap(cmd), 0, (uint32_t)colorBlendEquation.size(), colorBlendEquation.data()); - } - if(vk->ExtendedDynamicState3WriteMask()) - { - if(!colorWriteMask.empty() && dynamicStates[VkDynamicColorWriteMaskEXT]) - ObjDisp(cmd)->CmdSetColorWriteMaskEXT(Unwrap(cmd), 0, (uint32_t)colorWriteMask.size(), - colorWriteMask.data()); - } - if(vk->ExtendedDynamicState3ConservRast()) - { - if(dynamicStates[VkDynamicConservativeRastModeEXT]) - ObjDisp(cmd)->CmdSetConservativeRasterizationModeEXT(Unwrap(cmd), conservativeRastMode); - } - if(vk->ExtendedDynamicState3DepthClampEnable()) - { - if(dynamicStates[VkDynamicDepthClampEnableEXT]) - ObjDisp(cmd)->CmdSetDepthClampEnableEXT(Unwrap(cmd), depthClampEnable); - } - if(vk->ExtendedDynamicState3DepthClip()) - { - if(dynamicStates[VkDynamicDepthClipEnableEXT]) - ObjDisp(cmd)->CmdSetDepthClipEnableEXT(Unwrap(cmd), depthClipEnable); - } - if(vk->ExtendedDynamicState3DepthClipNegative()) - { - if(dynamicStates[VkDynamicDepthClipNegativeOneEXT]) - ObjDisp(cmd)->CmdSetDepthClipNegativeOneToOneEXT(Unwrap(cmd), negativeOneToOne); - } - if(vk->ExtendedDynamicState3PrimOverest()) - { - if(dynamicStates[VkDynamicOverstimationSizeEXT]) - ObjDisp(cmd)->CmdSetExtraPrimitiveOverestimationSizeEXT(Unwrap(cmd), primOverestimationSize); - } - if(vk->ExtendedDynamicState3LineRast()) - { - if(dynamicStates[VkDynamicLineRastModeEXT]) - ObjDisp(cmd)->CmdSetLineRasterizationModeEXT(Unwrap(cmd), lineRasterMode); - } - if(vk->ExtendedDynamicState3LineStipple()) - { - if(dynamicStates[VkDynamicLineStippleEnableEXT]) - ObjDisp(cmd)->CmdSetLineStippleEnableEXT(Unwrap(cmd), stippledLineEnable); - } - if(vk->ExtendedDynamicState3LogicEnable()) - { - if(dynamicStates[VkDynamicLogicOpEnableEXT]) - ObjDisp(cmd)->CmdSetLogicOpEnableEXT(Unwrap(cmd), logicOpEnable); - } - if(vk->ExtendedDynamicState3PolyMode()) - { - if(dynamicStates[VkDynamicPolygonModeEXT]) - ObjDisp(cmd)->CmdSetPolygonModeEXT(Unwrap(cmd), polygonMode); - } - if(vk->ExtendedDynamicState3ProvokingVert()) - { - if(dynamicStates[VkDynamicProvokingVertexModeEXT]) - ObjDisp(cmd)->CmdSetProvokingVertexModeEXT(Unwrap(cmd), provokingVertexMode); - } - if(vk->ExtendedDynamicState3RastSamples()) - { - if(dynamicStates[VkDynamicRasterizationSamplesEXT]) - ObjDisp(cmd)->CmdSetRasterizationSamplesEXT(Unwrap(cmd), rastSamples); - } - if(vk->ExtendedDynamicState3RastStream()) - { - if(dynamicStates[VkDynamicRasterizationStreamEXT]) - ObjDisp(cmd)->CmdSetRasterizationStreamEXT(Unwrap(cmd), rasterStream); - } - if(vk->ExtendedDynamicState3SampleLoc()) - { - if(dynamicStates[VkDynamicSampleLocationsEnableEXT]) - ObjDisp(cmd)->CmdSetSampleLocationsEnableEXT(Unwrap(cmd), sampleLocEnable); - } - if(vk->ExtendedDynamicState3SampleMask()) - { - if(dynamicStates[VkDynamicSampleMaskEXT]) - ObjDisp(cmd)->CmdSetSampleMaskEXT(Unwrap(cmd), rastSamples, sampleMask.data()); - } - if(vk->ExtendedDynamicState3TesselDomain()) - { - if(dynamicStates[VkDynamicTessDomainOriginEXT]) - ObjDisp(cmd)->CmdSetTessellationDomainOriginEXT(Unwrap(cmd), domainOrigin); - } - - if(dynamicStates[VkDynamicLineWidth] && !vk->GetDriverInfo().QualcommLineWidthDynamicStateCrash()) - ObjDisp(cmd)->CmdSetLineWidth(Unwrap(cmd), lineWidth); - - if(dynamicStates[VkDynamicDepthBias]) - ObjDisp(cmd)->CmdSetDepthBias(Unwrap(cmd), bias.depth, bias.biasclamp, bias.slope); - - if(dynamicStates[VkDynamicBlendConstants]) - ObjDisp(cmd)->CmdSetBlendConstants(Unwrap(cmd), blendConst); - - if(dynamicStates[VkDynamicDepthBounds]) - ObjDisp(cmd)->CmdSetDepthBounds(Unwrap(cmd), mindepth, maxdepth); - - if(dynamicStates[VkDynamicStencilCompareMask]) - { - ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.compare); - ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.compare); - } - - if(dynamicStates[VkDynamicStencilWriteMask]) - { - ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.write); - ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.write); - } - - if(dynamicStates[VkDynamicStencilReference]) - { - ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.ref); - ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.ref); - } - - if(!sampleLocations.locations.empty() && dynamicStates[VkDynamicSampleLocationsEXT]) - { - VkSampleLocationsInfoEXT info = {VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT}; - info.pSampleLocations = sampleLocations.locations.data(); - info.sampleLocationsCount = (uint32_t)sampleLocations.locations.size(); - info.sampleLocationsPerPixel = sampleLocations.sampleCount; - info.sampleLocationGridSize = sampleLocations.gridSize; - ObjDisp(cmd)->CmdSetSampleLocationsEXT(Unwrap(cmd), &info); - } - - if(!discardRectangles.empty() && dynamicStates[VkDynamicDiscardRectangleEXT]) - ObjDisp(cmd)->CmdSetDiscardRectangleEXT(Unwrap(cmd), 0, (uint32_t)discardRectangles.size(), - &discardRectangles[0]); - - if(stippleFactor && dynamicStates[VkDynamicLineStippleKHR]) - ObjDisp(cmd)->CmdSetLineStippleEXT(Unwrap(cmd), stippleFactor, stipplePattern); - - if(vk->FragmentShadingRate()) - { - if(dynamicStates[VkDynamicShadingRateKHR]) - ObjDisp(cmd)->CmdSetFragmentShadingRateKHR(Unwrap(cmd), &pipelineShadingRate, - shadingRateCombiners); - } - - if(vk->DynamicAttachmentLoop()) - { - if(dynamicStates[VkDynamicAttachmentFeedbackLoopEnableEXT]) - ObjDisp(cmd)->CmdSetAttachmentFeedbackLoopEnableEXT(Unwrap(cmd), feedbackAspects); + BindLastPushConstants(vk, cmd); } if(graphics.pipeline != ResourceId()) @@ -584,88 +342,7 @@ void VulkanRenderState::BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd, else BindDescriptorSetsWithoutPipeline(vk, cmd, graphics, VK_PIPELINE_BIND_POINT_GRAPHICS); - if(ibuffer.buf != ResourceId()) - { - VkIndexType type = VK_INDEX_TYPE_UINT16; - if(ibuffer.bytewidth == 4) - type = VK_INDEX_TYPE_UINT32; - else if(ibuffer.bytewidth == 1) - type = VK_INDEX_TYPE_UINT8_KHR; - - ObjDisp(cmd)->CmdBindIndexBuffer( - Unwrap(cmd), Unwrap(vk->GetResourceManager()->GetCurrentHandle(ibuffer.buf)), - ibuffer.offs, type); - } - - if(vk->DynamicVertexInput() && dynamicStates[VkDynamicVertexInputEXT]) - { - ObjDisp(cmd)->CmdSetVertexInputEXT(Unwrap(cmd), (uint32_t)vertexBindings.size(), - vertexBindings.data(), (uint32_t)vertexAttributes.size(), - vertexAttributes.data()); - } - - bool dynamicStride = - dynamicStates[VkDynamicVertexInputBindingStride] && vk->ExtendedDynamicState(); - - for(size_t i = 0; i < vbuffers.size(); i++) - { - if(vbuffers[i].buf == ResourceId()) - { - if(vk->NULLDescriptorsAllowed()) - { - VkBuffer empty = VK_NULL_HANDLE; - - if(dynamicStride) - ObjDisp(cmd)->CmdBindVertexBuffers2EXT( - Unwrap(cmd), (uint32_t)i, 1, &empty, &vbuffers[i].offs, - vbuffers[i].size == VK_WHOLE_SIZE ? NULL : &vbuffers[i].size, &vbuffers[i].stride); - else - ObjDisp(cmd)->CmdBindVertexBuffers(Unwrap(cmd), (uint32_t)i, 1, &empty, - &vbuffers[i].offs); - } - - continue; - } - - if(dynamicStride) - ObjDisp(cmd)->CmdBindVertexBuffers2EXT( - Unwrap(cmd), (uint32_t)i, 1, - UnwrapPtr(vk->GetResourceManager()->GetCurrentHandle(vbuffers[i].buf)), - &vbuffers[i].offs, vbuffers[i].size == VK_WHOLE_SIZE ? NULL : &vbuffers[i].size, - &vbuffers[i].stride); - else - ObjDisp(cmd)->CmdBindVertexBuffers( - Unwrap(cmd), (uint32_t)i, 1, - UnwrapPtr(vk->GetResourceManager()->GetCurrentHandle(vbuffers[i].buf)), - &vbuffers[i].offs); - } - - for(size_t i = 0; i < xfbbuffers.size(); i++) - { - if(xfbbuffers[i].buf == ResourceId()) - continue; - - ObjDisp(cmd)->CmdBindTransformFeedbackBuffersEXT( - Unwrap(cmd), (uint32_t)i, 1, - UnwrapPtr(vk->GetResourceManager()->GetCurrentHandle(xfbbuffers[i].buf)), - &xfbbuffers[i].offs, &xfbbuffers[i].size); - } - - if(!xfbcounters.empty()) - { - rdcarray buffers; - rdcarray offsets; - - for(size_t i = 0; i < xfbcounters.size(); i++) - { - buffers.push_back( - Unwrap(vk->GetResourceManager()->GetCurrentHandle(xfbcounters[i].buf))); - offsets.push_back(xfbcounters[i].offs); - } - - ObjDisp(cmd)->CmdBeginTransformFeedbackEXT( - Unwrap(cmd), firstxfbcounter, (uint32_t)xfbcounters.size(), buffers.data(), offsets.data()); - } + BindDynamicState(vk, cmd); } if(binding == BindCompute || binding == BindInitial) @@ -693,27 +370,374 @@ void VulkanRenderState::BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd, } else if(binding == BindInitial) { - if(pushLayout != ResourceId()) - { - // set push constants with the last layout used - VkPipelineLayout layout = - vk->GetResourceManager()->GetCurrentHandle(pushLayout); - - const rdcarray &pushRanges = - vk->GetDebugManager()->GetPipelineLayoutInfo(pushLayout).pushRanges; - - // only set push constant ranges that the layout uses - for(size_t i = 0; i < pushRanges.size(); i++) - ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags, - pushRanges[i].offset, pushRanges[i].size, - pushconsts + pushRanges[i].offset); - } + BindLastPushConstants(vk, cmd); BindDescriptorSetsWithoutPipeline(vk, cmd, compute, VK_PIPELINE_BIND_POINT_COMPUTE); } } } +void VulkanRenderState::BindShaderObjects(WrappedVulkan *vk, VkCommandBuffer cmd, + PipelineBinding binding) +{ + if(binding == BindGraphics || binding == BindInitial) + { + if(graphics.shaderObject) + { + for(uint32_t i = 0; i < (uint32_t)ShaderStage::Count; i++) + { + if(i == (uint32_t)ShaderStage::Compute) + continue; + + const VkShaderStageFlagBits stage = (VkShaderStageFlagBits)(1 << (uint32_t)i); + const VkShaderEXT shader = + Unwrap(vk->GetResourceManager()->GetCurrentHandle(shaderObjects[i])); + + ObjDisp(cmd)->CmdBindShadersEXT(Unwrap(cmd), 1, &stage, &shader); + } + } + + BindLastPushConstants(vk, cmd); + + BindDescriptorSetsForShaders(vk, cmd, graphics, VK_PIPELINE_BIND_POINT_GRAPHICS); + + BindDynamicState(vk, cmd); + } + + if(binding == BindCompute || binding == BindInitial) + { + if(compute.shaderObject && shaderObjects[(uint32_t)ShaderStage::Compute] != ResourceId()) + { + const VkShaderStageFlagBits stage = + (VkShaderStageFlagBits)(1 << (uint32_t)ShaderStage::Compute); + const VkShaderEXT shader = Unwrap(vk->GetResourceManager()->GetCurrentHandle( + shaderObjects[(uint32_t)ShaderStage::Compute])); + ObjDisp(cmd)->CmdBindShadersEXT(Unwrap(cmd), 1, &stage, &shader); + } + + BindLastPushConstants(vk, cmd); + + BindDescriptorSetsForShaders(vk, cmd, compute, VK_PIPELINE_BIND_POINT_COMPUTE); + } +} + +void VulkanRenderState::BindDynamicState(WrappedVulkan *vk, VkCommandBuffer cmd) +{ + if(!views.empty() && dynamicStates[VkDynamicViewport]) + ObjDisp(cmd)->CmdSetViewport(Unwrap(cmd), 0, (uint32_t)views.size(), &views[0]); + if(!scissors.empty() && dynamicStates[VkDynamicScissor]) + ObjDisp(cmd)->CmdSetScissor(Unwrap(cmd), 0, (uint32_t)scissors.size(), &scissors[0]); + + if(vk->DynamicColorWrite()) + { + if(!colorWriteEnable.empty() && dynamicStates[VkDynamicColorWriteEXT]) + ObjDisp(cmd)->CmdSetColorWriteEnableEXT(Unwrap(cmd), (uint32_t)colorWriteEnable.size(), + colorWriteEnable.data()); + } + + if(vk->ExtendedDynamicState() || vk->ShaderObject()) + { + if(!views.empty() && dynamicStates[VkDynamicViewportCount]) + ObjDisp(cmd)->CmdSetViewportWithCountEXT(Unwrap(cmd), (uint32_t)views.size(), views.data()); + if(!scissors.empty() && dynamicStates[VkDynamicScissorCount]) + ObjDisp(cmd)->CmdSetScissorWithCountEXT(Unwrap(cmd), (uint32_t)scissors.size(), + scissors.data()); + + if(dynamicStates[VkDynamicCullMode]) + ObjDisp(cmd)->CmdSetCullModeEXT(Unwrap(cmd), cullMode); + if(dynamicStates[VkDynamicFrontFace]) + ObjDisp(cmd)->CmdSetFrontFaceEXT(Unwrap(cmd), frontFace); + if(dynamicStates[VkDynamicPrimitiveTopology]) + ObjDisp(cmd)->CmdSetPrimitiveTopologyEXT(Unwrap(cmd), primitiveTopology); + + if(dynamicStates[VkDynamicDepthBoundsTestEnable]) + ObjDisp(cmd)->CmdSetDepthBoundsTestEnableEXT(Unwrap(cmd), depthBoundsTestEnable); + + if(dynamicStates[VkDynamicDepthTestEnable]) + ObjDisp(cmd)->CmdSetDepthTestEnableEXT(Unwrap(cmd), depthTestEnable); + if(dynamicStates[VkDynamicDepthWriteEnable]) + ObjDisp(cmd)->CmdSetDepthWriteEnableEXT(Unwrap(cmd), depthWriteEnable); + if(dynamicStates[VkDynamicDepthCompareOp]) + ObjDisp(cmd)->CmdSetDepthCompareOpEXT(Unwrap(cmd), depthCompareOp); + + if(dynamicStates[VkDynamicStencilTestEnable]) + ObjDisp(cmd)->CmdSetStencilTestEnableEXT(Unwrap(cmd), stencilTestEnable); + + if(dynamicStates[VkDynamicStencilOp]) + { + ObjDisp(cmd)->CmdSetStencilOpEXT(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.failOp, + front.passOp, front.depthFailOp, front.compareOp); + ObjDisp(cmd)->CmdSetStencilOpEXT(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, front.failOp, + front.passOp, front.depthFailOp, front.compareOp); + } + } + + if(vk->ExtendedDynamicState2() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicDepthBiasEnable]) + ObjDisp(cmd)->CmdSetDepthBiasEnableEXT(Unwrap(cmd), depthBiasEnable); + if(dynamicStates[VkDynamicPrimRestart]) + ObjDisp(cmd)->CmdSetPrimitiveRestartEnableEXT(Unwrap(cmd), primRestartEnable); + if(dynamicStates[VkDynamicRastDiscard]) + ObjDisp(cmd)->CmdSetRasterizerDiscardEnableEXT(Unwrap(cmd), rastDiscardEnable); + } + if(vk->ExtendedDynamicState2Logic() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicLogicOpEXT]) + ObjDisp(cmd)->CmdSetLogicOpEXT(Unwrap(cmd), logicOp); + } + if(vk->ExtendedDynamicState2CPs() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicControlPointsEXT]) + ObjDisp(cmd)->CmdSetPatchControlPointsEXT(Unwrap(cmd), patchControlPoints); + } + + if(vk->ExtendedDynamicState3AlphaToCover() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicAlphaToCoverageEXT]) + ObjDisp(cmd)->CmdSetAlphaToCoverageEnableEXT(Unwrap(cmd), alphaToCoverageEnable); + } + if(vk->ExtendedDynamicState3AlphaToOne() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicAlphaToOneEXT]) + ObjDisp(cmd)->CmdSetAlphaToOneEnableEXT(Unwrap(cmd), alphaToOneEnable); + } + if(vk->ExtendedDynamicState3CBEnable() || vk->ShaderObject()) + { + if(!colorBlendEnable.empty() && dynamicStates[VkDynamicColorBlendEnableEXT]) + ObjDisp(cmd)->CmdSetColorBlendEnableEXT(Unwrap(cmd), 0, (uint32_t)colorBlendEnable.size(), + colorBlendEnable.data()); + } + if(vk->ExtendedDynamicState3CBEquation() || vk->ShaderObject()) + { + if(!colorBlendEquation.empty() && dynamicStates[VkDynamicColorBlendEquationEXT]) + ObjDisp(cmd)->CmdSetColorBlendEquationEXT(Unwrap(cmd), 0, (uint32_t)colorBlendEquation.size(), + colorBlendEquation.data()); + } + if(vk->ExtendedDynamicState3WriteMask() || vk->ShaderObject()) + { + if(!colorWriteMask.empty() && dynamicStates[VkDynamicColorWriteMaskEXT]) + ObjDisp(cmd)->CmdSetColorWriteMaskEXT(Unwrap(cmd), 0, (uint32_t)colorWriteMask.size(), + colorWriteMask.data()); + } + if(vk->ExtendedDynamicState3ConservRast() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicConservativeRastModeEXT]) + ObjDisp(cmd)->CmdSetConservativeRasterizationModeEXT(Unwrap(cmd), conservativeRastMode); + } + if(vk->ExtendedDynamicState3DepthClampEnable() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicDepthClampEnableEXT]) + ObjDisp(cmd)->CmdSetDepthClampEnableEXT(Unwrap(cmd), depthClampEnable); + } + if(vk->ExtendedDynamicState3DepthClip() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicDepthClipEnableEXT]) + ObjDisp(cmd)->CmdSetDepthClipEnableEXT(Unwrap(cmd), depthClipEnable); + } + if(vk->ExtendedDynamicState3DepthClipNegative() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicDepthClipNegativeOneEXT]) + ObjDisp(cmd)->CmdSetDepthClipNegativeOneToOneEXT(Unwrap(cmd), negativeOneToOne); + } + if(vk->ExtendedDynamicState3PrimOverest() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicOverstimationSizeEXT]) + ObjDisp(cmd)->CmdSetExtraPrimitiveOverestimationSizeEXT(Unwrap(cmd), primOverestimationSize); + } + if(vk->ExtendedDynamicState3LineRast() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicLineRastModeEXT]) + ObjDisp(cmd)->CmdSetLineRasterizationModeEXT(Unwrap(cmd), lineRasterMode); + } + if(vk->ExtendedDynamicState3LineStipple() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicLineStippleEnableEXT]) + ObjDisp(cmd)->CmdSetLineStippleEnableEXT(Unwrap(cmd), stippledLineEnable); + } + if(vk->ExtendedDynamicState3LogicEnable() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicLogicOpEnableEXT]) + ObjDisp(cmd)->CmdSetLogicOpEnableEXT(Unwrap(cmd), logicOpEnable); + } + if(vk->ExtendedDynamicState3PolyMode() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicPolygonModeEXT]) + ObjDisp(cmd)->CmdSetPolygonModeEXT(Unwrap(cmd), polygonMode); + } + if(vk->ExtendedDynamicState3ProvokingVert() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicProvokingVertexModeEXT]) + ObjDisp(cmd)->CmdSetProvokingVertexModeEXT(Unwrap(cmd), provokingVertexMode); + } + if(vk->ExtendedDynamicState3RastSamples() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicRasterizationSamplesEXT]) + ObjDisp(cmd)->CmdSetRasterizationSamplesEXT(Unwrap(cmd), rastSamples); + } + if(vk->ExtendedDynamicState3RastStream() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicRasterizationStreamEXT]) + ObjDisp(cmd)->CmdSetRasterizationStreamEXT(Unwrap(cmd), rasterStream); + } + if(vk->ExtendedDynamicState3SampleLoc() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicSampleLocationsEnableEXT]) + ObjDisp(cmd)->CmdSetSampleLocationsEnableEXT(Unwrap(cmd), sampleLocEnable); + } + if(vk->ExtendedDynamicState3SampleMask() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicSampleMaskEXT]) + ObjDisp(cmd)->CmdSetSampleMaskEXT(Unwrap(cmd), rastSamples, sampleMask.data()); + } + if(vk->ExtendedDynamicState3TesselDomain() || vk->ShaderObject()) + { + if(dynamicStates[VkDynamicTessDomainOriginEXT]) + ObjDisp(cmd)->CmdSetTessellationDomainOriginEXT(Unwrap(cmd), domainOrigin); + } + + if(dynamicStates[VkDynamicLineWidth] && !vk->GetDriverInfo().QualcommLineWidthDynamicStateCrash()) + ObjDisp(cmd)->CmdSetLineWidth(Unwrap(cmd), lineWidth); + + if(dynamicStates[VkDynamicDepthBias]) + ObjDisp(cmd)->CmdSetDepthBias(Unwrap(cmd), bias.depth, bias.biasclamp, bias.slope); + + if(dynamicStates[VkDynamicBlendConstants]) + ObjDisp(cmd)->CmdSetBlendConstants(Unwrap(cmd), blendConst); + + if(dynamicStates[VkDynamicDepthBounds]) + ObjDisp(cmd)->CmdSetDepthBounds(Unwrap(cmd), mindepth, maxdepth); + + if(dynamicStates[VkDynamicStencilCompareMask]) + { + ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.compare); + ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.compare); + } + + if(dynamicStates[VkDynamicStencilWriteMask]) + { + ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.write); + ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.write); + } + + if(dynamicStates[VkDynamicStencilReference]) + { + ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.ref); + ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.ref); + } + + if(!sampleLocations.locations.empty() && dynamicStates[VkDynamicSampleLocationsEXT]) + { + VkSampleLocationsInfoEXT info = {VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT}; + info.pSampleLocations = sampleLocations.locations.data(); + info.sampleLocationsCount = (uint32_t)sampleLocations.locations.size(); + info.sampleLocationsPerPixel = sampleLocations.sampleCount; + info.sampleLocationGridSize = sampleLocations.gridSize; + ObjDisp(cmd)->CmdSetSampleLocationsEXT(Unwrap(cmd), &info); + } + + if(!discardRectangles.empty() && dynamicStates[VkDynamicDiscardRectangleEXT]) + ObjDisp(cmd)->CmdSetDiscardRectangleEXT(Unwrap(cmd), 0, (uint32_t)discardRectangles.size(), + &discardRectangles[0]); + + if(stippleFactor && dynamicStates[VkDynamicLineStippleKHR]) + ObjDisp(cmd)->CmdSetLineStippleEXT(Unwrap(cmd), stippleFactor, stipplePattern); + + if(vk->FragmentShadingRate()) + { + if(dynamicStates[VkDynamicShadingRateKHR]) + ObjDisp(cmd)->CmdSetFragmentShadingRateKHR(Unwrap(cmd), &pipelineShadingRate, + shadingRateCombiners); + } + + if(vk->DynamicAttachmentLoop()) + { + if(dynamicStates[VkDynamicAttachmentFeedbackLoopEnableEXT]) + ObjDisp(cmd)->CmdSetAttachmentFeedbackLoopEnableEXT(Unwrap(cmd), feedbackAspects); + } + + if(ibuffer.buf != ResourceId()) + { + VkIndexType type = VK_INDEX_TYPE_UINT16; + if(ibuffer.bytewidth == 4) + type = VK_INDEX_TYPE_UINT32; + else if(ibuffer.bytewidth == 1) + type = VK_INDEX_TYPE_UINT8_KHR; + + ObjDisp(cmd)->CmdBindIndexBuffer( + Unwrap(cmd), Unwrap(vk->GetResourceManager()->GetCurrentHandle(ibuffer.buf)), + ibuffer.offs, type); + } + + if(vk->DynamicVertexInput() && dynamicStates[VkDynamicVertexInputEXT]) + { + ObjDisp(cmd)->CmdSetVertexInputEXT(Unwrap(cmd), (uint32_t)vertexBindings.size(), + vertexBindings.data(), (uint32_t)vertexAttributes.size(), + vertexAttributes.data()); + } + + bool dynamicStride = dynamicStates[VkDynamicVertexInputBindingStride] && vk->ExtendedDynamicState(); + + for(size_t i = 0; i < vbuffers.size(); i++) + { + if(vbuffers[i].buf == ResourceId()) + { + if(vk->NULLDescriptorsAllowed()) + { + VkBuffer empty = VK_NULL_HANDLE; + + if(dynamicStride) + ObjDisp(cmd)->CmdBindVertexBuffers2EXT( + Unwrap(cmd), (uint32_t)i, 1, &empty, &vbuffers[i].offs, + vbuffers[i].size == VK_WHOLE_SIZE ? NULL : &vbuffers[i].size, &vbuffers[i].stride); + else + ObjDisp(cmd)->CmdBindVertexBuffers(Unwrap(cmd), (uint32_t)i, 1, &empty, &vbuffers[i].offs); + } + + continue; + } + + if(dynamicStride) + ObjDisp(cmd)->CmdBindVertexBuffers2EXT( + Unwrap(cmd), (uint32_t)i, 1, + UnwrapPtr(vk->GetResourceManager()->GetCurrentHandle(vbuffers[i].buf)), + &vbuffers[i].offs, vbuffers[i].size == VK_WHOLE_SIZE ? NULL : &vbuffers[i].size, + &vbuffers[i].stride); + else + ObjDisp(cmd)->CmdBindVertexBuffers( + Unwrap(cmd), (uint32_t)i, 1, + UnwrapPtr(vk->GetResourceManager()->GetCurrentHandle(vbuffers[i].buf)), + &vbuffers[i].offs); + } + + for(size_t i = 0; i < xfbbuffers.size(); i++) + { + if(xfbbuffers[i].buf == ResourceId()) + continue; + + ObjDisp(cmd)->CmdBindTransformFeedbackBuffersEXT( + Unwrap(cmd), (uint32_t)i, 1, + UnwrapPtr(vk->GetResourceManager()->GetCurrentHandle(xfbbuffers[i].buf)), + &xfbbuffers[i].offs, &xfbbuffers[i].size); + } + + if(!xfbcounters.empty()) + { + rdcarray buffers; + rdcarray offsets; + + for(size_t i = 0; i < xfbcounters.size(); i++) + { + buffers.push_back( + Unwrap(vk->GetResourceManager()->GetCurrentHandle(xfbcounters[i].buf))); + offsets.push_back(xfbcounters[i].offs); + } + + ObjDisp(cmd)->CmdBeginTransformFeedbackEXT( + Unwrap(cmd), firstxfbcounter, (uint32_t)xfbcounters.size(), buffers.data(), offsets.data()); + } +} + void VulkanRenderState::BindDescriptorSetsForPipeline(WrappedVulkan *vk, VkCommandBuffer cmd, VulkanStatePipeline &pipe, VkPipelineBindPoint bindPoint) @@ -919,6 +943,79 @@ void VulkanRenderState::BindDescriptorSetsWithoutPipeline(WrappedVulkan *vk, VkC } } +void VulkanRenderState::BindDescriptorSetsForShaders(WrappedVulkan *vk, VkCommandBuffer cmd, + VulkanStatePipeline &pipe, + VkPipelineBindPoint bindPoint) +{ + if(pipe.descSets.empty()) + return; + + const rdcarray &descSetLayouts = + vk->GetDebugManager()->GetPipelineLayoutInfo(pipe.descSets[pipe.lastBoundSet].pipeLayout).descSetLayouts; + + for(size_t i = 0; i < descSetLayouts.size(); i++) + { + const DescSetLayout &descLayout = vk->GetDebugManager()->GetDescSetLayout(descSetLayouts[i]); + + if(i < pipe.descSets.size() && pipe.descSets[i].descSet != ResourceId()) + { + // if we come to a descriptor set that isn't compatible, stop setting descriptor sets from + // here on. + // We can get into this situation if for example we have many sets bound at some point, then + // there's a pipeline change that causes most or all of them to be invalidated as + // incompatible, then the program only re-binds some subset that it knows is statically used + // by the next action. The remaining sets are invalid, but also unused and this is + // explicitly allowed by the spec. We just have to make sure we don't try to actively bind + // an incompatible descriptor set. + ResourceId createdDescSetLayoutId = vk->GetDescLayoutForDescSet(pipe.descSets[i].descSet); + + if(descSetLayouts[i] != createdDescSetLayoutId) + { + const DescSetLayout &createdDescLayout = + vk->GetDebugManager()->GetDescSetLayout(createdDescSetLayoutId); + + if(!descLayout.isCompatible(createdDescLayout)) + { + // this set is incompatible, don't rebind it. Assume the application knows the shader + // doesn't need this set, and the binding is just stale + continue; + } + } + + // if there are dynamic buffers, pass along the offsets + + uint32_t *dynamicOffsets = NULL; + + if(descLayout.dynamicCount > 0) + { + dynamicOffsets = &pipe.descSets[i].offsets[0]; + + if(pipe.descSets[i].offsets.size() < descLayout.dynamicCount) + { + dynamicOffsets = new uint32_t[descLayout.dynamicCount]; + for(uint32_t o = 0; o < descLayout.dynamicCount; o++) + { + if(o < pipe.descSets[i].offsets.size()) + { + dynamicOffsets[o] = pipe.descSets[i].offsets[o]; + } + else + { + dynamicOffsets[o] = 0; + RDCWARN("Missing dynamic offset for set %u!", (uint32_t)i); + } + } + } + } + + BindDescriptorSet(vk, descLayout, cmd, bindPoint, (uint32_t)i, dynamicOffsets); + + if(pipe.descSets[i].offsets.size() < descLayout.dynamicCount) + SAFE_DELETE_ARRAY(dynamicOffsets); + } + } +} + void VulkanRenderState::BindDescriptorSet(WrappedVulkan *vk, const DescSetLayout &descLayout, VkCommandBuffer cmd, VkPipelineBindPoint bindPoint, uint32_t setIndex, uint32_t *dynamicOffsets) @@ -1142,3 +1239,22 @@ void VulkanRenderState::SetFramebuffer(WrappedVulkan *vk, ResourceId fb, fbattachments[i] = GetResID(attachmentsInfo->pAttachments[i]); } } + +void VulkanRenderState::BindLastPushConstants(WrappedVulkan *vk, VkCommandBuffer cmd) +{ + if(pushLayout != ResourceId()) + { + // set push constants with the last layout used + VkPipelineLayout layout = + vk->GetResourceManager()->GetCurrentHandle(pushLayout); + + const rdcarray &pushRanges = + vk->GetDebugManager()->GetPipelineLayoutInfo(pushLayout).pushRanges; + + // only set push constant ranges that the layout uses + for(size_t i = 0; i < pushRanges.size(); i++) + ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags, + pushRanges[i].offset, pushRanges[i].size, + pushconsts + pushRanges[i].offset); + } +} diff --git a/renderdoc/driver/vulkan/vk_state.h b/renderdoc/driver/vulkan/vk_state.h index 6390ee902..a9ee7f549 100644 --- a/renderdoc/driver/vulkan/vk_state.h +++ b/renderdoc/driver/vulkan/vk_state.h @@ -35,6 +35,9 @@ struct VulkanStatePipeline { ResourceId pipeline; + // shader object + bool shaderObject = false; + struct DescriptorAndOffsets { ResourceId pipeLayout; @@ -63,6 +66,8 @@ struct VulkanRenderState void BeginRenderPassAndApplyState(WrappedVulkan *vk, VkCommandBuffer cmd, PipelineBinding binding, bool obeySuspending); void BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd, PipelineBinding binding, bool subpass0); + void BindShaderObjects(WrappedVulkan *vk, VkCommandBuffer cmd, PipelineBinding binding); + void BindDynamicState(WrappedVulkan *vk, VkCommandBuffer cmd); void EndRenderPass(VkCommandBuffer cmd); void FinishSuspendedRenderPass(VkCommandBuffer cmd); @@ -283,6 +288,9 @@ struct VulkanRenderState VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, }; + // shader objects + ResourceId shaderObjects[NumShaderStages]; + // attachment feedback loop VkImageAspectFlags feedbackAspects = VK_IMAGE_ASPECT_NONE; @@ -297,6 +305,11 @@ private: void BindDescriptorSetsWithoutPipeline(WrappedVulkan *vk, VkCommandBuffer cmd, VulkanStatePipeline &pipe, VkPipelineBindPoint bindPoint); + void BindDescriptorSetsForShaders(WrappedVulkan *vk, VkCommandBuffer cmd, + VulkanStatePipeline &pipe, VkPipelineBindPoint bindPoint); + void BindDescriptorSet(WrappedVulkan *vk, const DescSetLayout &descLayout, VkCommandBuffer cmd, VkPipelineBindPoint bindPoint, uint32_t setIndex, uint32_t *dynamicOffsets); + + void BindLastPushConstants(WrappedVulkan *vk, VkCommandBuffer cmd); }; diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index 54384cc64..906b11a1b 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -3096,10 +3096,23 @@ bool WrappedVulkan::Serialise_vkCmdBindPipeline(SerialiserType &ser, VkCommandBu if(pipelineBindPoint == VK_PIPELINE_BIND_POINT_COMPUTE) { renderstate.compute.pipeline = liveid; + renderstate.compute.shaderObject = false; + + // disturb compute shader bound via vkCmdBindShadersEXT, if any + renderstate.shaderObjects[(uint32_t)ShaderStage::Compute] = ResourceId(); } else { renderstate.graphics.pipeline = liveid; + renderstate.graphics.shaderObject = false; + + // disturb graphics shaders bound via vkCmdBindShadersEXT, if any + for(uint32_t i = 0; i < (uint32_t)ShaderStage::Count; i++) + { + if(i == (uint32_t)ShaderStage::Compute) + continue; + renderstate.shaderObjects[i] = ResourceId(); + } const VulkanCreationInfo::Pipeline &pipeInfo = m_CreationInfo.m_Pipeline[liveid]; @@ -3416,10 +3429,12 @@ bool WrappedVulkan::Serialise_vkCmdBindPipeline(SerialiserType &ser, VkCommandBu if(pipelineBindPoint == VK_PIPELINE_BIND_POINT_COMPUTE) { m_BakedCmdBufferInfo[m_LastCmdBufferID].state.compute.pipeline = liveid; + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.compute.shaderObject = false; } else { m_BakedCmdBufferInfo[m_LastCmdBufferID].state.graphics.pipeline = liveid; + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.graphics.shaderObject = false; const VulkanCreationInfo::Pipeline &pipeInfo = m_CreationInfo.m_Pipeline[liveid]; @@ -8045,14 +8060,19 @@ bool WrappedVulkan::Serialise_vkCmdBindShadersEXT(SerialiserType &ser, { int stageIndex = StageIndex(pStages[i]); + renderstate.shaderObjects[stageIndex] = + pShaders && (pShaders[i] != VK_NULL_HANDLE) ? GetResID(pShaders[i]) : ResourceId(); + // calling vkCmdBindShadersEXT disturbs the corresponding pipeline bind points // such that any pipelines previously bound to those points are no longer bound if(stageIndex == (int)ShaderStage::Compute) { + renderstate.compute.shaderObject = true; renderstate.compute.pipeline = ResourceId(); } else { + renderstate.graphics.shaderObject = true; renderstate.graphics.pipeline = ResourceId(); } } @@ -8070,13 +8090,18 @@ bool WrappedVulkan::Serialise_vkCmdBindShadersEXT(SerialiserType &ser, { int stageIndex = StageIndex(pStages[i]); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.shaderObjects[stageIndex] = + pShaders && (pShaders[i] != VK_NULL_HANDLE) ? GetResID(pShaders[i]) : ResourceId(); + if(stageIndex == (int)ShaderStage::Compute) { m_BakedCmdBufferInfo[m_LastCmdBufferID].state.compute.pipeline = ResourceId(); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.compute.shaderObject = true; } else { m_BakedCmdBufferInfo[m_LastCmdBufferID].state.graphics.pipeline = ResourceId(); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.graphics.shaderObject = true; } } } diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index f55a517d5..562323ab1 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -2025,7 +2025,9 @@ void DoSerialise(SerialiserType &ser, VKPipe::Shader &el) SERIALISE_MEMBER(specializationData); SERIALISE_MEMBER(specializationIds); - SIZE_CHECK(104); + SERIALISE_MEMBER(shaderObject); + + SIZE_CHECK(112); } template @@ -2286,7 +2288,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::State &el) SERIALISE_MEMBER(conditionalRendering); - SIZE_CHECK(1744); + SIZE_CHECK(1808); } #pragma endregion Vulkan pipeline state