From 06e48e3040a3961621383fc06df5eaf937f7eecf Mon Sep 17 00:00:00 2001 From: Shahbaz Youssefi Date: Mon, 21 Oct 2024 23:17:51 -0400 Subject: [PATCH] Support VK_KHR_dynamic_rendering_local_read Fixes #3341 --- .../VulkanPipelineStateViewer.cpp | 94 +++++++++++- renderdoc/api/replay/vk_pipestate.h | 34 ++++- renderdoc/driver/vulkan/extension_support.md | 2 +- renderdoc/driver/vulkan/vk_common.cpp | 102 +++++++++++++ renderdoc/driver/vulkan/vk_common.h | 48 ++++++ renderdoc/driver/vulkan/vk_core.cpp | 8 + renderdoc/driver/vulkan/vk_core.h | 9 ++ renderdoc/driver/vulkan/vk_hookset_defs.h | 8 + renderdoc/driver/vulkan/vk_info.cpp | 6 + renderdoc/driver/vulkan/vk_info.h | 3 + renderdoc/driver/vulkan/vk_next_chains.cpp | 9 +- renderdoc/driver/vulkan/vk_overlay.cpp | 26 ++++ renderdoc/driver/vulkan/vk_pixelhistory.cpp | 23 ++- renderdoc/driver/vulkan/vk_replay.cpp | 13 +- renderdoc/driver/vulkan/vk_serialise.cpp | 71 ++++++++- renderdoc/driver/vulkan/vk_state.cpp | 10 ++ renderdoc/driver/vulkan/vk_state.h | 3 + renderdoc/driver/vulkan/vk_stringise.cpp | 4 +- .../driver/vulkan/wrappers/vk_cmd_funcs.cpp | 3 + .../vulkan/wrappers/vk_device_funcs.cpp | 8 + .../vulkan/wrappers/vk_dynamic_funcs.cpp | 139 ++++++++++++++++++ renderdoc/replay/renderdoc_serialise.inl | 12 +- 22 files changed, 608 insertions(+), 27 deletions(-) diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index 9d20ca834a..4f350e60eb 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -2614,12 +2614,32 @@ void VulkanPipelineStateViewer::setState() { slotname = QFormatStr("Color %1").arg(a.localIdx); + // With dynamic rendering, the API references the framebuffer index everywhere, for + // example when specifying blend state for attachments or with vkCmdClearAttachments. As + // such, RenderDoc shows the same index in Color attachments (i.e. fbIdx == localIdx) to + // avoid confusion, even when VK_KHR_dynamic_rendering_local_read maps these attachments + // to different "locations" used by the shader. In that case, the mapped location is + // shown besides the attachment index. + uint32_t location = a.localIdx; + if(a.fbIdx < rp.colorAttachmentLocations.count()) + { + location = rp.colorAttachmentLocations[a.fbIdx]; + if(location == VKPipe::RenderPass::AttachmentUnused) + { + slotname += QFormatStr(" [disabled]"); + } + else + { + slotname += QFormatStr(" [location %1]").arg(location); + } + } + if(state.fragmentShader.reflection != NULL) { const rdcarray &outSig = state.fragmentShader.reflection->outputSignature; for(int s = 0; s < outSig.count(); s++) { - if(outSig[s].regIndex == (uint32_t)a.localIdx && + if(outSig[s].regIndex == location && (outSig[s].systemValue == ShaderBuiltin::Undefined || outSig[s].systemValue == ShaderBuiltin::ColorOutput)) { @@ -2819,6 +2839,22 @@ void VulkanPipelineStateViewer::setState() if(showNode(usedSlot, /*filledSlot*/ true)) { + QString writemask = QFormatStr("%1%2%3%4") + .arg((blend.writeMask & 0x1) == 0 ? lit("_") : lit("R")) + .arg((blend.writeMask & 0x2) == 0 ? lit("_") : lit("G")) + .arg((blend.writeMask & 0x4) == 0 ? lit("_") : lit("B")) + .arg((blend.writeMask & 0x8) == 0 ? lit("_") : lit("A")); + + // With VK_KHR_dynamic_rendering_local_read, if a color attachment is mapped to + // VK_ATTACHMENT_UNUSED, it is implicitly disabled. The Slot name in the "Render Pass" + // pane already tags the attachment with [disabled], but for clarity the write mask is also + // set to DISABLED here. + if(i < rp.colorAttachmentLocations.count() && + rp.colorAttachmentLocations[i] == VKPipe::RenderPass::AttachmentUnused) + { + writemask = lit("DISABLED"); + } + RDTreeWidgetItem *node = new RDTreeWidgetItem( {i, blend.enabled ? tr("True") : tr("False"), @@ -2828,11 +2864,7 @@ void VulkanPipelineStateViewer::setState() ToQStr(blend.alphaBlend.source), ToQStr(blend.alphaBlend.destination), ToQStr(blend.alphaBlend.operation), - QFormatStr("%1%2%3%4") - .arg((blend.writeMask & 0x1) == 0 ? lit("_") : lit("R")) - .arg((blend.writeMask & 0x2) == 0 ? lit("_") : lit("G")) - .arg((blend.writeMask & 0x4) == 0 ? lit("_") : lit("B")) - .arg((blend.writeMask & 0x8) == 0 ? lit("_") : lit("A"))}); + writemask}); if(!usedSlot) setInactiveRow(node); @@ -4188,6 +4220,40 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe:: xml.writeEndElement(); } + if(!pass.renderpass.colorAttachmentLocations.isEmpty()) + { + QList locations; + + for(int i = 0; i < pass.renderpass.colorAttachmentLocations.count(); i++) + locations.push_back({pass.renderpass.colorAttachmentLocations[i]}); + + m_Common.exportHTMLTable(xml, + { + tr("Color Attachment Location"), + }, + locations); + + xml.writeStartElement(lit("p")); + xml.writeEndElement(); + } + + if(!pass.renderpass.colorAttachmentInputIndices.isEmpty()) + { + QList inputIndices; + + for(int i = 0; i < pass.renderpass.colorAttachmentInputIndices.count(); i++) + inputIndices.push_back({pass.renderpass.colorAttachmentInputIndices[i]}); + + m_Common.exportHTMLTable(xml, + { + tr("Color Attachment Input Index"), + }, + inputIndices); + + xml.writeStartElement(lit("p")); + xml.writeEndElement(); + } + if(!pass.renderpass.resolveAttachments.isEmpty()) { QList resolves; @@ -4213,6 +4279,22 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe:: xml.writeEndElement(); } + if(!pass.renderpass.isDepthInputAttachmentIndexImplicit) + { + xml.writeStartElement(lit("p")); + xml.writeCharacters( + tr("Depth Input Attachment Index: %1").arg(pass.renderpass.depthInputAttachmentIndex)); + xml.writeEndElement(); + } + + if(!pass.renderpass.isStencilInputAttachmentIndexImplicit) + { + xml.writeStartElement(lit("p")); + xml.writeCharacters( + tr("Stencil Input Attachment Index: %1").arg(pass.renderpass.stencilInputAttachmentIndex)); + xml.writeEndElement(); + } + if(pass.renderpass.depthstencilResolveAttachment >= 0) { xml.writeStartElement(lit("p")); diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index a3d58df5c1..35a956557f 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -748,7 +748,13 @@ struct DepthStencil float maxDepthBounds = 0.0f; }; -DOCUMENT("Describes the setup of a renderpass and subpasses."); +DOCUMENT(R"(Describes the setup of a renderpass and subpasses. + +.. data:: AttachmentUnused + + Alias for VK_ATTACHMENT_UNUSED, for use by the UI to know when a value in colorAttachmentLocations + or colorAttachmentInputIndices is mapped to VK_ATTACHMENT_UNUSED. +)"); struct RenderPass { DOCUMENT(""); @@ -859,6 +865,32 @@ samples used to render this subpass. If the subpass is not internally multisampled, tileOnlyMSAASampleCount is set to 0. )"); uint32_t tileOnlyMSAASampleCount = 0; + + DOCUMENT(R"(The color index->location mapping set up by dynamic rendering local read. + +:type: List[int] +)"); + rdcarray colorAttachmentLocations; + + DOCUMENT(R"(The color index->input index mapping set up by dynamic rendering local read. + +:type: List[int] +)"); + rdcarray colorAttachmentInputIndices; + + DOCUMENT("Whether or not depth input attachment index is implicit (dynamic rendering)."); + bool isDepthInputAttachmentIndexImplicit = true; + + DOCUMENT("Whether or not stencil input attachment index is implicit (dynamic rendering)."); + bool isStencilInputAttachmentIndexImplicit = true; + + DOCUMENT("Depth input attachment index if explicit (dynamic rendering)."); + uint32_t depthInputAttachmentIndex = UINT32_MAX; + + DOCUMENT("Stencil input attachment index if explicit (dynamic rendering)."); + uint32_t stencilInputAttachmentIndex = UINT32_MAX; + + static const uint32_t AttachmentUnused = ~0U; }; DOCUMENT("Describes a framebuffer object and its attachments."); diff --git a/renderdoc/driver/vulkan/extension_support.md b/renderdoc/driver/vulkan/extension_support.md index 4d71649a5b..010fb78cc9 100644 --- a/renderdoc/driver/vulkan/extension_support.md +++ b/renderdoc/driver/vulkan/extension_support.md @@ -144,6 +144,7 @@ Maintainers can update this file by updating vk.xml in this folder and running ` * `VK_KHR_draw_indirect_count` * `VK_KHR_driver_properties` * `VK_KHR_dynamic_rendering` +* `VK_KHR_dynamic_rendering_local_read` * `VK_KHR_external_fence_capabilities` * `VK_KHR_external_fence_fd` * `VK_KHR_external_fence_win32` @@ -241,7 +242,6 @@ KHR extensions will definitely be implemented at some point, though KHR extensio ## KHR Extensions * `VK_KHR_cooperative_matrix` -* `VK_KHR_dynamic_rendering_local_read` * `VK_KHR_maintenance5` * `VK_KHR_maintenance6` * `VK_KHR_map_memory2` diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index fc4521d18b..99499489b2 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -1366,6 +1366,108 @@ void DescriptorSetSlot::AccumulateBindRefs(DescriptorBindRefs &refs, VulkanResou } } +void DynamicRenderingLocalRead::Init(const VkBaseInStructure *infoStruct) +{ + const VkRenderingAttachmentLocationInfoKHR *attachmentLocationInfo = + (const VkRenderingAttachmentLocationInfoKHR *)FindNextStruct( + infoStruct, VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR); + if(attachmentLocationInfo != NULL) + { + UpdateLocations(*attachmentLocationInfo); + } + + const VkRenderingInputAttachmentIndexInfoKHR *inputAttachmentIndexInfo = + (const VkRenderingInputAttachmentIndexInfoKHR *)FindNextStruct( + infoStruct, VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR); + if(inputAttachmentIndexInfo != NULL) + { + UpdateInputIndices(*inputAttachmentIndexInfo); + } +} + +void DynamicRenderingLocalRead::UpdateLocations( + const VkRenderingAttachmentLocationInfoKHR &attachmentLocationInfo) +{ + // If NULL is given, an identity mapping is assumed. This is indicated by an empty + // array. This works out because not providing VkRenderingAttachmentLocationInfoKHR has the + // same meaning. + if(attachmentLocationInfo.pColorAttachmentLocations == NULL) + { + colorAttachmentLocations.clear(); + } + else + { + colorAttachmentLocations.assign(attachmentLocationInfo.pColorAttachmentLocations, + attachmentLocationInfo.colorAttachmentCount); + } +} + +void DynamicRenderingLocalRead::UpdateInputIndices( + const VkRenderingInputAttachmentIndexInfoKHR &inputAttachmentIndexInfo) +{ + // If NULL is given, an identity mapping is assumed. This is indicated by an empty + // array. This works out because not providing VkRenderingInputAttachmentIndexInfoKHR has the + // same meaning. + if(inputAttachmentIndexInfo.pColorAttachmentInputIndices == NULL) + { + colorAttachmentInputIndices.clear(); + } + else + { + colorAttachmentInputIndices.assign(inputAttachmentIndexInfo.pColorAttachmentInputIndices, + inputAttachmentIndexInfo.colorAttachmentCount); + } + isDepthInputAttachmentIndexImplicit = inputAttachmentIndexInfo.pDepthInputAttachmentIndex == NULL; + isStencilInputAttachmentIndexImplicit = + inputAttachmentIndexInfo.pStencilInputAttachmentIndex == NULL; + if(!isDepthInputAttachmentIndexImplicit) + { + depthInputAttachmentIndex = *inputAttachmentIndexInfo.pDepthInputAttachmentIndex; + } + if(!isStencilInputAttachmentIndexImplicit) + { + stencilInputAttachmentIndex = *inputAttachmentIndexInfo.pStencilInputAttachmentIndex; + } +} + +void DynamicRenderingLocalRead::CopyLocations(const DynamicRenderingLocalRead &from) +{ + colorAttachmentLocations = from.colorAttachmentLocations; +} + +void DynamicRenderingLocalRead::CopyInputIndices(const DynamicRenderingLocalRead &from) +{ + colorAttachmentInputIndices = from.colorAttachmentInputIndices; + isDepthInputAttachmentIndexImplicit = from.isDepthInputAttachmentIndexImplicit; + isStencilInputAttachmentIndexImplicit = from.isStencilInputAttachmentIndexImplicit; + depthInputAttachmentIndex = from.depthInputAttachmentIndex; + stencilInputAttachmentIndex = from.stencilInputAttachmentIndex; +} + +void DynamicRenderingLocalRead::SetLocations(VkCommandBuffer cmd) +{ + VkRenderingAttachmentLocationInfoKHR attachmentLocations = {}; + attachmentLocations.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR; + attachmentLocations.colorAttachmentCount = colorAttachmentLocations.count(); + attachmentLocations.pColorAttachmentLocations = colorAttachmentLocations.data(); + + ObjDisp(cmd)->CmdSetRenderingAttachmentLocationsKHR(Unwrap(cmd), &attachmentLocations); +} + +void DynamicRenderingLocalRead::SetInputIndices(VkCommandBuffer cmd) +{ + VkRenderingInputAttachmentIndexInfoKHR inputIndices = {}; + inputIndices.sType = VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR; + inputIndices.colorAttachmentCount = colorAttachmentInputIndices.count(); + inputIndices.pColorAttachmentInputIndices = colorAttachmentInputIndices.data(); + inputIndices.pDepthInputAttachmentIndex = + isDepthInputAttachmentIndexImplicit ? NULL : &depthInputAttachmentIndex; + inputIndices.pStencilInputAttachmentIndex = + isStencilInputAttachmentIndexImplicit ? NULL : &stencilInputAttachmentIndex; + + ObjDisp(cmd)->CmdSetRenderingInputAttachmentIndicesKHR(Unwrap(cmd), &inputIndices); +} + #if ENABLED(ENABLE_UNIT_TESTS) #undef None diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index be5e7551b0..01e589868b 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -326,6 +326,46 @@ class VkDriverInfo bool maliBrokenASDeviceSerialisation = false; }; +struct DynamicRenderingLocalRead +{ + void Init(const VkBaseInStructure *infoStruct); + + void UpdateLocations(const VkRenderingAttachmentLocationInfoKHR &attachmentLocationInfo); + void UpdateInputIndices(const VkRenderingInputAttachmentIndexInfoKHR &inputAttachmentIndexInfo); + + void CopyLocations(const DynamicRenderingLocalRead &from); + void CopyInputIndices(const DynamicRenderingLocalRead &from); + + bool AreLocationsNonDefault() { return !colorAttachmentLocations.isEmpty(); } + bool AreInputIndicesNonDefault() + { + return !colorAttachmentInputIndices.isEmpty() || !isDepthInputAttachmentIndexImplicit || + !isStencilInputAttachmentIndexImplicit; + } + + void SetLocations(VkCommandBuffer cmd); + void SetInputIndices(VkCommandBuffer cmd); + + // VkRenderingAttachmentLocationInfoKHR + // Notes: + // - If the array is empty, it indicates an identity mapping. + // - If an element is VK_ATTACHMENT_UNUSED, writes to it are disabled (as if the color + // attachment is masked) + rdcarray colorAttachmentLocations; + + // VkRenderingInputAttachmentIndexInfoKHR + // Notes: + // - The depth/stencil indices are only set if the is..Implicit flag is false. By default, the + // depth/stencil indices are assumed to be implicit (no input_attachment_index decoration + // needed in the shader). + // - If an element is VK_ATTACHMENT_UNUSED, it won't be used as input attachment. + rdcarray colorAttachmentInputIndices; + bool isDepthInputAttachmentIndexImplicit = true; + bool isStencilInputAttachmentIndexImplicit = true; + uint32_t depthInputAttachmentIndex = ~0U; + uint32_t stencilInputAttachmentIndex = ~0U; +}; + enum { VkCheckLayer_unique_objects, @@ -1091,6 +1131,8 @@ enum class VulkanChunk : uint32_t vkCmdTraceRaysIndirectKHR, vkCmdTraceRaysKHR, vkCreateRayTracingPipelinesKHR, + vkCmdSetRenderingAttachmentLocationsKHR, + vkCmdSetRenderingInputAttachmentIndicesKHR, Max, }; @@ -1335,6 +1377,7 @@ DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDescriptorIndexingProperties) DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDiscardRectanglePropertiesEXT); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDriverProperties); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDynamicRenderingFeatures); +DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceExtendedDynamicState3FeaturesEXT); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceExtendedDynamicState3PropertiesEXT); @@ -1519,8 +1562,10 @@ DECLARE_REFLECTION_STRUCT(VkRayTracingShaderGroupCreateInfoKHR); DECLARE_REFLECTION_STRUCT(VkRefreshCycleDurationGOOGLE); DECLARE_REFLECTION_STRUCT(VkReleaseSwapchainImagesInfoEXT); DECLARE_REFLECTION_STRUCT(VkRenderingAttachmentInfo); +DECLARE_REFLECTION_STRUCT(VkRenderingAttachmentLocationInfoKHR); DECLARE_REFLECTION_STRUCT(VkRenderingFragmentDensityMapAttachmentInfoEXT); DECLARE_REFLECTION_STRUCT(VkRenderingFragmentShadingRateAttachmentInfoKHR); +DECLARE_REFLECTION_STRUCT(VkRenderingInputAttachmentIndexInfoKHR); DECLARE_REFLECTION_STRUCT(VkRenderingInfo); DECLARE_REFLECTION_STRUCT(VkRenderPassAttachmentBeginInfo); DECLARE_REFLECTION_STRUCT(VkRenderPassBeginInfo); @@ -1775,6 +1820,7 @@ DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDescriptorIndexingProperties) DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDiscardRectanglePropertiesEXT); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDriverProperties); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDynamicRenderingFeatures); +DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicState3FeaturesEXT); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicState3PropertiesEXT); @@ -1957,8 +2003,10 @@ DECLARE_DESERIALISE_TYPE(VkRayTracingPipelineInterfaceCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkRayTracingShaderGroupCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkReleaseSwapchainImagesInfoEXT); DECLARE_DESERIALISE_TYPE(VkRenderingAttachmentInfo); +DECLARE_DESERIALISE_TYPE(VkRenderingAttachmentLocationInfoKHR); DECLARE_DESERIALISE_TYPE(VkRenderingFragmentDensityMapAttachmentInfoEXT); DECLARE_DESERIALISE_TYPE(VkRenderingFragmentShadingRateAttachmentInfoKHR); +DECLARE_DESERIALISE_TYPE(VkRenderingInputAttachmentIndexInfoKHR); DECLARE_DESERIALISE_TYPE(VkRenderingInfo); DECLARE_DESERIALISE_TYPE(VkRenderPassAttachmentBeginInfo); DECLARE_DESERIALISE_TYPE(VkRenderPassBeginInfo); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index bdeef59443..d320fdbb95 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1490,6 +1490,10 @@ static const VkExtensionProperties supportedExtensions[] = { VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION, }, + { + VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME, + VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_SPEC_VERSION, + }, { VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_SPEC_VERSION, @@ -4230,6 +4234,10 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk) case VulkanChunk::vkCmdBeginRendering: return Serialise_vkCmdBeginRendering(ser, VK_NULL_HANDLE, NULL); case VulkanChunk::vkCmdEndRendering: return Serialise_vkCmdEndRendering(ser, VK_NULL_HANDLE); + case VulkanChunk::vkCmdSetRenderingAttachmentLocationsKHR: + return Serialise_vkCmdSetRenderingAttachmentLocationsKHR(ser, VK_NULL_HANDLE, NULL); + case VulkanChunk::vkCmdSetRenderingInputAttachmentIndicesKHR: + return Serialise_vkCmdSetRenderingInputAttachmentIndicesKHR(ser, VK_NULL_HANDLE, NULL); case VulkanChunk::vkCmdSetFragmentShadingRateKHR: return Serialise_vkCmdSetFragmentShadingRateKHR(ser, VK_NULL_HANDLE, NULL, NULL); diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 7c37efbb7e..a72ea88a62 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -2787,6 +2787,15 @@ class WrappedVulkan : public IFrameCapturer IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdEndRendering, VkCommandBuffer commandBuffer); + // VK_KHR_dynamic_rendering_local_read + + IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdSetRenderingAttachmentLocationsKHR, + VkCommandBuffer commandBuffer, + const VkRenderingAttachmentLocationInfoKHR *pLocationInfo); + IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdSetRenderingInputAttachmentIndicesKHR, + VkCommandBuffer commandBuffer, + const VkRenderingInputAttachmentIndexInfoKHR *pLocationInfo); + // VK_KHR_fragment_shading_rate IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdSetFragmentShadingRateKHR, VkCommandBuffer commandBuffer, diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index a964af88d0..c283d52a2d 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -522,6 +522,7 @@ DeclExt(EXT_multisampled_render_to_single_sampled); \ DeclExt(EXT_vertex_input_dynamic_state); \ DeclExt(KHR_dynamic_rendering); \ + DeclExt(KHR_dynamic_rendering_local_read); \ DeclExt(KHR_fragment_shading_rate); \ DeclExt(EXT_attachment_feedback_loop_layout); \ DeclExt(EXT_pageable_device_local_memory); \ @@ -651,6 +652,7 @@ CheckExt(EXT_multisampled_render_to_single_sampled, VKXX); \ CheckExt(EXT_vertex_input_dynamic_state, VKXX); \ CheckExt(KHR_dynamic_rendering, VK13); \ + CheckExt(KHR_dynamic_rendering_local_read, VKXX); \ CheckExt(KHR_fragment_shading_rate, VKXX); \ CheckExt(EXT_attachment_feedback_loop_layout, VKXX); \ CheckExt(EXT_pageable_device_local_memory, VKXX); \ @@ -941,6 +943,8 @@ HookInitExtension(EXT_vertex_input_dynamic_state || EXT_shader_object, CmdSetVertexInputEXT); \ HookInitPromotedExtension(KHR_dynamic_rendering, CmdBeginRendering, KHR); \ HookInitPromotedExtension(KHR_dynamic_rendering, CmdEndRendering, KHR); \ + HookInitExtension(KHR_dynamic_rendering_local_read, CmdSetRenderingAttachmentLocationsKHR); \ + HookInitExtension(KHR_dynamic_rendering_local_read, CmdSetRenderingInputAttachmentIndicesKHR); \ HookInitExtension(KHR_fragment_shading_rate, CmdSetFragmentShadingRateKHR); \ HookInitExtension(EXT_pageable_device_local_memory, SetDeviceMemoryPriorityEXT); \ HookInitExtension(EXT_swapchain_maintenance1, ReleaseSwapchainImagesEXT); \ @@ -1743,6 +1747,10 @@ HookDefine2(void, vkCmdBeginRendering, VkCommandBuffer, commandBuffer, const VkRenderingInfo *, \ pRenderingInfo); \ HookDefine1(void, vkCmdEndRendering, VkCommandBuffer, commandBuffer); \ + HookDefine2(void, vkCmdSetRenderingAttachmentLocationsKHR, VkCommandBuffer, commandBuffer, \ + const VkRenderingAttachmentLocationInfoKHR *, pLocationInfo); \ + HookDefine2(void, vkCmdSetRenderingInputAttachmentIndicesKHR, VkCommandBuffer, commandBuffer, \ + const VkRenderingInputAttachmentIndexInfoKHR *, pInputAttachmentIndexInfo); \ HookDefine3(void, vkCmdSetFragmentShadingRateKHR, VkCommandBuffer, commandBuffer, \ const VkExtent2D *, pFragmentSize, const VkFragmentShadingRateCombinerOpKHR *, \ combinerOps); \ diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp index 02896c56c9..72fead1cb9 100644 --- a/renderdoc/driver/vulkan/vk_info.cpp +++ b/renderdoc/driver/vulkan/vk_info.cpp @@ -1109,6 +1109,8 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, stencilFormat = VK_FORMAT_UNDEFINED; } + dynamicRenderingLocalRead.Init((const VkBaseInStructure *)pCreateInfo); + RDCEraseEl(dynamicStates); if(pCreateInfo->pDynamicState) { @@ -1645,6 +1647,8 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, shadingRateCombiners[0] = pipeInfo.shadingRateCombiners[0]; shadingRateCombiners[1] = pipeInfo.shadingRateCombiners[1]; + dynamicRenderingLocalRead.CopyInputIndices(pipeInfo.dynamicRenderingLocalRead); + flags |= pipeInfo.flags; } @@ -1674,6 +1678,8 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, depthFormat = pipeInfo.depthFormat; stencilFormat = pipeInfo.stencilFormat; + dynamicRenderingLocalRead.CopyLocations(pipeInfo.dynamicRenderingLocalRead); + flags |= pipeInfo.flags; } } diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index 9c446f235c..eb7f7bf530 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -288,6 +288,9 @@ struct VulkanCreationInfo VkFormat depthFormat; VkFormat stencilFormat; + // VkRenderingAttachmentLocationInfoKHR and VkRenderingInputAttachmentIndexInfoKHR + DynamicRenderingLocalRead dynamicRenderingLocalRead; + // a variant of the pipeline that uses subpass 0, used for when we are replaying in isolation. // See loadRPs in the RenderPass info VkPipeline subpass0pipe; diff --git a/renderdoc/driver/vulkan/vk_next_chains.cpp b/renderdoc/driver/vulkan/vk_next_chains.cpp index dd05904255..5a69f7244a 100644 --- a/renderdoc/driver/vulkan/vk_next_chains.cpp +++ b/renderdoc/driver/vulkan/vk_next_chains.cpp @@ -272,6 +272,8 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, VkPhysicalDeviceDriverProperties); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, \ VkPhysicalDeviceDynamicRenderingFeatures) \ + COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR, \ + VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR) \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT, \ VkPhysicalDeviceExtendedDynamicStateFeaturesEXT); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT, \ @@ -663,6 +665,10 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, VkVertexInputBindingDescription2EXT); \ COPY_STRUCT(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK, \ VkWriteDescriptorSetInlineUniformBlock); \ + COPY_STRUCT(VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR, \ + VkRenderingAttachmentLocationInfoKHR); \ + COPY_STRUCT(VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR, \ + VkRenderingInputAttachmentIndexInfoKHR); \ COPY_STRUCT_CAPTURE_ONLY(VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO, \ VkLayerInstanceCreateInfo); \ COPY_STRUCT_CAPTURE_ONLY(VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO, VkLayerDeviceCreateInfo); \ @@ -998,7 +1004,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: \ - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV: \ @@ -1140,8 +1145,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT: \ case VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM: \ case VK_STRUCTURE_TYPE_RENDERING_AREA_INFO_KHR: \ - case VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR: \ - case VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR: \ case VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM: \ case VK_STRUCTURE_TYPE_SAMPLER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT: \ case VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM: \ diff --git a/renderdoc/driver/vulkan/vk_overlay.cpp b/renderdoc/driver/vulkan/vk_overlay.cpp index 2a256c7e1f..6f0b3323f5 100644 --- a/renderdoc/driver/vulkan/vk_overlay.cpp +++ b/renderdoc/driver/vulkan/vk_overlay.cpp @@ -325,6 +325,21 @@ struct VulkanQuadOverdrawCallback : public VulkanActionCallback pipestate.BindShaderObjects(m_pDriver, cmd, VulkanRenderState::BindGraphics); else pipestate.BindPipeline(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); + + // Reset the attachment mapping, if any + if(m_PrevState.dynamicRendering.localRead.AreLocationsNonDefault()) + { + VkRenderingAttachmentLocationInfoKHR attachmentLocations = {}; + attachmentLocations.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR; + m_pDriver->vkCmdSetRenderingAttachmentLocationsKHR(cmd, &attachmentLocations); + } + if(m_PrevState.dynamicRendering.localRead.AreInputIndicesNonDefault()) + { + VkRenderingInputAttachmentIndexInfoKHR inputIndices = {}; + inputIndices.sType = VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR; + + m_pDriver->vkCmdSetRenderingInputAttachmentIndicesKHR(cmd, &inputIndices); + } } } @@ -344,6 +359,17 @@ struct VulkanQuadOverdrawCallback : public VulkanActionCallback m_pDriver->GetCmdRenderState().BindPipeline(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); + // Restore the attachment mappings, if any. + if(m_PrevState.dynamicRendering.localRead.AreLocationsNonDefault()) + { + m_PrevState.dynamicRendering.localRead.SetLocations(cmd); + } + + if(m_PrevState.dynamicRendering.localRead.AreInputIndicesNonDefault()) + { + m_PrevState.dynamicRendering.localRead.SetInputIndices(cmd); + } + return true; } diff --git a/renderdoc/driver/vulkan/vk_pixelhistory.cpp b/renderdoc/driver/vulkan/vk_pixelhistory.cpp index 57063d92d2..f70143683e 100644 --- a/renderdoc/driver/vulkan/vk_pixelhistory.cpp +++ b/renderdoc/driver/vulkan/vk_pixelhistory.cpp @@ -3218,11 +3218,13 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback for(uint32_t i = 0; i < 2; i++) { uint32_t storeOffset = (fragsProcessed + f) * sizeof(PerFragmentInfo); + bool isPrimitiveIDPipe = i == 0; - VkMarkerRegion region(cmd, StringFormat::Fmt("Getting %s for %u", - i == 0 ? "primitive ID" : "shader output", eid)); + VkMarkerRegion region( + cmd, StringFormat::Fmt("Getting %s for %u", + isPrimitiveIDPipe ? "primitive ID" : "shader output", eid)); - if(i == 0 && !m_pDriver->GetDeviceEnabledFeatures().geometryShader) + if(isPrimitiveIDPipe && !m_pDriver->GetDeviceEnabledFeatures().geometryShader) { // without geometryShader, can't read primitive ID in pixel shader VkMarkerRegion::Set("Can't get primitive ID without geometryShader feature", cmd); @@ -3303,7 +3305,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback state.shaderObjects[(uint32_t)ShaderStage::Fragment] = shadsIter[i]; // set dynamic state - if(i == 0) + if(isPrimitiveIDPipe) { // first pass - fragment shader which outputs primitive ID state.depthTestEnable = false; @@ -3317,6 +3319,13 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback } } + // The primitive ID shader always writes to location 0, so make sure that's not remapped + // with VK_KHR_dynamic_rendering_local_read. + if(isPrimitiveIDPipe && prevState.dynamicRendering.localRead.AreLocationsNonDefault()) + { + state.dynamicRendering.localRead = {}; + } + m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState( m_pDriver, cmd, VulkanRenderState::BindGraphics, false); @@ -3329,7 +3338,10 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback m_pDriver->ReplayDraw(cmd, *action); state.EndRenderPass(cmd); - if(i == 1) + // Restore location mapping for the other pipelines. + state.dynamicRendering.localRead = prevState.dynamicRendering.localRead; + + if(!isPrimitiveIDPipe) { storeOffset += offsetof(struct PerFragmentInfo, shaderOut); if(depthEnabled) @@ -3707,7 +3719,6 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback else { pipes.primitiveIdPipe = VK_NULL_HANDLE; - RDCWARN("Can't get primitive ID at event %u due to lack of geometry shader support", eid); } return pipes; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index ba50801c28..b8669ccf38 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -1786,7 +1786,7 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) rpState.resourceId = ResourceId(); rpState.subpass = 0; rpState.fragmentDensityOffsets.clear(); - rpState.tileOnlyMSAASampleCount = 0; + rpState.tileOnlyMSAASampleCount = dyn.tileOnlyMSAASampleCount; fbState.resourceId = ResourceId(); // dynamic rendering does not provide a framebuffer dimension, it's implicit from the image @@ -1942,6 +1942,17 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) if(dyn.viewMask & (1 << v)) rpState.multiviews.push_back(v); } + + ret.currentPass.renderpass.colorAttachmentLocations = dyn.localRead.colorAttachmentLocations; + ret.currentPass.renderpass.colorAttachmentInputIndices = + dyn.localRead.colorAttachmentInputIndices; + ret.currentPass.renderpass.isDepthInputAttachmentIndexImplicit = + dyn.localRead.isDepthInputAttachmentIndexImplicit; + ret.currentPass.renderpass.isStencilInputAttachmentIndexImplicit = + dyn.localRead.isStencilInputAttachmentIndexImplicit; + ret.currentPass.renderpass.depthInputAttachmentIndex = dyn.localRead.depthInputAttachmentIndex; + ret.currentPass.renderpass.stencilInputAttachmentIndex = + dyn.localRead.stencilInputAttachmentIndex; } else if(state.GetRenderPass() != ResourceId()) { diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index 2559a8c537..848a7c5966 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -1089,6 +1089,14 @@ SERIALISE_VK_HANDLES(); PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR, \ VkRenderingFragmentShadingRateAttachmentInfoKHR) \ \ + /* VK_KHR_dynamic_rendering_local_read */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR, \ + VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR, \ + VkRenderingAttachmentLocationInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR, \ + VkRenderingInputAttachmentIndexInfoKHR) \ + \ /* VK_KHR_external_fence_capabilities */ \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, \ VkPhysicalDeviceExternalFenceInfo) \ @@ -1717,11 +1725,6 @@ SERIALISE_VK_HANDLES(); PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR) \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR) \ \ - /* VK_KHR_dynamic_rendering_local_read */ \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR) \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR) \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR) \ - \ /* VK_KHR_map_memory2 */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR) \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR) \ @@ -9182,6 +9185,22 @@ void Deserialise(const VkPhysicalDeviceDynamicRenderingFeatures &el) DeserialiseNext(el.pNext); } +template +void DoSerialise(SerialiserType &ser, VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(dynamicRenderingLocalRead); +} + +template <> +void Deserialise(const VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR &el) +{ + DeserialiseNext(el.pNext); +} + template void DoSerialise(SerialiserType &ser, VkRenderingFragmentDensityMapAttachmentInfoEXT &el) { @@ -9328,6 +9347,45 @@ void Deserialise(const VkRenderingInfo &el) delete el.pStencilAttachment; } +template +void DoSerialise(SerialiserType &ser, VkRenderingAttachmentLocationInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(colorAttachmentCount).Important(); + SERIALISE_MEMBER_ARRAY(pColorAttachmentLocations, colorAttachmentCount); +} + +template <> +void Deserialise(const VkRenderingAttachmentLocationInfoKHR &el) +{ + DeserialiseNext(el.pNext); + delete[] el.pColorAttachmentLocations; +} + +template +void DoSerialise(SerialiserType &ser, VkRenderingInputAttachmentIndexInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(colorAttachmentCount).Important(); + SERIALISE_MEMBER_ARRAY(pColorAttachmentInputIndices, colorAttachmentCount); + SERIALISE_MEMBER_OPT(pDepthInputAttachmentIndex); + SERIALISE_MEMBER_OPT(pStencilInputAttachmentIndex); +} + +template <> +void Deserialise(const VkRenderingInputAttachmentIndexInfoKHR &el) +{ + DeserialiseNext(el.pNext); + delete[] el.pColorAttachmentInputIndices; + delete el.pDepthInputAttachmentIndex; + delete el.pStencilInputAttachmentIndex; +} + template void DoSerialise(SerialiserType &ser, VkPhysicalDeviceExternalFenceInfo &el) { @@ -12585,6 +12643,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDescriptorIndexingProperties) INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDiscardRectanglePropertiesEXT); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDriverProperties); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDynamicRenderingFeatures); +INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicState3FeaturesEXT); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicState3PropertiesEXT); @@ -12769,6 +12828,8 @@ INSTANTIATE_SERIALISE_TYPE(VkRenderingAttachmentInfo); INSTANTIATE_SERIALISE_TYPE(VkRenderingFragmentDensityMapAttachmentInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkRenderingFragmentShadingRateAttachmentInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkRenderingInfo); +INSTANTIATE_SERIALISE_TYPE(VkRenderingAttachmentLocationInfoKHR); +INSTANTIATE_SERIALISE_TYPE(VkRenderingInputAttachmentIndexInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkRenderPassAttachmentBeginInfo); INSTANTIATE_SERIALISE_TYPE(VkRenderPassBeginInfo); INSTANTIATE_SERIALISE_TYPE(VkRenderPassCreateInfo); diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp index 5116f7be1b..9ed7b42154 100644 --- a/renderdoc/driver/vulkan/vk_state.cpp +++ b/renderdoc/driver/vulkan/vk_state.cpp @@ -230,6 +230,16 @@ void VulkanRenderState::BeginRenderPassAndApplyState(WrappedVulkan *vk, VkComman ObjDisp(cmd)->CmdBeginConditionalRenderingEXT(Unwrap(cmd), &beginInfo); } + + if(dynamicRendering.localRead.AreLocationsNonDefault()) + { + dynamicRendering.localRead.SetLocations(cmd); + } + + if(dynamicRendering.localRead.AreInputIndicesNonDefault()) + { + dynamicRendering.localRead.SetInputIndices(cmd); + } } void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd) diff --git a/renderdoc/driver/vulkan/vk_state.h b/renderdoc/driver/vulkan/vk_state.h index b8417b6405..f484c99cb9 100644 --- a/renderdoc/driver/vulkan/vk_state.h +++ b/renderdoc/driver/vulkan/vk_state.h @@ -289,6 +289,9 @@ struct VulkanRenderState bool tileOnlyMSAAEnable = false; VkSampleCountFlagBits tileOnlyMSAASampleCount = VK_SAMPLE_COUNT_1_BIT; + + // VK_KHR_dynamic_rendering_local_read + DynamicRenderingLocalRead localRead; } dynamicRendering; // fdm offset diff --git a/renderdoc/driver/vulkan/vk_stringise.cpp b/renderdoc/driver/vulkan/vk_stringise.cpp index a231bbd215..e5a59aec9a 100644 --- a/renderdoc/driver/vulkan/vk_stringise.cpp +++ b/renderdoc/driver/vulkan/vk_stringise.cpp @@ -28,7 +28,7 @@ template <> rdcstr DoStringise(const VulkanChunk &el) { - RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1213, "Chunks changed without updating names"); + RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1215, "Chunks changed without updating names"); BEGIN_ENUM_STRINGISE(VulkanChunk) { @@ -245,6 +245,8 @@ rdcstr DoStringise(const VulkanChunk &el) STRINGISE_ENUM_CLASS(vkCmdTraceRaysIndirectKHR) STRINGISE_ENUM_CLASS(vkCmdTraceRaysKHR) STRINGISE_ENUM_CLASS(vkCreateRayTracingPipelinesKHR) + STRINGISE_ENUM_CLASS(vkCmdSetRenderingAttachmentLocationsKHR) + STRINGISE_ENUM_CLASS(vkCmdSetRenderingInputAttachmentIndicesKHR) STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk"); } END_ENUM_STRINGISE() diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index e8918619af..7937a75079 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -1258,6 +1258,9 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman BeginInfo.pInheritanceInfo->subpass; // framebuffer is not useful here since it may be incomplete (imageless) and it's // optional, so we should just treat it as never present. + + m_BakedCmdBufferInfo[BakedCommandBuffer].state.dynamicRendering.localRead.Init( + (const VkBaseInStructure *)BeginInfo.pInheritanceInfo); } ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &unwrappedBeginInfo); diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 82ba365f87..e2e1e56812 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -3093,6 +3093,14 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi } END_PHYS_EXT_CHECK(); + BEGIN_PHYS_EXT_CHECK( + VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR); + { + CHECK_PHYS_EXT_FEATURE(dynamicRenderingLocalRead); + } + END_PHYS_EXT_CHECK(); + BEGIN_PHYS_EXT_CHECK(VkPhysicalDevice4444FormatsFeaturesEXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT); { diff --git a/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp index 10c59da139..c91d2d1b6a 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp @@ -3566,6 +3566,138 @@ void WrappedVulkan::vkCmdSetRayTracingPipelineStackSizeKHR(VkCommandBuffer comma } } +template +bool WrappedVulkan::Serialise_vkCmdSetRenderingAttachmentLocationsKHR( + SerialiserType &ser, VkCommandBuffer commandBuffer, + const VkRenderingAttachmentLocationInfoKHR *pLocationInfo) +{ + SERIALISE_ELEMENT(commandBuffer); + SERIALISE_ELEMENT_LOCAL(locationInfo, *pLocationInfo).Named("pLocationInfo"_lit).Important(); + + Serialise_DebugMessages(ser); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer)); + + if(IsActiveReplaying(m_State)) + { + if(InRerecordRange(m_LastCmdBufferID)) + { + commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); + + { + VulkanRenderState &renderstate = GetCmdRenderState(); + + renderstate.dynamicRendering.localRead.UpdateLocations(locationInfo); + } + } + else + { + commandBuffer = VK_NULL_HANDLE; + } + } + + if(commandBuffer != VK_NULL_HANDLE) + ObjDisp(commandBuffer)->CmdSetRenderingAttachmentLocationsKHR(Unwrap(commandBuffer), &locationInfo); + } + + return true; +} + +void WrappedVulkan::vkCmdSetRenderingAttachmentLocationsKHR( + VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfoKHR *pLocationInfo) +{ + SCOPED_DBG_SINK(); + + SERIALISE_TIME_CALL( + ObjDisp(commandBuffer) + ->CmdSetRenderingAttachmentLocationsKHR(Unwrap(commandBuffer), pLocationInfo)); + + if(IsCaptureMode(m_State)) + { + VkResourceRecord *record = GetRecord(commandBuffer); + + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetRenderingAttachmentLocationsKHR); + Serialise_vkCmdSetRenderingAttachmentLocationsKHR(ser, commandBuffer, pLocationInfo); + + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); + } +} + +template +bool WrappedVulkan::Serialise_vkCmdSetRenderingInputAttachmentIndicesKHR( + SerialiserType &ser, VkCommandBuffer commandBuffer, + const VkRenderingInputAttachmentIndexInfoKHR *pInputAttachmentIndexInfo) +{ + SERIALISE_ELEMENT(commandBuffer); + SERIALISE_ELEMENT_LOCAL(inputAttachmentIndexInfo, *pInputAttachmentIndexInfo) + .Named("pInputAttachmentIndexInfo"_lit) + .Important(); + + Serialise_DebugMessages(ser); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer)); + + if(IsActiveReplaying(m_State)) + { + if(InRerecordRange(m_LastCmdBufferID)) + { + commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); + + { + VulkanRenderState &renderstate = GetCmdRenderState(); + + renderstate.dynamicRendering.localRead.UpdateInputIndices(inputAttachmentIndexInfo); + } + } + else + { + commandBuffer = VK_NULL_HANDLE; + } + } + + if(commandBuffer != VK_NULL_HANDLE) + ObjDisp(commandBuffer) + ->CmdSetRenderingInputAttachmentIndicesKHR(Unwrap(commandBuffer), + &inputAttachmentIndexInfo); + } + + return true; +} + +void WrappedVulkan::vkCmdSetRenderingInputAttachmentIndicesKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInputAttachmentIndexInfoKHR *pInputAttachmentIndexInfo) +{ + SCOPED_DBG_SINK(); + + SERIALISE_TIME_CALL(ObjDisp(commandBuffer) + ->CmdSetRenderingInputAttachmentIndicesKHR(Unwrap(commandBuffer), + pInputAttachmentIndexInfo)); + + if(IsCaptureMode(m_State)) + { + VkResourceRecord *record = GetRecord(commandBuffer); + + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetRenderingInputAttachmentIndicesKHR); + Serialise_vkCmdSetRenderingInputAttachmentIndicesKHR(ser, commandBuffer, + pInputAttachmentIndexInfo); + + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); + } +} + INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetViewport, VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports); @@ -3707,3 +3839,10 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetTessellationDomainOriginEXT, VkTessellationDomainOrigin domainOrigin); INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetRayTracingPipelineStackSizeKHR, VkCommandBuffer commandBuffer, uint32_t pipelineStackSize) + +INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetRenderingAttachmentLocationsKHR, + VkCommandBuffer commandBuffer, + const VkRenderingAttachmentLocationInfoKHR *pLocationInfo); +INSTANTIATE_FUNCTION_SERIALISED( + void, vkCmdSetRenderingInputAttachmentIndicesKHR, VkCommandBuffer commandBuffer, + const VkRenderingInputAttachmentIndexInfoKHR *pInputAttachmentIndexInfo); diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index ac4a279a20..03a9b9cd0e 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -2182,8 +2182,14 @@ void DoSerialise(SerialiserType &ser, VKPipe::RenderPass &el) SERIALISE_MEMBER(multiviews); SERIALISE_MEMBER(fragmentDensityOffsets); SERIALISE_MEMBER(tileOnlyMSAASampleCount); + SERIALISE_MEMBER(colorAttachmentLocations); + SERIALISE_MEMBER(colorAttachmentInputIndices); + SERIALISE_MEMBER(isDepthInputAttachmentIndexImplicit); + SERIALISE_MEMBER(isStencilInputAttachmentIndexImplicit); + SERIALISE_MEMBER(depthInputAttachmentIndex); + SERIALISE_MEMBER(stencilInputAttachmentIndex); - SIZE_CHECK(168); + SIZE_CHECK(232); } template @@ -2219,7 +2225,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::CurrentPass &el) SERIALISE_MEMBER(depthFeedbackAllowed); SERIALISE_MEMBER(stencilFeedbackAllowed); - SIZE_CHECK(240); + SIZE_CHECK(304); } template @@ -2289,7 +2295,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::State &el) SERIALISE_MEMBER(conditionalRendering); - SIZE_CHECK(1808); + SIZE_CHECK(1872); } #pragma endregion Vulkan pipeline state