diff --git a/renderdoc/driver/vulkan/extension_support.md b/renderdoc/driver/vulkan/extension_support.md index d1c153821..6cdba8dd6 100644 --- a/renderdoc/driver/vulkan/extension_support.md +++ b/renderdoc/driver/vulkan/extension_support.md @@ -57,6 +57,7 @@ Maintainers can update this file by updating vk.xml in this folder and running ` * `VK_EXT_filter_cubic` * `VK_EXT_fragment_density_map` * `VK_EXT_fragment_density_map2` +* `VK_EXT_fragment_density_offset` * `VK_EXT_fragment_shader_interlock` * `VK_EXT_full_screen_exclusive` * `VK_EXT_global_priority_query` @@ -298,7 +299,6 @@ The portability subset is only relevant on mac, which is not a supported platfor * `VK_EXT_external_memory_acquire_unmodified` * `VK_EXT_external_memory_host` * `VK_EXT_external_memory_metal` -* `VK_EXT_fragment_density_map_offset` * `VK_EXT_image_drm_format_modifier` * `VK_EXT_image_sliced_view_of_3d` * `VK_EXT_layer_settings` diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 606af0f68..3e35ddff1 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -1401,6 +1401,7 @@ enum class VulkanChunk : uint32_t vkCmdSetDescriptorBufferOffsets2EXT, vkCmdPushDescriptorSet2, vkCmdPushDescriptorSetWithTemplate2, + vkCmdEndRendering2EXT, Max, }; @@ -1909,6 +1910,7 @@ DECLARE_REFLECTION_STRUCT(VkRenderingAttachmentLocationInfo); DECLARE_REFLECTION_STRUCT(VkRenderingFragmentDensityMapAttachmentInfoEXT); DECLARE_REFLECTION_STRUCT(VkRenderingFragmentShadingRateAttachmentInfoKHR); DECLARE_REFLECTION_STRUCT(VkRenderingInfo); +DECLARE_REFLECTION_STRUCT(VkRenderingEndInfoEXT); DECLARE_REFLECTION_STRUCT(VkRenderingInputAttachmentIndexInfo); DECLARE_REFLECTION_STRUCT(VkRenderPassAttachmentBeginInfo); DECLARE_REFLECTION_STRUCT(VkRenderPassBeginInfo); @@ -2431,6 +2433,7 @@ DECLARE_DESERIALISE_TYPE(VkRenderingAttachmentLocationInfo); DECLARE_DESERIALISE_TYPE(VkRenderingFragmentDensityMapAttachmentInfoEXT); DECLARE_DESERIALISE_TYPE(VkRenderingFragmentShadingRateAttachmentInfoKHR); DECLARE_DESERIALISE_TYPE(VkRenderingInfo); +DECLARE_DESERIALISE_TYPE(VkRenderingEndInfoEXT); DECLARE_DESERIALISE_TYPE(VkRenderingInputAttachmentIndexInfo); 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 ba7b8fef4..7a82d18a3 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1177,6 +1177,10 @@ static const VkExtensionProperties supportedExtensions[] = { VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME, VK_EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION, }, + { + VK_EXT_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME, + VK_EXT_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION, + }, { VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME, VK_EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION, @@ -4649,6 +4653,8 @@ 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::vkCmdEndRendering2EXT: + return Serialise_vkCmdEndRendering2EXT(ser, VK_NULL_HANDLE, NULL); case VulkanChunk::vkCmdSetRenderingAttachmentLocations: return Serialise_vkCmdSetRenderingAttachmentLocations(ser, VK_NULL_HANDLE, NULL); case VulkanChunk::vkCmdSetRenderingInputAttachmentIndices: diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 5938f12e7..5edb287e3 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -2971,6 +2971,8 @@ public: const VkRenderingInfo *pRenderingInfo); IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdEndRendering, VkCommandBuffer commandBuffer); + IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdEndRendering2EXT, VkCommandBuffer commandBuffer, + const VkRenderingEndInfoEXT *pRenderingEndInfo); // VK_KHR_dynamic_rendering_local_read diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index 19d67c4d7..d0d3abf0d 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -557,7 +557,8 @@ DeclExt(EXT_image_compression_control_swapchain); \ DeclExt(EXT_descriptor_buffer); \ DeclExt(KHR_map_memory2); \ - DeclExt(KHR_present_wait2); + DeclExt(KHR_present_wait2); \ + DeclExt(EXT_fragment_density_map_offset); // for simplicity and since the check itself is platform agnostic, // these aren't protected in platform defines @@ -701,7 +702,8 @@ CheckExt(EXT_image_compression_control_swapchain, VKXX); \ CheckExt(EXT_descriptor_buffer, VKXX); \ CheckExt(KHR_map_memory2, VK14); \ - CheckExt(KHR_present_wait2, VKXX); + CheckExt(KHR_present_wait2, VKXX); \ + CheckExt(EXT_fragment_density_map_offset, VKXX); #define HookInitVulkanInstanceExts_PhysDev() \ HookInitExtension(KHR_surface, GetPhysicalDeviceSurfaceSupportKHR); \ @@ -978,6 +980,7 @@ HookInitExtension(EXT_vertex_input_dynamic_state || EXT_shader_object, CmdSetVertexInputEXT); \ HookInitPromotedExtension(KHR_dynamic_rendering, CmdBeginRendering, KHR); \ HookInitPromotedExtension(KHR_dynamic_rendering, CmdEndRendering, KHR); \ + HookInitExtension(EXT_fragment_density_map_offset, CmdEndRendering2EXT); \ HookInitPromotedExtension(KHR_dynamic_rendering_local_read, CmdSetRenderingAttachmentLocations, \ KHR); \ HookInitPromotedExtension(KHR_dynamic_rendering_local_read, \ @@ -1823,6 +1826,8 @@ HookDefine2(void, vkCmdBeginRendering, VkCommandBuffer, commandBuffer, const VkRenderingInfo *, \ pRenderingInfo); \ HookDefine1(void, vkCmdEndRendering, VkCommandBuffer, commandBuffer); \ + HookDefine2(void, vkCmdEndRendering2EXT, VkCommandBuffer, commandBuffer, \ + const VkRenderingEndInfoEXT *, pRenderingEndInfo); \ HookDefine2(void, vkCmdSetRenderingAttachmentLocations, VkCommandBuffer, commandBuffer, \ const VkRenderingAttachmentLocationInfo *, pLocationInfo); \ HookDefine2(void, vkCmdSetRenderingInputAttachmentIndices, VkCommandBuffer, commandBuffer, \ diff --git a/renderdoc/driver/vulkan/vk_next_chains.cpp b/renderdoc/driver/vulkan/vk_next_chains.cpp index 82b671424..1eb841166 100644 --- a/renderdoc/driver/vulkan/vk_next_chains.cpp +++ b/renderdoc/driver/vulkan/vk_next_chains.cpp @@ -694,6 +694,7 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, VkRayTracingPipelineInterfaceCreateInfoKHR); \ COPY_STRUCT(VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, \ VkRayTracingShaderGroupCreateInfoKHR); \ + COPY_STRUCT(VK_STRUCTURE_TYPE_RENDERING_END_INFO_EXT, VkRenderingEndInfoEXT); \ COPY_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, VkRenderPassCreateInfo); \ COPY_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, VkRenderPassCreateInfo2); \ COPY_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT, \ @@ -1343,7 +1344,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_TILE_SHADING_CREATE_INFO_QCOM: \ case VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM: \ - case VK_STRUCTURE_TYPE_RENDERING_END_INFO_EXT: \ case VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM: \ case VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM: \ case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM: \ diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index 956c7337f..f6a4cdab4 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -1656,6 +1656,7 @@ SERIALISE_VK_HANDLES(); VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT) \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_EXT, \ VkRenderPassFragmentDensityMapOffsetEndInfoEXT) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDERING_END_INFO_EXT, VkRenderingEndInfoEXT) \ \ /* Surface creation structs. These would pull in dependencies on OS-specific includes. */ \ /* So treat them as unsupported. */ \ @@ -1836,9 +1837,6 @@ SERIALISE_VK_HANDLES(); PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT) \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT) \ \ - /* VK_EXT_fragment_density_map_offset */ \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_RENDERING_END_INFO_EXT) \ - \ /* VK_EXT_headless_surface */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT) \ \ @@ -7302,6 +7300,19 @@ void Deserialise(const VkRenderPassFragmentDensityMapOffsetEndInfoEXT &el) delete[] el.pFragmentDensityOffsets; } +template +void DoSerialise(SerialiserType &ser, VkRenderingEndInfoEXT &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_RENDERING_END_INFO_EXT); + SerialiseNext(ser, el.sType, el.pNext); +} + +template <> +void Deserialise(const VkRenderingEndInfoEXT &el) +{ + DeserialiseNext(el.pNext); +} + template void DoSerialise(SerialiserType &ser, VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT &el) { @@ -14925,6 +14936,7 @@ INSTANTIATE_SERIALISE_TYPE(VkReleaseSwapchainImagesInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkRenderingAreaInfo); INSTANTIATE_SERIALISE_TYPE(VkRenderingAttachmentInfo); INSTANTIATE_SERIALISE_TYPE(VkRenderingAttachmentLocationInfo); +INSTANTIATE_SERIALISE_TYPE(VkRenderingEndInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkRenderingFragmentDensityMapAttachmentInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkRenderingFragmentShadingRateAttachmentInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkRenderingInfo); diff --git a/renderdoc/driver/vulkan/vk_stringise.cpp b/renderdoc/driver/vulkan/vk_stringise.cpp index 3ae933032..1883368f3 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 == 1233, "Chunks changed without updating names"); + RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1234, "Chunks changed without updating names"); BEGIN_ENUM_STRINGISE(VulkanChunk) { @@ -207,6 +207,7 @@ rdcstr DoStringise(const VulkanChunk &el) STRINGISE_ENUM_CLASS(vkCmdSetVertexInputEXT) STRINGISE_ENUM_CLASS(vkCmdBeginRendering) STRINGISE_ENUM_CLASS(vkCmdEndRendering) + STRINGISE_ENUM_CLASS(vkCmdEndRendering2EXT) STRINGISE_ENUM_CLASS(vkCmdSetFragmentShadingRateKHR) STRINGISE_ENUM_CLASS(vkSetDeviceMemoryPriorityEXT) STRINGISE_ENUM_CLASS(vkCmdSetAttachmentFeedbackLoopEnableEXT) diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index 646145566..a4020ff07 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -8270,6 +8270,290 @@ void WrappedVulkan::vkCmdEndRendering(VkCommandBuffer commandBuffer) } } +template +bool WrappedVulkan::Serialise_vkCmdEndRendering2EXT(SerialiserType &ser, + VkCommandBuffer commandBuffer, + const VkRenderingEndInfoEXT *pRenderingEndInfo) +{ + SERIALISE_ELEMENT(commandBuffer); + SERIALISE_ELEMENT_LOCAL(RenderingEndInfo, *pRenderingEndInfo).Named("pRenderingEndInfo"_lit).Important(); + + Serialise_DebugMessages(ser); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + byte *tempMem = GetTempMemory(GetNextPatchSize(pRenderingEndInfo)); + VkRenderingEndInfoEXT *unwrappedEndInfo = + UnwrapStructAndChain(m_State, tempMem, pRenderingEndInfo); + m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer)); + + if(IsActiveReplaying(m_State)) + { + VulkanRenderState &renderstate = GetCmdRenderState(); + + bool suspending = (renderstate.dynamicRendering.flags & VK_RENDERING_SUSPENDING_BIT) != 0; + + if(InRerecordRange(m_LastCmdBufferID)) + { + commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); + + if(ShouldUpdateRenderpassActive(m_LastCmdBufferID, true)) + { + m_BakedCmdBufferInfo[m_LastCmdBufferID].renderPassOpen = false; + + // if this rendering is just being suspended, the pass is still active + if(!suspending && IsCommandBufferPartial(m_LastCmdBufferID)) + { + GetCommandBufferPartialSubmission(m_LastCmdBufferID)->renderPassActive = false; + } + } + + ActionFlags drawFlags = ActionFlags::PassBoundary | ActionFlags::EndPass; + uint32_t eventId = HandlePreCallback(commandBuffer, drawFlags); + + ObjDisp(commandBuffer)->CmdEndRendering2EXT(Unwrap(commandBuffer), unwrappedEndInfo); + + if(eventId && m_ActionCallback->PostMisc(eventId, drawFlags, commandBuffer)) + { + // Do not call vkCmdEndRendering2EXT again. + m_ActionCallback->PostRemisc(eventId, drawFlags, commandBuffer); + } + + // only do discards when not suspending! + if(m_ReplayOptions.optimisation != ReplayOptimisationLevel::Fastest && !suspending) + { + rdcarray dynAtts = renderstate.dynamicRendering.color; + dynAtts.push_back(renderstate.dynamicRendering.depth); + + size_t depthIdx = dynAtts.size() - 1; + size_t stencilIdx = ~0U; + VkImageAspectFlags depthAspects = VK_IMAGE_ASPECT_DEPTH_BIT; + + // if we have different images attached, or different store ops, treat stencil separately + if(renderstate.dynamicRendering.stencil.imageView != VK_NULL_HANDLE && + (renderstate.dynamicRendering.depth.imageView != + renderstate.dynamicRendering.stencil.imageView || + renderstate.dynamicRendering.depth.storeOp != + renderstate.dynamicRendering.stencil.storeOp)) + { + dynAtts.push_back(renderstate.dynamicRendering.stencil); + stencilIdx = dynAtts.size() - 1; + } + // otherwise if the same image is bound and the storeOp is the same then include it + else if(renderstate.dynamicRendering.stencil.imageView != VK_NULL_HANDLE) + { + depthAspects |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + + for(size_t i = 0; i < dynAtts.size(); i++) + { + if(dynAtts[i].imageView == VK_NULL_HANDLE) + continue; + + const VulkanCreationInfo::ImageView &viewInfo = + m_CreationInfo.m_ImageView[GetResID(dynAtts[i].imageView)]; + VkImage image = GetResourceManager()->GetCurrentHandle(viewInfo.image); + + if(dynAtts[i].storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE) + { + VkImageSubresourceRange range = viewInfo.range; + + if(i == depthIdx) + range.aspectMask = depthAspects; + + if(i == stencilIdx) + range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + + GetDebugManager()->FillWithDiscardPattern(commandBuffer, DiscardType::RenderPassStore, + image, dynAtts[i].imageLayout, range, + renderstate.renderArea); + } + } + } + + if(suspending) + { + renderstate.dynamicRendering.suspended = true; + } + else + { + renderstate.dynamicRendering = VulkanRenderState::DynamicRendering(); + renderstate.SetFramebuffer(ResourceId(), rdcarray()); + } + } + else if(IsRenderpassOpen(m_LastCmdBufferID)) + { + commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); + ObjDisp(commandBuffer)->CmdEndRendering2EXT(Unwrap(commandBuffer), unwrappedEndInfo); + + m_BakedCmdBufferInfo[m_LastCmdBufferID].renderPassOpen = false; + + const VkRenderPassFragmentDensityMapOffsetEndInfoEXT *fragmentDensityOffsetStruct = + (const VkRenderPassFragmentDensityMapOffsetEndInfoEXT *)FindNextStruct( + unwrappedEndInfo, + VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_EXT); + + if(fragmentDensityOffsetStruct) + { + rdcarray &stateOffsets = GetCmdRenderState().fragmentDensityMapOffsets; + stateOffsets.resize(fragmentDensityOffsetStruct->fragmentDensityOffsetCount); + for(uint32_t i = 0; i < fragmentDensityOffsetStruct->fragmentDensityOffsetCount; i++) + { + stateOffsets[i] = fragmentDensityOffsetStruct->pFragmentDensityOffsets[i]; + } + } + + // only do discards when not suspending! + if(Vulkan_Hack_DisableRPNormalisation() && !suspending) + { + rdcarray dynAtts = renderstate.dynamicRendering.color; + dynAtts.push_back(renderstate.dynamicRendering.depth); + + size_t depthIdx = dynAtts.size() - 1; + size_t stencilIdx = ~0U; + VkImageAspectFlags depthAspects = VK_IMAGE_ASPECT_DEPTH_BIT; + + // if we have different images attached, or different store ops, treat stencil separately + if(renderstate.dynamicRendering.stencil.imageView != VK_NULL_HANDLE && + (renderstate.dynamicRendering.depth.imageView != + renderstate.dynamicRendering.stencil.imageView || + renderstate.dynamicRendering.depth.storeOp != + renderstate.dynamicRendering.stencil.storeOp)) + { + dynAtts.push_back(renderstate.dynamicRendering.stencil); + stencilIdx = dynAtts.size() - 1; + } + // otherwise if the same image is bound and the storeOp is the same then include it + else if(renderstate.dynamicRendering.stencil.imageView != VK_NULL_HANDLE) + { + depthAspects |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + + for(size_t i = 0; i < dynAtts.size(); i++) + { + if(dynAtts[i].imageView == VK_NULL_HANDLE) + continue; + + const VulkanCreationInfo::ImageView &viewInfo = + m_CreationInfo.m_ImageView[GetResID(dynAtts[i].imageView)]; + VkImage image = GetResourceManager()->GetCurrentHandle(viewInfo.image); + + if(dynAtts[i].storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE) + { + VkImageSubresourceRange range = viewInfo.range; + + if(i == depthIdx) + range.aspectMask = depthAspects; + + if(i == stencilIdx) + range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + + GetDebugManager()->FillWithDiscardPattern(commandBuffer, DiscardType::RenderPassStore, + image, VK_IMAGE_LAYOUT_UNDEFINED, range, + renderstate.renderArea); + } + } + } + } + } + else + { + ObjDisp(commandBuffer)->CmdEndRendering2EXT(Unwrap(commandBuffer), unwrappedEndInfo); + + // fetch any queued indirect readbacks here + for(const VkIndirectRecordData &indirectcopy : + m_BakedCmdBufferInfo[m_LastCmdBufferID].indirectCopies) + ExecuteIndirectReadback(commandBuffer, indirectcopy); + + m_BakedCmdBufferInfo[m_LastCmdBufferID].indirectCopies.clear(); + + VulkanRenderState &state = m_BakedCmdBufferInfo[m_LastCmdBufferID].state; + + uint32_t eid = m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID; + rdcarray> &usage = + m_BakedCmdBufferInfo[m_LastCmdBufferID].resourceUsage; + + VulkanRenderState::DynamicRendering &dyn = state.dynamicRendering; + + bool suspending = (dyn.flags & VK_RENDERING_SUSPENDING_BIT) != 0; + + rdcarray dynAtts = dyn.color; + dynAtts.push_back(dyn.depth); + + // if stencil attachment is different, or only one is resolving, add the stencil attachment. + // Otherwise depth will cover both (at most) + if((dyn.depth.imageView != dyn.stencil.imageView) || + (dyn.depth.resolveMode != 0) != (dyn.stencil.resolveMode != 0)) + dynAtts.push_back(dyn.stencil); + + for(size_t i = 0; i < dynAtts.size(); i++) + { + if(dynAtts[i].resolveMode && dynAtts[i].imageView != VK_NULL_HANDLE && + dynAtts[i].resolveImageView != VK_NULL_HANDLE) + { + usage.push_back(make_rdcpair(m_CreationInfo.m_ImageView[GetResID(dynAtts[i].imageView)].image, + EventUsage(eid, ResourceUsage::ResolveSrc))); + + usage.push_back( + make_rdcpair(m_CreationInfo.m_ImageView[GetResID(dynAtts[i].resolveImageView)].image, + EventUsage(eid, ResourceUsage::ResolveDst))); + } + + // also add any discards + if(dynAtts[i].storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE) + { + usage.push_back(make_rdcpair(m_CreationInfo.m_ImageView[GetResID(dynAtts[i].imageView)].image, + EventUsage(eid, ResourceUsage::Discard))); + } + } + + AddEvent(); + ActionDescription action; + action.customName = + StringFormat::Fmt("vkCmdEndRendering2EXT(%s)", MakeRenderPassOpString(true).c_str()); + action.flags |= ActionFlags::PassBoundary | ActionFlags::EndPass; + + AddAction(action); + + if(!suspending) + { + // track while reading, reset this to empty so AddAction sets no outputs, + // but only AFTER the above AddAction (we want it grouped together) + state.dynamicRendering = VulkanRenderState::DynamicRendering(); + state.SetFramebuffer(ResourceId(), rdcarray()); + } + } + } + + return true; +} + +void WrappedVulkan::vkCmdEndRendering2EXT(VkCommandBuffer commandBuffer, + const VkRenderingEndInfoEXT *pRenderingEndInfo) +{ + SCOPED_DBG_SINK(); + + byte *tempMem = GetTempMemory(GetNextPatchSize(pRenderingEndInfo)); + VkRenderingEndInfoEXT *unwrappedEndInfo = UnwrapStructAndChain(m_State, tempMem, pRenderingEndInfo); + + SERIALISE_TIME_CALL( + ObjDisp(commandBuffer)->CmdEndRendering2EXT(Unwrap(commandBuffer), unwrappedEndInfo)); + + if(IsCaptureMode(m_State)) + { + VkResourceRecord *record = GetRecord(commandBuffer); + + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndRendering2EXT); + Serialise_vkCmdEndRendering2EXT(ser, commandBuffer, pRenderingEndInfo); + + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); + } +} + VkResult WrappedVulkan::vkBuildAccelerationStructuresKHR( VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos, @@ -10155,6 +10439,8 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdBeginRendering, VkCommandBuffer comma const VkRenderingInfo *pRenderingInfo); INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdEndRendering, VkCommandBuffer commandBuffer); +INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdEndRendering2EXT, VkCommandBuffer commandBuffer, + const VkRenderingEndInfoEXT *pRenderingEndInfo); INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdBuildAccelerationStructuresIndirectKHR, VkCommandBuffer commandBuffer, uint32_t infoCount,