diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index 259a3a665..d0b281cba 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -2406,7 +2406,7 @@ void VulkanPipelineStateViewer::setState() ui->scissors->beginUpdate(); ui->scissors->clear(); - if(state.currentPass.renderpass.resourceId != ResourceId()) + if(state.currentPass.renderpass.resourceId != ResourceId() || state.currentPass.renderpass.dynamic) { ui->scissors->addTopLevelItem(new RDTreeWidgetItem( {tr("Render Area"), state.currentPass.renderArea.x, state.currentPass.renderArea.y, @@ -2542,11 +2542,23 @@ void VulkanPipelineStateViewer::setState() bool targets[32] = {}; - ui->renderpass->setText(QFormatStr("Render Pass: %1 (Subpass %2)") - .arg(ToQStr(state.currentPass.renderpass.resourceId)) - .arg(state.currentPass.renderpass.subpass)); - ui->framebuffer->setText( - QFormatStr("Framebuffer: %1").arg(ToQStr(state.currentPass.framebuffer.resourceId))); + if(state.currentPass.renderpass.dynamic) + { + QString dynamic = tr("Dynamic", "Dynamic rendering renderpass name"); + QString text = QFormatStr("Render Pass: %1").arg(dynamic); + if(state.currentPass.renderpass.suspended) + text += tr(" (Suspended)", "Dynamic rendering renderpass name"); + ui->renderpass->setText(text); + ui->framebuffer->setText(tr("Framebuffer: %1").arg(dynamic)); + } + else + { + ui->renderpass->setText(QFormatStr("Render Pass: %1 (Subpass %2)") + .arg(ToQStr(state.currentPass.renderpass.resourceId)) + .arg(state.currentPass.renderpass.subpass)); + ui->framebuffer->setText( + QFormatStr("Framebuffer: %1").arg(ToQStr(state.currentPass.framebuffer.resourceId))); + } vs = ui->fbAttach->verticalScrollBar()->value(); ui->fbAttach->beginUpdate(); @@ -2621,9 +2633,9 @@ void VulkanPipelineStateViewer::setState() QString slotname; if(colIdx >= 0) - slotname = QFormatStr("Color %1").arg(i); + slotname = QFormatStr("Color %1").arg(colIdx); else if(resIdx >= 0) - slotname = QFormatStr("Resolve %1").arg(i); + slotname = QFormatStr("Resolve %1").arg(resIdx); else if(state.currentPass.renderpass.fragmentDensityAttachment == i) slotname = lit("Fragment Density Map"); else diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index 18c538474..2fdcce67f 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -945,6 +945,12 @@ struct RenderPass DOCUMENT("The :class:`ResourceId` of the render pass."); ResourceId resourceId; + DOCUMENT("Whether or not dynamic rendering is in use (no render pass or framebuffer objects)."); + bool dynamic = false; + + DOCUMENT("Whether or not dynamic rendering is currently suspended."); + bool suspended = false; + DOCUMENT("The index of the current active subpass."); uint32_t subpass; diff --git a/renderdoc/driver/vulkan/extension_support.md b/renderdoc/driver/vulkan/extension_support.md index b030945ef..02a0b19b9 100644 --- a/renderdoc/driver/vulkan/extension_support.md +++ b/renderdoc/driver/vulkan/extension_support.md @@ -117,6 +117,7 @@ Maintainers can update this file by updating vk.xml in this folder and running ` * `VK_KHR_display` * `VK_KHR_draw_indirect_count` * `VK_KHR_driver_properties` +* `VK_KHR_dynamic_rendering` * `VK_KHR_external_fence_capabilities` * `VK_KHR_external_fence_fd` * `VK_KHR_external_fence_win32` diff --git a/renderdoc/driver/vulkan/official/vulkan_core.h b/renderdoc/driver/vulkan/official/vulkan_core.h index 056deb6ed..a2f4e7717 100644 --- a/renderdoc/driver/vulkan/official/vulkan_core.h +++ b/renderdoc/driver/vulkan/official/vulkan_core.h @@ -72,7 +72,7 @@ extern "C" { #define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 196 +#define VK_HEADER_VERSION 197 // Complete version of this file #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 2, VK_HEADER_VERSION) @@ -514,6 +514,15 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT = 1000040007, #endif VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + VK_STRUCTURE_TYPE_RENDERING_INFO_KHR = 1000044000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR = 1000044001, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR = 1000044002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = 1000044003, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = 1000044004, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, @@ -900,6 +909,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD, VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, @@ -1768,8 +1778,9 @@ typedef enum VkAttachmentLoadOp { typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_STORE = 0, VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, - VK_ATTACHMENT_STORE_OP_NONE_EXT = 1000301000, - VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE_EXT, + VK_ATTACHMENT_STORE_OP_NONE_KHR = 1000301000, + VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE_KHR, + VK_ATTACHMENT_STORE_OP_NONE_EXT = VK_ATTACHMENT_STORE_OP_NONE_KHR, VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentStoreOp; @@ -2203,6 +2214,8 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, @@ -6486,6 +6499,116 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" +#define VK_KHR_dynamic_rendering 1 +#define VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION 1 +#define VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME "VK_KHR_dynamic_rendering" + +typedef enum VkRenderingFlagBitsKHR { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = 0x00000001, + VK_RENDERING_SUSPENDING_BIT_KHR = 0x00000002, + VK_RENDERING_RESUMING_BIT_KHR = 0x00000004, + VK_RENDERING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRenderingFlagBitsKHR; +typedef VkFlags VkRenderingFlagsKHR; +typedef struct VkRenderingAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkResolveModeFlagBits resolveMode; + VkImageView resolveImageView; + VkImageLayout resolveImageLayout; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkClearValue clearValue; +} VkRenderingAttachmentInfoKHR; + +typedef struct VkRenderingInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingFlagsKHR flags; + VkRect2D renderArea; + uint32_t layerCount; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkRenderingAttachmentInfoKHR* pColorAttachments; + const VkRenderingAttachmentInfoKHR* pDepthAttachment; + const VkRenderingAttachmentInfoKHR* pStencilAttachment; +} VkRenderingInfoKHR; + +typedef struct VkPipelineRenderingCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkPipelineRenderingCreateInfoKHR; + +typedef struct VkPhysicalDeviceDynamicRenderingFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRendering; +} VkPhysicalDeviceDynamicRenderingFeaturesKHR; + +typedef struct VkCommandBufferInheritanceRenderingInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingFlagsKHR flags; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; + VkSampleCountFlagBits rasterizationSamples; +} VkCommandBufferInheritanceRenderingInfoKHR; + +typedef struct VkRenderingFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkExtent2D shadingRateAttachmentTexelSize; +} VkRenderingFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkRenderingFragmentDensityMapAttachmentInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; +} VkRenderingFragmentDensityMapAttachmentInfoEXT; + +typedef struct VkAttachmentSampleCountInfoAMD { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const VkSampleCountFlagBits* pColorAttachmentSamples; + VkSampleCountFlagBits depthStencilAttachmentSamples; +} VkAttachmentSampleCountInfoAMD; + +typedef VkAttachmentSampleCountInfoAMD VkAttachmentSampleCountInfoNV; + +typedef struct VkMultiviewPerViewAttributesInfoNVX { + VkStructureType sType; + const void* pNext; + VkBool32 perViewAttributes; + VkBool32 perViewAttributesPositionXOnly; +} VkMultiviewPerViewAttributesInfoNVX; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderingKHR)(VkCommandBuffer commandBuffer, const VkRenderingInfoKHR* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderingKHR)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderingKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInfoKHR* pRenderingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( + VkCommandBuffer commandBuffer); +#endif + + #define VK_KHR_multiview 1 #define VK_KHR_MULTIVIEW_SPEC_VERSION 1 #define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" diff --git a/renderdoc/driver/vulkan/vk.xml b/renderdoc/driver/vulkan/vk.xml index a785f5c4e..af8373af9 100644 --- a/renderdoc/driver/vulkan/vk.xml +++ b/renderdoc/driver/vulkan/vk.xml @@ -155,7 +155,7 @@ branch of the member gitlab server. // Vulkan 1.2 version number #define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 196 +#define VK_HEADER_VERSION 197 // Complete version of this file #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 2, VK_HEADER_VERSION) @@ -311,6 +311,7 @@ typedef void CAMetalLayer; typedef VkFlags VkAccelerationStructureMotionInfoFlagsNV; typedef VkFlags VkAccelerationStructureMotionInstanceFlagsNV; typedef VkFlags64 VkFormatFeatureFlags2KHR; + typedef VkFlags VkRenderingFlagsKHR; WSI extensions typedef VkFlags VkCompositeAlphaFlagsKHR; @@ -419,7 +420,7 @@ typedef void CAMetalLayer; typedef VkFlags VkVideoEncodeH264CreateFlagsEXT; Video Encode H.265 extension - typedef VkFlags VkVideoEncodeH265CapabilityFlagsEXT; + typedef VkFlags VkVideoEncodeH265CapabilityFlagsEXT; typedef VkFlags VkVideoEncodeH265InputModeFlagsEXT; typedef VkFlags VkVideoEncodeH265OutputModeFlagsEXT; typedef VkFlags VkVideoEncodeH265CreateFlagsEXT; @@ -636,6 +637,7 @@ typedef void CAMetalLayer; + WSI extensions @@ -737,7 +739,6 @@ typedef void CAMetalLayer; Video H.265 Encode extensions - @@ -1387,7 +1388,7 @@ typedef void CAMetalLayer; const VkPipelineColorBlendStateCreateInfo* pColorBlendState const VkPipelineDynamicStateCreateInfo* pDynamicState VkPipelineLayout layoutInterface layout of the pipeline - VkRenderPass renderPass + VkRenderPass renderPass uint32_t subpass VkPipeline basePipelineHandleIf VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of int32_t basePipelineIndexIf VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of @@ -1752,7 +1753,7 @@ typedef void CAMetalLayer; VkStructureType sType const void* pNext VkFramebufferCreateFlags flags - VkRenderPass renderPass + VkRenderPass renderPass uint32_t attachmentCount const VkImageView* pAttachments uint32_t width @@ -2675,7 +2676,7 @@ typedef void CAMetalLayer; const VkRect2D* pSplitInstanceBindRegions - + VkStructureType sType const void* pNext uint32_t deviceMask @@ -5675,7 +5676,7 @@ typedef void CAMetalLayer; VkDeviceSize srcBufferRange VkVideoPictureResourceKHR dstPictureResource const VkVideoReferenceSlotKHR* pSetupReferenceSlot - uint32_t referenceSlotCount + uint32_t referenceSlotCount const VkVideoReferenceSlotKHR* pReferenceSlots Video Decode Codec Standard specific structures @@ -5690,7 +5691,7 @@ typedef void CAMetalLayer; - + @@ -5706,7 +5707,7 @@ typedef void CAMetalLayer; - + VkStructureTypesType const void* pNext StdVideoH264ProfileIdc stdProfileIdc @@ -5783,7 +5784,7 @@ typedef void CAMetalLayer; - + VkStructureTypesType const void* pNext StdVideoH265ProfileIdc stdProfileIdc @@ -5857,7 +5858,7 @@ typedef void CAMetalLayer; VkVideoCodingQualityPresetFlagsKHR codecQualityPreset VkVideoSessionKHR videoSession VkVideoSessionParametersKHR videoSessionParameters - uint32_t referenceSlotCount + uint32_t referenceSlotCount const VkVideoReferenceSlotKHR* pReferenceSlots @@ -5881,7 +5882,7 @@ typedef void CAMetalLayer; VkDeviceSize dstBitstreamBufferMaxRange VkVideoPictureResourceKHR srcPictureResource const VkVideoReferenceSlotKHR* pSetupReferenceSlot - uint32_t referenceSlotCount + uint32_t referenceSlotCount const VkVideoReferenceSlotKHR* pReferenceSlots @@ -5966,7 +5967,7 @@ typedef void CAMetalLayer; uint32_t ppsIdEntryCount const uint8_t* ppsIdEntries - + VkStructureTypesType const void* pNext StdVideoH264ProfileIdc stdProfileIdc @@ -6058,7 +6059,7 @@ typedef void CAMetalLayer; const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists const StdVideoEncodeH265SliceHeader* pSliceHeaderStd - + VkStructureTypesType const void* pNext StdVideoH265ProfileIdc stdProfileIdc @@ -6374,6 +6375,82 @@ typedef void CAMetalLayer; VkChromaLocation suggestedXChromaOffset VkChromaLocation suggestedYChromaOffset + + VkStructureType sType + const void* pNext + uint32_t viewMask + uint32_t colorAttachmentCount + const VkFormat* pColorAttachmentFormats + VkFormat depthAttachmentFormat + VkFormat stencilAttachmentFormat + + + VkStructureType sType + const void* pNext + VkRenderingFlagsKHR flags + VkRect2D renderArea + uint32_t layerCount + uint32_t viewMask + uint32_t colorAttachmentCount + const VkRenderingAttachmentInfoKHR* pColorAttachments + const VkRenderingAttachmentInfoKHR* pDepthAttachment + const VkRenderingAttachmentInfoKHR* pStencilAttachment + + + VkStructureType sType + const void* pNext + VkImageView imageView + VkImageLayout imageLayout + VkResolveModeFlagBits resolveMode + VkImageView resolveImageView + VkImageLayout resolveImageLayout + VkAttachmentLoadOp loadOp + VkAttachmentStoreOp storeOp + VkClearValue clearValue + + + VkStructureType sType + const void* pNext + VkImageView imageView + VkImageLayout imageLayout + VkExtent2D shadingRateAttachmentTexelSize + + + VkStructureType sType + const void* pNext + VkImageView imageView + VkImageLayout imageLayout + + + VkStructureType sType + void* pNext + VkBool32 dynamicRendering + + + VkStructureType sType + const void* pNext + VkRenderingFlagsKHR flags + uint32_t viewMask + uint32_t colorAttachmentCount + const VkFormat* pColorAttachmentFormats + VkFormat depthAttachmentFormat + VkFormat stencilAttachmentFormat + VkSampleCountFlagBits rasterizationSamples + + + VkStructureType sType + const void* pNext + uint32_t colorAttachmentCount + const VkSampleCountFlagBits* pColorAttachmentSamples + VkSampleCountFlagBits depthStencilAttachmentSamples + + + + VkStructureType sType + const void* pNext + VkBool32 perViewAttributes + VkBool32 perViewAttributesPositionXOnly + Vulkan enumerant (token) definitions @@ -7992,17 +8069,6 @@ typedef void CAMetalLayer; - - - - - - - - - - - @@ -8019,6 +8085,11 @@ typedef void CAMetalLayer; + + + + + @@ -11129,6 +11200,15 @@ typedef void CAMetalLayer; VkBufferCollectionFUCHSIA collection VkBufferCollectionPropertiesFUCHSIA* pProperties + + void vkCmdBeginRenderingKHR + VkCommandBuffer commandBuffer + const VkRenderingInfoKHR* pRenderingInfo + + + void vkCmdEndRenderingKHR + VkCommandBuffer commandBuffer + @@ -12766,7 +12846,6 @@ typedef void CAMetalLayer; - @@ -12838,12 +12917,47 @@ typedef void CAMetalLayer; - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -16201,7 +16315,7 @@ typedef void CAMetalLayer; - + @@ -16294,6 +16408,7 @@ typedef void CAMetalLayer; + @@ -17120,7 +17235,7 @@ typedef void CAMetalLayer; - + @@ -17317,6 +17432,24 @@ typedef void CAMetalLayer; + + + + + + + + + + + + + + + + + + diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 319c8bec4..971164849 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -722,6 +722,8 @@ enum class VulkanChunk : uint32_t vkCmdSetPrimitiveRestartEnableEXT, vkCmdSetRasterizerDiscardEnableEXT, vkCmdSetVertexInputEXT, + vkCmdBeginRenderingKHR, + vkCmdEndRenderingKHR, Max, }; @@ -799,6 +801,7 @@ DECLARE_REFLECTION_STRUCT(VkCalibratedTimestampInfoEXT); DECLARE_REFLECTION_STRUCT(VkCommandBufferAllocateInfo); DECLARE_REFLECTION_STRUCT(VkCommandBufferBeginInfo); DECLARE_REFLECTION_STRUCT(VkCommandBufferInheritanceConditionalRenderingInfoEXT); +DECLARE_REFLECTION_STRUCT(VkCommandBufferInheritanceRenderingInfoKHR); DECLARE_REFLECTION_STRUCT(VkCommandBufferInheritanceInfo); DECLARE_REFLECTION_STRUCT(VkCommandBufferSubmitInfoKHR); DECLARE_REFLECTION_STRUCT(VkCommandPoolCreateInfo); @@ -936,6 +939,7 @@ DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDescriptorIndexingFeatures) DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDescriptorIndexingProperties) DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDiscardRectanglePropertiesEXT); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDriverProperties); +DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceDynamicRenderingFeaturesKHR); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceExtendedDynamicStateFeaturesEXT); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceExternalBufferInfo); @@ -1054,6 +1058,7 @@ DECLARE_REFLECTION_STRUCT(VkPipelineRasterizationDepthClipStateCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkPipelineRasterizationLineStateCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkPipelineRasterizationStateCreateInfo); DECLARE_REFLECTION_STRUCT(VkPipelineRasterizationStateStreamCreateInfoEXT); +DECLARE_REFLECTION_STRUCT(VkPipelineRenderingCreateInfoKHR); DECLARE_REFLECTION_STRUCT(VkPipelineSampleLocationsStateCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkPipelineShaderStageCreateInfo); DECLARE_REFLECTION_STRUCT(VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT); @@ -1074,6 +1079,9 @@ DECLARE_REFLECTION_STRUCT(VkQueryPoolPerformanceCreateInfoKHR); DECLARE_REFLECTION_STRUCT(VkQueueFamilyGlobalPriorityPropertiesEXT); DECLARE_REFLECTION_STRUCT(VkQueueFamilyProperties2); DECLARE_REFLECTION_STRUCT(VkRefreshCycleDurationGOOGLE); +DECLARE_REFLECTION_STRUCT(VkRenderingAttachmentInfoKHR); +DECLARE_REFLECTION_STRUCT(VkRenderingFragmentDensityMapAttachmentInfoEXT); +DECLARE_REFLECTION_STRUCT(VkRenderingInfoKHR); DECLARE_REFLECTION_STRUCT(VkRenderPassAttachmentBeginInfo); DECLARE_REFLECTION_STRUCT(VkRenderPassBeginInfo); DECLARE_REFLECTION_STRUCT(VkRenderPassCreateInfo); @@ -1154,6 +1162,7 @@ DECLARE_DESERIALISE_TYPE(VkCalibratedTimestampInfoEXT); DECLARE_DESERIALISE_TYPE(VkCommandBufferAllocateInfo); DECLARE_DESERIALISE_TYPE(VkCommandBufferBeginInfo); DECLARE_DESERIALISE_TYPE(VkCommandBufferInheritanceConditionalRenderingInfoEXT); +DECLARE_DESERIALISE_TYPE(VkCommandBufferInheritanceRenderingInfoKHR); DECLARE_DESERIALISE_TYPE(VkCommandBufferInheritanceInfo); DECLARE_DESERIALISE_TYPE(VkCommandBufferSubmitInfoKHR); DECLARE_DESERIALISE_TYPE(VkCommandPoolCreateInfo); @@ -1287,6 +1296,7 @@ DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDescriptorIndexingFeatures) DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDescriptorIndexingProperties) DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDiscardRectanglePropertiesEXT); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDriverProperties); +DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceDynamicRenderingFeaturesKHR); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicStateFeaturesEXT); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceExternalBufferInfo); @@ -1405,6 +1415,7 @@ DECLARE_DESERIALISE_TYPE(VkPipelineRasterizationDepthClipStateCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkPipelineRasterizationLineStateCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkPipelineRasterizationStateCreateInfo); DECLARE_DESERIALISE_TYPE(VkPipelineRasterizationStateStreamCreateInfoEXT); +DECLARE_DESERIALISE_TYPE(VkPipelineRenderingCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkPipelineSampleLocationsStateCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkPipelineShaderStageCreateInfo); DECLARE_DESERIALISE_TYPE(VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT); @@ -1423,6 +1434,9 @@ DECLARE_DESERIALISE_TYPE(VkQueryPoolCreateInfo); DECLARE_DESERIALISE_TYPE(VkQueryPoolPerformanceCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkQueueFamilyGlobalPriorityPropertiesEXT); DECLARE_DESERIALISE_TYPE(VkQueueFamilyProperties2); +DECLARE_DESERIALISE_TYPE(VkRenderingAttachmentInfoKHR); +DECLARE_DESERIALISE_TYPE(VkRenderingFragmentShadingRateAttachmentInfoKHR); +DECLARE_DESERIALISE_TYPE(VkRenderingInfoKHR); DECLARE_DESERIALISE_TYPE(VkRenderPassAttachmentBeginInfo); DECLARE_DESERIALISE_TYPE(VkRenderPassBeginInfo); DECLARE_DESERIALISE_TYPE(VkRenderPassCreateInfo); @@ -1738,6 +1752,7 @@ DECLARE_REFLECTION_ENUM(VkPolygonMode); DECLARE_REFLECTION_ENUM(VkPresentModeKHR); DECLARE_REFLECTION_ENUM(VkPrimitiveTopology); DECLARE_REFLECTION_ENUM(VkPrivateDataSlotCreateFlagBitsEXT); +DECLARE_REFLECTION_ENUM(VkRenderingFlagBitsKHR); DECLARE_REFLECTION_ENUM(VkQueryControlFlagBits); DECLARE_REFLECTION_ENUM(VkQueryPipelineStatisticFlagBits); DECLARE_REFLECTION_ENUM(VkQueryResultFlagBits); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 9dfdbcee7..31b77a02e 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1172,6 +1172,9 @@ static const VkExtensionProperties supportedExtensions[] = { { VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION, }, + { + VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION, + }, { VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_SPEC_VERSION, }, @@ -3507,6 +3510,11 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk) case VulkanChunk::vkCmdSetVertexInputEXT: return Serialise_vkCmdSetVertexInputEXT(ser, VK_NULL_HANDLE, 0, NULL, 0, NULL); + case VulkanChunk::vkCmdBeginRenderingKHR: + return Serialise_vkCmdBeginRenderingKHR(ser, VK_NULL_HANDLE, NULL); + case VulkanChunk::vkCmdEndRenderingKHR: + return Serialise_vkCmdEndRenderingKHR(ser, VK_NULL_HANDLE); + // chunks that are reserved but not yet serialised case VulkanChunk::vkResetCommandPool: case VulkanChunk::vkCreateDepthTargetView: @@ -3733,7 +3741,8 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay // if a render pass was active, begin it and set up the partial replay state m_RenderState.BeginRenderPassAndApplyState( - this, cmd, rpUnneeded ? VulkanRenderState::BindNone : VulkanRenderState::BindGraphics); + this, cmd, rpUnneeded ? VulkanRenderState::BindNone : VulkanRenderState::BindGraphics, + false); } else { @@ -4255,14 +4264,15 @@ void WrappedVulkan::AddAction(const ActionDescription &a) if(m_LastCmdBufferID != ResourceId()) { - ResourceId fb = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.GetFramebuffer(); - ResourceId rp = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass; - uint32_t sp = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass; + const VulkanRenderState &state = m_BakedCmdBufferInfo[m_LastCmdBufferID].state; + + ResourceId fb = state.GetFramebuffer(); + ResourceId rp = state.GetRenderPass(); + uint32_t sp = state.subpass; if(fb != ResourceId() && rp != ResourceId()) { - const rdcarray &atts = - m_BakedCmdBufferInfo[m_LastCmdBufferID].state.GetFramebufferAttachments(); + const rdcarray &atts = state.GetFramebufferAttachments(); RDCASSERT(sp < m_CreationInfo.m_RenderPass[rp].subpasses.size()); @@ -4288,6 +4298,25 @@ void WrappedVulkan::AddAction(const ActionDescription &a) GetResourceManager()->GetOriginalID(m_CreationInfo.m_ImageView[atts[dsAtt]].image); } } + else if(state.dynamicRendering.active) + { + const VulkanRenderState::DynamicRendering &dyn = state.dynamicRendering; + + for(size_t i = 0; i < ARRAY_COUNT(action.outputs) && i < dyn.color.size(); i++) + { + if(dyn.color[i].imageView == VK_NULL_HANDLE) + continue; + + action.outputs[i] = GetResourceManager()->GetOriginalID( + m_CreationInfo.m_ImageView[GetResID(dyn.color[i].imageView)].image); + } + + if(dyn.depth.imageView != VK_NULL_HANDLE) + { + action.depthOut = GetResourceManager()->GetOriginalID( + m_CreationInfo.m_ImageView[GetResID(dyn.depth.imageView)].image); + } + } } // markers don't increment action ID @@ -4542,14 +4571,18 @@ void WrappedVulkan::AddUsage(VulkanActionTreeNode &actionNode, rdcarray &fbattachments) +void WrappedVulkan::AddFramebufferUsage(VulkanActionTreeNode &actionNode, + const VulkanRenderState &renderState) { + ResourceId renderPass = renderState.GetRenderPass(); + ResourceId framebuffer = renderState.GetFramebuffer(); + + uint32_t subpass = renderState.subpass; + const rdcarray &fbattachments = renderState.GetFramebufferAttachments(); + VulkanCreationInfo &c = m_CreationInfo; uint32_t e = actionNode.action.eventId; @@ -4595,17 +4628,43 @@ void WrappedVulkan::AddFramebufferUsage(VulkanActionTreeNode &actionNode, Resour } } } + else if(renderState.dynamicRendering.active) + { + const VulkanRenderState::DynamicRendering &dyn = renderState.dynamicRendering; + + for(size_t i = 0; i < dyn.color.size(); i++) + { + if(dyn.color[i].imageView == VK_NULL_HANDLE) + continue; + + actionNode.resourceUsage.push_back(make_rdcpair( + c.m_ImageView[GetResID(dyn.color[i].imageView)].image, + EventUsage(e, ResourceUsage::ColorTarget, GetResID(dyn.color[i].imageView)))); + } + + if(dyn.depth.imageView != VK_NULL_HANDLE) + { + actionNode.resourceUsage.push_back(make_rdcpair( + c.m_ImageView[GetResID(dyn.depth.imageView)].image, + EventUsage(e, ResourceUsage::DepthStencilTarget, GetResID(dyn.depth.imageView)))); + } + + if(dyn.stencil.imageView != VK_NULL_HANDLE && dyn.depth.imageView != dyn.stencil.imageView) + { + actionNode.resourceUsage.push_back(make_rdcpair( + c.m_ImageView[GetResID(dyn.stencil.imageView)].image, + EventUsage(e, ResourceUsage::DepthStencilTarget, GetResID(dyn.stencil.imageView)))); + } + } } void WrappedVulkan::AddFramebufferUsageAllChildren(VulkanActionTreeNode &actionNode, - ResourceId renderPass, ResourceId framebuffer, - uint32_t subpass, - const rdcarray &fbattachments) + const VulkanRenderState &renderState) { for(VulkanActionTreeNode &c : actionNode.children) - AddFramebufferUsageAllChildren(c, renderPass, framebuffer, subpass, fbattachments); + AddFramebufferUsageAllChildren(c, renderState); - AddFramebufferUsage(actionNode, renderPass, framebuffer, subpass, fbattachments); + AddFramebufferUsage(actionNode, renderState); } void WrappedVulkan::AddEvent() diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 545bf1432..ef7d64e09 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -956,12 +956,9 @@ private: void AddEvent(); void AddUsage(VulkanActionTreeNode &actionNode, rdcarray &debugMessages); - void AddFramebufferUsage(VulkanActionTreeNode &actionNode, ResourceId renderPass, - ResourceId framebuffer, uint32_t subpass, - const rdcarray &fbattachments); - void AddFramebufferUsageAllChildren(VulkanActionTreeNode &actionNode, ResourceId renderPass, - ResourceId framebuffer, uint32_t subpass, - const rdcarray &fbattachments); + void AddFramebufferUsage(VulkanActionTreeNode &actionNode, const VulkanRenderState &renderState); + void AddFramebufferUsageAllChildren(VulkanActionTreeNode &actionNode, + const VulkanRenderState &renderState); // no copy semantics WrappedVulkan(const WrappedVulkan &); @@ -2506,4 +2503,11 @@ public: const VkVertexInputBindingDescription2EXT *pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT *pVertexAttributeDescriptions); + + // VK_KHR_dynamic_rendering + + IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdBeginRenderingKHR, VkCommandBuffer commandBuffer, + const VkRenderingInfoKHR *pRenderingInfo); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdEndRenderingKHR, VkCommandBuffer commandBuffer); }; diff --git a/renderdoc/driver/vulkan/vk_dispatch_defs.h b/renderdoc/driver/vulkan/vk_dispatch_defs.h index 6d74a370a..2e9d4548e 100644 --- a/renderdoc/driver/vulkan/vk_dispatch_defs.h +++ b/renderdoc/driver/vulkan/vk_dispatch_defs.h @@ -468,6 +468,10 @@ struct VkDevDispatchTable PFN_vkCmdDecodeVideoKHR CmdDecodeVideoKHR; #endif // VK_ENABLE_BETA_EXTENSIONS + // VK_KHR_dynamic_rendering + PFN_vkCmdBeginRenderingKHR CmdBeginRenderingKHR; + PFN_vkCmdEndRenderingKHR CmdEndRenderingKHR; + // VK_KHR_device_group PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR GetDeviceGroupPeerMemoryFeaturesKHR; PFN_vkCmdSetDeviceMaskKHR CmdSetDeviceMaskKHR; diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index ae5b8169f..6f4374a2c 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -532,7 +532,8 @@ DeclExt(KHR_maintenance4); \ DeclExt(EXT_color_write_enable); \ DeclExt(EXT_extended_dynamic_state2); \ - DeclExt(EXT_vertex_input_dynamic_state); + DeclExt(EXT_vertex_input_dynamic_state); \ + DeclExt(KHR_dynamic_rendering); // for simplicity and since the check itself is platform agnostic, // these aren't protected in platform defines @@ -637,7 +638,8 @@ CheckExt(KHR_maintenance4, VKXX); \ CheckExt(EXT_color_write_enable, VKXX); \ CheckExt(EXT_extended_dynamic_state2, VKXX); \ - CheckExt(EXT_vertex_input_dynamic_state, VKXX); + CheckExt(EXT_vertex_input_dynamic_state, VKXX); \ + CheckExt(KHR_dynamic_rendering, VKXX); #define HookInitVulkanInstanceExts_PhysDev() \ HookInitExtension(KHR_surface, GetPhysicalDeviceSurfaceSupportKHR); \ @@ -890,6 +892,8 @@ HookInitExtension(EXT_extended_dynamic_state2, CmdSetPrimitiveRestartEnableEXT); \ HookInitExtension(EXT_extended_dynamic_state2, CmdSetRasterizerDiscardEnableEXT); \ HookInitExtension(EXT_vertex_input_dynamic_state, CmdSetVertexInputEXT); \ + HookInitExtension(KHR_dynamic_rendering, CmdBeginRenderingKHR); \ + HookInitExtension(KHR_dynamic_rendering, CmdEndRenderingKHR); \ HookInitExtension_Device_Win32(); \ HookInitExtension_Device_Linux(); \ HookInitExtension_Device_GGP(); \ @@ -1600,6 +1604,9 @@ vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT *, \ pVertexBindingDescriptions, uint32_t, vertexAttributeDescriptionCount, \ const VkVertexInputAttributeDescription2EXT *, pVertexAttributeDescriptions); \ + HookDefine2(void, vkCmdBeginRenderingKHR, VkCommandBuffer, commandBuffer, \ + const VkRenderingInfoKHR *, pRenderingInfo); \ + HookDefine1(void, vkCmdEndRenderingKHR, VkCommandBuffer, commandBuffer); \ HookDefine_Win32(); \ HookDefine_Linux(); \ HookDefine_GGP(); \ diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp index d859712fc..62409788b 100644 --- a/renderdoc/driver/vulkan/vk_info.cpp +++ b/renderdoc/driver/vulkan/vk_info.cpp @@ -360,6 +360,25 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, renderpass = GetResID(pCreateInfo->renderPass); subpass = pCreateInfo->subpass; + const VkPipelineRenderingCreateInfoKHR *dynRenderCreate = + (const VkPipelineRenderingCreateInfoKHR *)FindNextStruct( + pCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); + if(dynRenderCreate) + { + viewMask = dynRenderCreate->viewMask; + colorFormats.assign(dynRenderCreate->pColorAttachmentFormats, + dynRenderCreate->colorAttachmentCount); + depthFormat = dynRenderCreate->depthAttachmentFormat; + stencilFormat = dynRenderCreate->stencilAttachmentFormat; + } + else + { + viewMask = 0; + colorFormats.clear(); + depthFormat = VK_FORMAT_UNDEFINED; + stencilFormat = VK_FORMAT_UNDEFINED; + } + RDCEraseEl(dynamicStates); if(pCreateInfo->pDynamicState) { diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index f5821eb68..9fc4abf85 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -256,6 +256,12 @@ struct VulkanCreationInfo ResourceId renderpass; uint32_t subpass; + // VkPipelineRenderingCreateInfoKHR + uint32_t viewMask; + rdcarray colorFormats; + VkFormat depthFormat; + VkFormat stencilFormat; + // 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 dc4df130d..e7ac48fd9 100644 --- a/renderdoc/driver/vulkan/vk_next_chains.cpp +++ b/renderdoc/driver/vulkan/vk_next_chains.cpp @@ -58,6 +58,9 @@ static void CopyNextChainedStruct(const size_t structSize, byte *&tempMem, template static VkStruct *AllocStructCopy(byte *&tempMem, const VkStruct *inputStruct) { + if(!inputStruct) + return NULL; + VkStruct *ret = (VkStruct *)tempMem; tempMem = (byte *)(ret + 1); @@ -229,6 +232,8 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, VkPhysicalDeviceDiscardRectanglePropertiesEXT); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, \ VkPhysicalDeviceDriverProperties); \ + COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR, \ + VkPhysicalDeviceDynamicRenderingFeaturesKHR) \ 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, \ @@ -582,6 +587,8 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, VkConditionalRenderingBeginInfoEXT, UnwrapInPlace(out->buffer)); \ UNWRAP_STRUCT(VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, VkCopyDescriptorSet, \ UnwrapInPlace(out->srcSet), UnwrapInPlace(out->dstSet)); \ + UNWRAP_STRUCT(VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT, \ + VkRenderingFragmentDensityMapAttachmentInfoEXT, UnwrapInPlace(out->imageView)); \ UNWRAP_STRUCT(VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV, \ VkDedicatedAllocationMemoryAllocateInfoNV, UnwrapInPlace(out->buffer), \ UnwrapInPlace(out->image)); \ @@ -608,6 +615,8 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, UnwrapInPlace(out->pipeline)); \ UNWRAP_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR, VkPipelineExecutableInfoKHR, \ UnwrapInPlace(out->pipeline)); \ + UNWRAP_STRUCT(VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, VkRenderingAttachmentInfoKHR, \ + UnwrapInPlace(out->imageView), UnwrapInPlace(out->resolveImageView)); \ UNWRAP_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, VkRenderPassBeginInfo, \ UnwrapInPlace(out->renderPass), UnwrapInPlace(out->framebuffer)); \ UNWRAP_STRUCT(VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, VkSamplerYcbcrConversionInfo, \ @@ -674,6 +683,7 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV: \ case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR: \ case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID: \ + case VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD: \ case VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV: \ case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA: \ case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA: \ @@ -727,6 +737,7 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA: \ case VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT: \ case VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA: \ + case VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX: \ case VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE: \ case VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL: \ case VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL: \ @@ -807,6 +818,7 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR: \ case VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR: \ case VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV: \ + case VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR: \ case VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM: \ case VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT: \ case VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX: \ @@ -877,6 +889,15 @@ size_t GetNextPatchSize(const void *pNext) memSize += GetNextPatchSize(info->pRegions[i].pNext); break; } + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR: + { + memSize += sizeof(VkCommandBufferInheritanceRenderingInfoKHR); + + VkCommandBufferInheritanceRenderingInfoKHR *info = + (VkCommandBufferInheritanceRenderingInfoKHR *)next; + memSize += info->colorAttachmentCount * sizeof(VkCommandBufferInheritanceRenderingInfoKHR); + break; + } case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO: { memSize += sizeof(VkComputePipelineCreateInfo); @@ -1054,6 +1075,14 @@ size_t GetNextPatchSize(const void *pNext) memSize += info->setLayoutCount * sizeof(VkDescriptorSetLayout); break; } + case VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR: + { + memSize += sizeof(VkPipelineRenderingCreateInfoKHR); + + VkPipelineRenderingCreateInfoKHR *info = (VkPipelineRenderingCreateInfoKHR *)next; + memSize += info->colorAttachmentCount * sizeof(VkPipelineRenderingCreateInfoKHR); + break; + } case VK_STRUCTURE_TYPE_PRESENT_INFO_KHR: { memSize += sizeof(VkPresentInfoKHR); @@ -1063,6 +1092,26 @@ size_t GetNextPatchSize(const void *pNext) memSize += info->swapchainCount * sizeof(VkSwapchainKHR); break; } + case VK_STRUCTURE_TYPE_RENDERING_INFO_KHR: + { + memSize += sizeof(VkRenderingInfoKHR); + + VkRenderingInfoKHR *info = (VkRenderingInfoKHR *)next; + memSize += info->colorAttachmentCount * sizeof(VkRenderingAttachmentInfoKHR); + for(uint32_t i = 0; i < info->colorAttachmentCount; i++) + memSize += GetNextPatchSize(info->pColorAttachments[i].pNext); + if(info->pDepthAttachment) + { + memSize += sizeof(*info->pDepthAttachment); + memSize += GetNextPatchSize(info->pStencilAttachment->pNext); + } + if(info->pStencilAttachment) + { + memSize += sizeof(*info->pStencilAttachment); + memSize += GetNextPatchSize(info->pStencilAttachment->pNext); + } + break; + } case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: { memSize += sizeof(VkRenderPassAttachmentBeginInfo); @@ -1292,6 +1341,9 @@ size_t GetNextPatchSize(const void *pNext) void UnwrapNextChain(CaptureState state, const char *structName, byte *&tempMem, VkBaseInStructure *infoStruct) { + if(!infoStruct) + return; + // during capture, this walks the pNext chain and either copies structs that can be passed // straight through, or copies and modifies any with vulkan objects that need to be unwrapped. // @@ -1480,6 +1532,28 @@ void UnwrapNextChain(CaptureState state, const char *structName, byte *&tempMem, break; } + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR: + { + const VkCommandBufferInheritanceRenderingInfoKHR *in = + (const VkCommandBufferInheritanceRenderingInfoKHR *)nextInput; + VkCommandBufferInheritanceRenderingInfoKHR *out = + (VkCommandBufferInheritanceRenderingInfoKHR *)tempMem; + + // append immediately so tempMem is incremented + AppendModifiedChainedStruct(tempMem, out, nextChainTail); + + // allocate unwrapped array + VkFormat *outFormats = (VkFormat *)tempMem; + tempMem += sizeof(VkFormat) * in->colorAttachmentCount; + + *out = *in; + + out->pColorAttachmentFormats = outFormats; + for(uint32_t i = 0; i < in->colorAttachmentCount; i++) + outFormats[i] = in->pColorAttachmentFormats[i]; + + break; + } case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO: { const VkComputePipelineCreateInfo *in = (const VkComputePipelineCreateInfo *)nextInput; @@ -1911,6 +1985,27 @@ void UnwrapNextChain(CaptureState state, const char *structName, byte *&tempMem, break; } + case VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR: + { + const VkPipelineRenderingCreateInfoKHR *in = + (const VkPipelineRenderingCreateInfoKHR *)nextInput; + VkPipelineRenderingCreateInfoKHR *out = (VkPipelineRenderingCreateInfoKHR *)tempMem; + + // append immediately so tempMem is incremented + AppendModifiedChainedStruct(tempMem, out, nextChainTail); + + // allocate unwrapped array + VkFormat *outFormats = (VkFormat *)tempMem; + tempMem += sizeof(VkFormat) * in->colorAttachmentCount; + + *out = *in; + + out->pColorAttachmentFormats = outFormats; + for(uint32_t i = 0; i < in->colorAttachmentCount; i++) + outFormats[i] = in->pColorAttachmentFormats[i]; + + break; + } case VK_STRUCTURE_TYPE_PRESENT_INFO_KHR: { const VkPresentInfoKHR *in = (const VkPresentInfoKHR *)nextInput; @@ -1936,6 +2031,70 @@ void UnwrapNextChain(CaptureState state, const char *structName, byte *&tempMem, break; } + case VK_STRUCTURE_TYPE_RENDERING_INFO_KHR: + { + const VkRenderingInfoKHR *in = (const VkRenderingInfoKHR *)nextInput; + VkRenderingInfoKHR *out = (VkRenderingInfoKHR *)tempMem; + + // append immediately so tempMem is incremented + AppendModifiedChainedStruct(tempMem, out, nextChainTail); + + // allocate unwrapped array + VkRenderingAttachmentInfoKHR *outAttachs = (VkRenderingAttachmentInfoKHR *)tempMem; + tempMem += sizeof(VkRenderingAttachmentInfoKHR) * in->colorAttachmentCount; + + out->sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; + out->pNext = in->pNext; + out->flags = in->flags; + out->renderArea = in->renderArea; + out->layerCount = in->layerCount; + out->viewMask = in->viewMask; + out->colorAttachmentCount = in->colorAttachmentCount; + out->pColorAttachments = outAttachs; + for(uint32_t i = 0; i < in->colorAttachmentCount; i++) + { + outAttachs[i] = in->pColorAttachments[i]; + UnwrapInPlace(outAttachs[i].imageView); + UnwrapInPlace(outAttachs[i].resolveImageView); + UnwrapNextChain(state, "VkRenderingAttachmentInfoKHR", tempMem, + (VkBaseInStructure *)&outAttachs[i]); + } + + if(in->pDepthAttachment) + { + VkRenderingAttachmentInfoKHR *depth = (VkRenderingAttachmentInfoKHR *)tempMem; + out->pDepthAttachment = depth; + tempMem += sizeof(VkRenderingAttachmentInfoKHR); + + *depth = *in->pDepthAttachment; + UnwrapInPlace(depth->imageView); + UnwrapInPlace(depth->resolveImageView); + UnwrapNextChain(state, "VkRenderingAttachmentInfoKHR", tempMem, (VkBaseInStructure *)depth); + } + else + { + out->pDepthAttachment = NULL; + } + + if(in->pStencilAttachment) + { + VkRenderingAttachmentInfoKHR *stencil = (VkRenderingAttachmentInfoKHR *)tempMem; + out->pStencilAttachment = stencil; + tempMem += sizeof(VkRenderingAttachmentInfoKHR); + + *stencil = *in->pStencilAttachment; + UnwrapInPlace(stencil->imageView); + UnwrapInPlace(stencil->resolveImageView); + UnwrapNextChain(state, "VkRenderingAttachmentInfoKHR", tempMem, + (VkBaseInStructure *)stencil); + } + else + { + out->pStencilAttachment = NULL; + } + + break; + } case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: { const VkRenderPassAttachmentBeginInfo *in = @@ -2367,6 +2526,13 @@ void CopyNextChainForPatching(const char *structName, byte *&tempMem, VkBaseInSt case VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR: CopyNextChainedStruct(sizeof(VkBlitImageInfo2KHR), tempMem, nextInput, nextChainTail); break; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR: + CopyNextChainedStruct(sizeof(VkCommandBufferInheritanceRenderingInfoKHR), tempMem, + nextInput, nextChainTail); + break; + case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO: + CopyNextChainedStruct(sizeof(VkComputePipelineCreateInfo), tempMem, nextInput, nextChainTail); + break; case VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR: CopyNextChainedStruct(sizeof(VkCopyBufferInfo2KHR), tempMem, nextInput, nextChainTail); break; @@ -2416,15 +2582,19 @@ void CopyNextChainForPatching(const char *structName, byte *&tempMem, VkBaseInSt CopyNextChainedStruct(sizeof(VkGraphicsPipelineCreateInfo), tempMem, nextInput, nextChainTail); break; - case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO: - CopyNextChainedStruct(sizeof(VkComputePipelineCreateInfo), tempMem, nextInput, nextChainTail); - break; case VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO: CopyNextChainedStruct(sizeof(VkPipelineLayoutCreateInfo), tempMem, nextInput, nextChainTail); break; + case VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR: + CopyNextChainedStruct(sizeof(VkPipelineRenderingCreateInfoKHR), tempMem, nextInput, + nextChainTail); + break; case VK_STRUCTURE_TYPE_PRESENT_INFO_KHR: CopyNextChainedStruct(sizeof(VkPresentInfoKHR), tempMem, nextInput, nextChainTail); break; + case VK_STRUCTURE_TYPE_RENDERING_INFO_KHR: + CopyNextChainedStruct(sizeof(VkRenderingInfoKHR), tempMem, nextInput, nextChainTail); + break; case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: CopyNextChainedStruct(sizeof(VkRenderPassAttachmentBeginInfo), tempMem, nextInput, nextChainTail); diff --git a/renderdoc/driver/vulkan/vk_overlay.cpp b/renderdoc/driver/vulkan/vk_overlay.cpp index 7a8c66065..f01ff675c 100644 --- a/renderdoc/driver/vulkan/vk_overlay.cpp +++ b/renderdoc/driver/vulkan/vk_overlay.cpp @@ -521,13 +521,18 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D uint32_t multiviewMask = m_Overlay.MultiViewMask; - if(m_pDriver->m_RenderState.renderPass != ResourceId()) + VulkanRenderState &state = m_pDriver->m_RenderState; + if(state.dynamicRendering.active) + { + multiviewMask = state.dynamicRendering.viewMask; + } + else if(state.GetRenderPass() != ResourceId()) { const VulkanCreationInfo::RenderPass &rp = - m_pDriver->m_CreationInfo.m_RenderPass[m_pDriver->m_RenderState.renderPass]; + m_pDriver->m_CreationInfo.m_RenderPass[state.GetRenderPass()]; multiviewMask = 0; - for(uint32_t v : rp.subpasses[m_pDriver->m_RenderState.subpass].multiviews) + for(uint32_t v : rp.subpasses[state.subpass].multiviews) multiviewMask |= 1U << v; } @@ -721,9 +726,9 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D // bail out if the render area is outside our image. // This is an order-of-operations problem, if the overlay is set when the event is changed it is // refreshed before the UI layer can update the current texture. - if(m_pDriver->m_RenderState.renderArea.offset.x + m_pDriver->m_RenderState.renderArea.extent.width > + if(state.renderArea.offset.x + state.renderArea.extent.width > (m_Overlay.ImageDim.width >> sub.mip) || - m_pDriver->m_RenderState.renderArea.offset.y + m_pDriver->m_RenderState.renderArea.extent.height > + state.renderArea.offset.y + state.renderArea.extent.height > (m_Overlay.ImageDim.height >> sub.mip)) { return GetResID(m_Overlay.Image); @@ -763,7 +768,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D const ActionDescription *mainDraw = m_pDriver->GetAction(eventId); const VulkanCreationInfo::Pipeline &pipeInfo = - m_pDriver->m_CreationInfo.m_Pipeline[m_pDriver->m_RenderState.graphics.pipeline]; + m_pDriver->m_CreationInfo.m_Pipeline[state.graphics.pipeline]; // Secondary commands can't have render passes if((mainDraw && !(mainDraw->flags & ActionFlags::Drawcall)) || @@ -865,7 +870,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // backup state - VulkanRenderState prevstate = m_pDriver->m_RenderState; + VulkanRenderState prevstate = state; // make patched shader VkShaderModule mod = VK_NULL_HANDLE; @@ -892,12 +897,12 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D rs->rasterizerDiscardEnable = false; // disable tests in dynamic state too - m_pDriver->m_RenderState.depthTestEnable = VK_FALSE; - m_pDriver->m_RenderState.depthWriteEnable = VK_FALSE; - m_pDriver->m_RenderState.depthCompareOp = VK_COMPARE_OP_ALWAYS; - m_pDriver->m_RenderState.stencilTestEnable = VK_FALSE; - m_pDriver->m_RenderState.depthBoundsTestEnable = VK_FALSE; - m_pDriver->m_RenderState.cullMode = VK_CULL_MODE_NONE; + state.depthTestEnable = VK_FALSE; + state.depthWriteEnable = VK_FALSE; + state.depthCompareOp = VK_COMPARE_OP_ALWAYS; + state.stencilTestEnable = VK_FALSE; + state.depthBoundsTestEnable = VK_FALSE; + state.cullMode = VK_CULL_MODE_NONE; // disable all discard rectangles RemoveNextStruct(&pipeCreateInfo, @@ -1031,29 +1036,29 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // modify state - m_pDriver->m_RenderState.renderPass = GetResID(m_Overlay.NoDepthRP); - m_pDriver->m_RenderState.subpass = 0; - m_pDriver->m_RenderState.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB)); + state.SetRenderPass(GetResID(m_Overlay.NoDepthRP)); + state.subpass = 0; + state.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB)); - m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe); + state.graphics.pipeline = GetResID(pipe); // set dynamic scissors in case pipeline was using them if(overlay == DebugOverlay::Drawcall) { - for(size_t i = 0; i < m_pDriver->m_RenderState.scissors.size(); i++) + for(size_t i = 0; i < state.scissors.size(); i++) { - m_pDriver->m_RenderState.scissors[i].offset.x = 0; - m_pDriver->m_RenderState.scissors[i].offset.y = 0; - m_pDriver->m_RenderState.scissors[i].extent.width = 16384; - m_pDriver->m_RenderState.scissors[i].extent.height = 16384; + state.scissors[i].offset.x = 0; + state.scissors[i].offset.y = 0; + state.scissors[i].extent.width = 16384; + state.scissors[i].extent.height = 16384; } } if(overlay == DebugOverlay::Wireframe) - m_pDriver->m_RenderState.lineWidth = 1.0f; + state.lineWidth = 1.0f; if(overlay == DebugOverlay::Drawcall || overlay == DebugOverlay::Wireframe) - m_pDriver->m_RenderState.conditionalRendering.forceDisable = true; + state.conditionalRendering.forceDisable = true; if(patchedIndexCount == 0) { @@ -1073,14 +1078,13 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // do single draw - m_pDriver->m_RenderState.BeginRenderPassAndApplyState(m_pDriver, cmd, - VulkanRenderState::BindGraphics); + state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); ActionDescription action = *mainDraw; action.numIndices = patchedIndexCount; action.baseVertex = 0; action.indexOffset = 0; m_pDriver->ReplayDraw(cmd, action); - m_pDriver->m_RenderState.EndRenderPass(cmd); + state.EndRenderPass(cmd); vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); CheckVkResult(vkr); @@ -1099,7 +1103,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // restore state - m_pDriver->m_RenderState = prevstate; + state = prevstate; patchedIB.Destroy(); @@ -1145,7 +1149,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D float highlightCol[] = {1.0f, 0.0f, 0.0f, 1.0f}; // backup state - VulkanRenderState prevstate = m_pDriver->m_RenderState; + VulkanRenderState prevstate = state; // make patched shader VkShaderModule mod[2] = {0}; @@ -1180,12 +1184,12 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D rs->rasterizerDiscardEnable = false; // disable tests in dynamic state too - m_pDriver->m_RenderState.depthTestEnable = VK_FALSE; - m_pDriver->m_RenderState.depthWriteEnable = VK_FALSE; - m_pDriver->m_RenderState.depthCompareOp = VK_COMPARE_OP_ALWAYS; - m_pDriver->m_RenderState.stencilTestEnable = VK_FALSE; - m_pDriver->m_RenderState.depthBoundsTestEnable = VK_FALSE; - m_pDriver->m_RenderState.cullMode = VK_CULL_MODE_NONE; + state.depthTestEnable = VK_FALSE; + state.depthWriteEnable = VK_FALSE; + state.depthCompareOp = VK_COMPARE_OP_ALWAYS; + state.stencilTestEnable = VK_FALSE; + state.depthBoundsTestEnable = VK_FALSE; + state.cullMode = VK_CULL_MODE_NONE; if(m_pDriver->GetDeviceEnabledFeatures().depthClamp) rs->depthClampEnable = true; @@ -1249,14 +1253,14 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // modify state - m_pDriver->m_RenderState.renderPass = GetResID(m_Overlay.NoDepthRP); - m_pDriver->m_RenderState.subpass = 0; - m_pDriver->m_RenderState.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB)); + state.SetRenderPass(GetResID(m_Overlay.NoDepthRP)); + state.subpass = 0; + state.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB)); - m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[0]); - m_pDriver->m_RenderState.scissors = prevstate.scissors; + state.graphics.pipeline = GetResID(pipe[0]); + state.scissors = prevstate.scissors; - for(VkRect2D &sc : m_pDriver->m_RenderState.scissors) + for(VkRect2D &sc : state.scissors) { sc.offset.x = 0; sc.offset.y = 0; @@ -1266,13 +1270,13 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw); - m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[1]); - m_pDriver->m_RenderState.scissors = prevstate.scissors; + state.graphics.pipeline = GetResID(pipe[1]); + state.scissors = prevstate.scissors; m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw); // restore state - m_pDriver->m_RenderState = prevstate; + state = prevstate; cmd = m_pDriver->GetNextCmd(); @@ -1289,13 +1293,13 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D NULL, Unwrap(m_Overlay.NoDepthRP), Unwrap(m_Overlay.NoDepthFB), - m_pDriver->m_RenderState.renderArea, + state.renderArea, 1, &clearval, }; vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE); - VkViewport viewport = m_pDriver->m_RenderState.views[0]; + VkViewport viewport = state.views[0]; vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport); uint32_t uboOffs = 0; @@ -1334,12 +1338,11 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D vt->CmdDraw(Unwrap(cmd), 4, 1, 0, 0); - if(!m_pDriver->m_RenderState.scissors.empty()) + if(!state.scissors.empty()) { - Vec4f scissor((float)m_pDriver->m_RenderState.scissors[0].offset.x, - (float)m_pDriver->m_RenderState.scissors[0].offset.y, - (float)m_pDriver->m_RenderState.scissors[0].extent.width, - (float)m_pDriver->m_RenderState.scissors[0].extent.height); + Vec4f scissor((float)state.scissors[0].offset.x, (float)state.scissors[0].offset.y, + (float)state.scissors[0].extent.width, + (float)state.scissors[0].extent.height); ubo = (CheckerboardUBOData *)m_Overlay.m_CheckerUBO.Map(&uboOffs); @@ -1432,7 +1435,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // backup state - VulkanRenderState prevstate = m_pDriver->m_RenderState; + VulkanRenderState prevstate = state; // make patched shader VkShaderModule mod[2] = {0}; @@ -1471,12 +1474,12 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D rs->depthClampEnable = true; // disable tests in dynamic state too - m_pDriver->m_RenderState.depthTestEnable = VK_FALSE; - m_pDriver->m_RenderState.depthWriteEnable = VK_FALSE; - m_pDriver->m_RenderState.depthCompareOp = VK_COMPARE_OP_ALWAYS; - m_pDriver->m_RenderState.stencilTestEnable = VK_FALSE; - m_pDriver->m_RenderState.depthBoundsTestEnable = VK_FALSE; - m_pDriver->m_RenderState.cullMode = VK_CULL_MODE_NONE; + state.depthTestEnable = VK_FALSE; + state.depthWriteEnable = VK_FALSE; + state.depthCompareOp = VK_COMPARE_OP_ALWAYS; + state.stencilTestEnable = VK_FALSE; + state.depthBoundsTestEnable = VK_FALSE; + state.cullMode = VK_CULL_MODE_NONE; VkPipelineColorBlendStateCreateInfo *cb = (VkPipelineColorBlendStateCreateInfo *)pipeCreateInfo.pColorBlendState; @@ -1538,16 +1541,16 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // modify state - m_pDriver->m_RenderState.renderPass = GetResID(m_Overlay.NoDepthRP); - m_pDriver->m_RenderState.subpass = 0; - m_pDriver->m_RenderState.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB)); + state.SetRenderPass(GetResID(m_Overlay.NoDepthRP)); + state.subpass = 0; + state.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB)); - m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[0]); + state.graphics.pipeline = GetResID(pipe[0]); m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw); - m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[1]); - m_pDriver->m_RenderState.cullMode = origCullMode; + state.graphics.pipeline = GetResID(pipe[1]); + state.cullMode = origCullMode; m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw); @@ -1564,7 +1567,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // restore state - m_pDriver->m_RenderState = prevstate; + state = prevstate; for(int i = 0; i < 2; i++) { @@ -1607,17 +1610,32 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D VkFramebuffer depthFB = VK_NULL_HANDLE; VkRenderPass depthRP = VK_NULL_HANDLE; - const VulkanRenderState &state = m_pDriver->m_RenderState; VulkanCreationInfo &createinfo = m_pDriver->m_CreationInfo; - RDCASSERT(state.subpass < createinfo.m_RenderPass[state.renderPass].subpasses.size()); - int32_t dsIdx = - createinfo.m_RenderPass[state.renderPass].subpasses[state.subpass].depthstencilAttachment; + ResourceId depthStencilView; - // make a renderpass and framebuffer for rendering to overlay color and using - // depth buffer from the orignial render - if(dsIdx >= 0 && - dsIdx < (int32_t)createinfo.m_Framebuffer[state.GetFramebuffer()].attachments.size()) + if(state.dynamicRendering.active) + { + depthStencilView = GetResID(state.dynamicRendering.depth.imageView); + if(depthStencilView == ResourceId()) + depthStencilView = GetResID(state.dynamicRendering.stencil.imageView); + } + else + { + RDCASSERT(state.subpass < createinfo.m_RenderPass[state.GetRenderPass()].subpasses.size()); + int32_t dsIdx = + createinfo.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].depthstencilAttachment; + + // make a renderpass and framebuffer for rendering to overlay color and using + // depth buffer from the orignial render + if(dsIdx >= 0 && + dsIdx < (int32_t)createinfo.m_Framebuffer[state.GetFramebuffer()].attachments.size()) + { + depthStencilView = state.GetFramebufferAttachments()[dsIdx]; + } + } + + if(depthStencilView != ResourceId()) { VkAttachmentDescription attDescs[] = { {0, overlayFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, @@ -1630,8 +1648,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}, }; - ResourceId depthView = state.GetFramebufferAttachments()[dsIdx]; - VulkanCreationInfo::ImageView &depthViewInfo = createinfo.m_ImageView[depthView]; + VulkanCreationInfo::ImageView &depthViewInfo = createinfo.m_ImageView[depthStencilView]; ResourceId depthIm = depthViewInfo.image; VulkanCreationInfo::Image &depthImageInfo = createinfo.m_Image[depthIm]; @@ -1684,7 +1701,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D VkImageView views[] = { m_Overlay.ImageView, - m_pDriver->GetResourceManager()->GetCurrentHandle(depthView), + m_pDriver->GetResourceManager()->GetCurrentHandle(depthStencilView), }; // Create framebuffer rendering just to overlay image, no depth @@ -1712,7 +1729,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D highlightCol[3] = 1.0f; // backup state - VulkanRenderState prevstate = m_pDriver->m_RenderState; + VulkanRenderState prevstate = state; // make patched shader VkShaderModule failmod = {}, passmod = {}; @@ -1826,32 +1843,32 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // modify state - m_pDriver->m_RenderState.renderPass = GetResID(m_Overlay.NoDepthRP); - m_pDriver->m_RenderState.subpass = 0; - m_pDriver->m_RenderState.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB)); + state.SetRenderPass(GetResID(m_Overlay.NoDepthRP)); + state.subpass = 0; + state.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB)); - m_pDriver->m_RenderState.graphics.pipeline = GetResID(failpipe); + state.graphics.pipeline = GetResID(failpipe); // disable tests in dynamic state too - m_pDriver->m_RenderState.depthTestEnable = VK_FALSE; - m_pDriver->m_RenderState.depthWriteEnable = VK_FALSE; - m_pDriver->m_RenderState.stencilTestEnable = VK_FALSE; - m_pDriver->m_RenderState.depthBoundsTestEnable = VK_FALSE; - m_pDriver->m_RenderState.cullMode = VK_CULL_MODE_NONE; + state.depthTestEnable = VK_FALSE; + state.depthWriteEnable = VK_FALSE; + state.stencilTestEnable = VK_FALSE; + state.depthBoundsTestEnable = VK_FALSE; + state.cullMode = VK_CULL_MODE_NONE; m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw); - m_pDriver->m_RenderState.graphics.pipeline = GetResID(passpipe); + state.graphics.pipeline = GetResID(passpipe); if(depthRP != VK_NULL_HANDLE) { - m_pDriver->m_RenderState.renderPass = GetResID(depthRP); - m_pDriver->m_RenderState.SetFramebuffer(m_pDriver, GetResID(depthFB)); + state.SetRenderPass(GetResID(depthRP)); + state.SetFramebuffer(m_pDriver, GetResID(depthFB)); } if(overlay == DebugOverlay::Depth) - m_pDriver->m_RenderState.depthTestEnable = origDepthTest; + state.depthTestEnable = origDepthTest; else - m_pDriver->m_RenderState.stencilTestEnable = origStencilTest; + state.stencilTestEnable = origStencilTest; m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw); @@ -1868,7 +1885,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D CheckVkResult(vkr); // restore state - m_pDriver->m_RenderState = prevstate; + state = prevstate; m_pDriver->vkDestroyPipeline(m_Device, failpipe, NULL); m_pDriver->vkDestroyShaderModule(m_Device, failmod, NULL); @@ -1969,30 +1986,39 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo); CheckVkResult(vkr); - m_pDriver->m_RenderState.BeginRenderPassAndApplyState(m_pDriver, cmd, - VulkanRenderState::BindGraphics); + state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); VkClearAttachment clearatt = {VK_IMAGE_ASPECT_COLOR_BIT, 0, {}}; memcpy(clearatt.clearValue.color.float32, &clearCol, sizeof(clearatt.clearValue.color.float32)); rdcarray atts; - VulkanCreationInfo::Framebuffer &fb = - m_pDriver->m_CreationInfo.m_Framebuffer[m_pDriver->m_RenderState.GetFramebuffer()]; - VulkanCreationInfo::RenderPass &rp = - m_pDriver->m_CreationInfo.m_RenderPass[m_pDriver->m_RenderState.renderPass]; - - for(size_t i = 0; i < rp.subpasses[m_pDriver->m_RenderState.subpass].colorAttachments.size(); - i++) + if(state.dynamicRendering.active) { - clearatt.colorAttachment = (uint32_t)i; - atts.push_back(clearatt); + for(size_t i = 0; i < state.dynamicRendering.color.size(); i++) + { + if(state.dynamicRendering.color[i].imageView == VK_NULL_HANDLE) + continue; + + clearatt.colorAttachment = (uint32_t)i; + atts.push_back(clearatt); + } + } + else + { + VulkanCreationInfo::RenderPass &rp = + m_pDriver->m_CreationInfo.m_RenderPass[state.GetRenderPass()]; + + for(size_t i = 0; i < rp.subpasses[state.subpass].colorAttachments.size(); i++) + { + clearatt.colorAttachment = (uint32_t)i; + atts.push_back(clearatt); + } } // Try to clear depth as well, to help debug shadow rendering - if(m_pDriver->m_RenderState.graphics.pipeline != ResourceId() && - IsDepthOrStencilFormat(iminfo.format)) + if(state.graphics.pipeline != ResourceId() && IsDepthOrStencilFormat(iminfo.format)) { - VkCompareOp depthCompareOp = m_pDriver->m_RenderState.depthCompareOp; + VkCompareOp depthCompareOp = state.depthCompareOp; // If the depth func is equal or not equal, don't clear at all since the output would be // altered in an way that would cause replay to produce mostly incorrect results. @@ -2016,12 +2042,12 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D } VkClearRect rect = { - {{0, 0}, {fb.width, fb.height}}, 0, 1, + state.renderArea, 0, 1, }; vt->CmdClearAttachments(Unwrap(cmd), (uint32_t)atts.size(), &atts[0], 1, &rect); - m_pDriver->m_RenderState.EndRenderPass(cmd); + state.EndRenderPass(cmd); vkr = vt->EndCommandBuffer(Unwrap(cmd)); CheckVkResult(vkr); @@ -2047,7 +2073,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D { if(m_Overlay.m_QuadResolvePipeline[0] != VK_NULL_HANDLE && !pipeInfo.rasterizerDiscardEnable) { - VulkanRenderState prevstate = m_pDriver->m_RenderState; + VulkanRenderState prevstate = state; SCOPED_TIMER("Quad Overdraw"); @@ -2242,7 +2268,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D NULL, Unwrap(m_Overlay.NoDepthRP), Unwrap(m_Overlay.NoDepthFB), - m_pDriver->m_RenderState.renderArea, + state.renderArea, 1, &clearval, }; @@ -2290,7 +2316,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D { if(!pipeInfo.rasterizerDiscardEnable) { - VulkanRenderState prevstate = m_pDriver->m_RenderState; + VulkanRenderState prevstate = state; VkPipelineShaderStageCreateInfo stages[3] = { {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 0, VK_SHADER_STAGE_VERTEX_BIT, @@ -2359,8 +2385,6 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D m_pDriver->ReplayLog(0, events[0], eReplay_WithoutDraw); - VulkanRenderState &state = m_pDriver->GetRenderState(); - uint32_t meshOffs = 0; MeshUBOData *data = (MeshUBOData *)m_MeshRender.UBO.Map(&meshOffs); @@ -2406,19 +2430,31 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D VulkanCreationInfo &createinfo = m_pDriver->m_CreationInfo; - RDCASSERT(state.subpass < createinfo.m_RenderPass[state.renderPass].subpasses.size()); - int32_t dsIdx = - createinfo.m_RenderPass[state.renderPass].subpasses[state.subpass].depthstencilAttachment; + ResourceId depthStencilView; - bool depthUsed = false; - - // make a renderpass and framebuffer for rendering to overlay color and using - // depth buffer from the orignial render - if(dsIdx >= 0 && - dsIdx < (int32_t)createinfo.m_Framebuffer[state.GetFramebuffer()].attachments.size()) + if(state.dynamicRendering.active) { - depthUsed = true; + depthStencilView = GetResID(state.dynamicRendering.depth.imageView); + if(depthStencilView == ResourceId()) + depthStencilView = GetResID(state.dynamicRendering.stencil.imageView); + } + else + { + RDCASSERT(state.subpass < createinfo.m_RenderPass[state.GetRenderPass()].subpasses.size()); + int32_t dsIdx = + createinfo.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].depthstencilAttachment; + // make a renderpass and framebuffer for rendering to overlay color and using + // depth buffer from the orignial render + if(dsIdx >= 0 && + dsIdx < (int32_t)createinfo.m_Framebuffer[state.GetFramebuffer()].attachments.size()) + { + depthStencilView = state.GetFramebufferAttachments()[dsIdx]; + } + } + + if(depthStencilView != ResourceId()) + { VkAttachmentDescription attDescs[] = { {0, overlayFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, @@ -2430,8 +2466,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}, }; - ResourceId depthView = state.GetFramebufferAttachments()[dsIdx]; - VulkanCreationInfo::ImageView &depthViewInfo = createinfo.m_ImageView[depthView]; + VulkanCreationInfo::ImageView &depthViewInfo = createinfo.m_ImageView[depthStencilView]; ResourceId depthIm = depthViewInfo.image; VulkanCreationInfo::Image &depthImageInfo = createinfo.m_Image[depthIm]; @@ -2484,7 +2519,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D VkImageView views[] = { m_Overlay.ImageView, - m_pDriver->GetResourceManager()->GetCurrentHandle(depthView), + m_pDriver->GetResourceManager()->GetCurrentHandle(depthStencilView), }; // Create framebuffer rendering just to overlay image, no depth @@ -2840,7 +2875,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D m_pDriver->SubmitCmds(); m_pDriver->FlushQ(); - if(depthUsed) + if(depthStencilView != ResourceId()) { m_pDriver->vkDestroyFramebuffer(m_Device, FB, NULL); m_pDriver->vkDestroyRenderPass(m_Device, RP, NULL); @@ -2854,7 +2889,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D m_pDriver->ReplayLog(0, eventId, eReplay_WithoutDraw); // restore state - m_pDriver->m_RenderState = prevstate; + state = prevstate; cmd = m_pDriver->GetNextCmd(); diff --git a/renderdoc/driver/vulkan/vk_pixelhistory.cpp b/renderdoc/driver/vulkan/vk_pixelhistory.cpp index 5f2abfa21..e0eb3f952 100644 --- a/renderdoc/driver/vulkan/vk_pixelhistory.cpp +++ b/renderdoc/driver/vulkan/vk_pixelhistory.cpp @@ -637,14 +637,85 @@ protected: dynState->dynamicStateCount = (uint32_t)m_DynamicStates.size(); } - // CreateRenderPass creates a new VkRenderPass based on the original that has a separate - // depth-stencil attachment, and covers a single subpass. This will be used to replay - // a single draw. The new renderpass also replaces the depth stencil attachment, so - // it can be used to count the number of fragments. Optionally, the new renderpass - // changes the format for the color image that corresponds to colorIdx attachment. - VkRenderPass CreateRenderPass(ResourceId rp, bool &multiview, - VkFormat newColorFormat = VK_FORMAT_UNDEFINED, uint32_t colorIdx = 0) + // PatchRenderPass creates a new VkRenderPass based on the original that has a separate + // depth-stencil attachment, and covers a single subpass. This will be used to replay a single + // draw. The new renderpass also replaces the depth stencil attachment, so it can be used to count + // the number of fragments. Optionally, the new renderpass changes the format for the color image + // that corresponds to colorIdx attachment. It also modifies the render state to use the new + // renderpass, and returns it for further use. + // + // When dynamic rendering is in use, it doesn't create a new renderpass it just modifies the + // passed in state and returns a NULL handle. + VkRenderPass PatchRenderPass(VulkanRenderState &pipestate, bool &multiview, + VkFormat newColorFormat = VK_FORMAT_UNDEFINED, uint32_t colorIdx = 0) { + if(pipestate.dynamicRendering.active) + { + VulkanRenderState::DynamicRendering &dyn = pipestate.dynamicRendering; + // replicate work done below on renderpass objects. + + multiview = false; + if(pipestate.dynamicRendering.viewMask > 1) + { + pipestate.dynamicRendering.viewMask = 1U << m_CallbackInfo.targetSubresource.slice; + multiview = true; + } + + // strip any resolving, change load/store ops to load/store + for(size_t i = 0; i < dyn.color.size(); i++) + { + dyn.color[i].resolveMode = VK_RESOLVE_MODE_NONE; + dyn.color[i].resolveImageView = VK_NULL_HANDLE; + + if(dyn.color[i].loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT) + dyn.color[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + if(dyn.color[i].storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT) + dyn.color[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + // nothing to do with newColorFormat here - we patch that when creating the pipeline + } + + if(colorIdx >= (uint32_t)dyn.color.size()) + { + VkRenderingAttachmentInfoKHR c = { + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, + NULL, + VK_NULL_HANDLE, // the image view will be bound in PatchFramebuffer + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_RESOLVE_MODE_NONE, + VK_NULL_HANDLE, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_STORE_OP_STORE, + {}, + }; + + dyn.color.push_back(c); + } + + dyn.depth.resolveMode = VK_RESOLVE_MODE_NONE; + dyn.depth.resolveImageView = VK_NULL_HANDLE; + if(dyn.depth.loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT) + dyn.depth.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + if(dyn.depth.storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT) + dyn.depth.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + dyn.stencil.resolveMode = VK_RESOLVE_MODE_NONE; + dyn.stencil.resolveImageView = VK_NULL_HANDLE; + dyn.stencil.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + if(dyn.stencil.storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT) + dyn.stencil.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + // we'll be using our own depth/stencil attachment but it will be updated in PatchFramebuffer. + // Just set the image layout here + dyn.depth.imageLayout = dyn.stencil.imageLayout = + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + return VK_NULL_HANDLE; + } + + ResourceId rp = pipestate.GetRenderPass(); + const VulkanCreationInfo::RenderPass &rpInfo = m_pDriver->GetDebugManager()->GetRenderPassInfo(rp); // TODO: this should retrieve the correct subpass, once multiple subpasses @@ -807,17 +878,46 @@ protected: m_pDriver->vkCreateRenderPass(m_pDriver->GetDev(), &rpCreateInfo, NULL, &renderpass); m_pDriver->CheckVkResult(vkr); m_RpsToDestroy.push_back(renderpass); + + pipestate.SetRenderPass(GetResID(renderpass)); + return renderpass; } - // CreateFrambuffer creates a new VkFramebuffer that is based on the original, but + // PatchFramebuffer creates a new VkFramebuffer that is based on the original, but // substitutes the depth stencil image view. If there is no depth stencil attachment, // it will be added. Optionally, also substitutes the original target image view with - // the newColorAtt. - VkFramebuffer CreateFramebuffer(const VulkanRenderState &pipestate, VkRenderPass newRp, - VkImageView newColorAtt = VK_NULL_HANDLE, uint32_t colorIdx = 0) + // the newColorAtt. It also modifies the render state to use the new + // framebuffer, and returns it for further use. + // + // When dynamic rendering is in use, it doesn't create a new framebuffer it just modifies the + // passed in state and returns a NULL handle. + VkFramebuffer PatchFramebuffer(VulkanRenderState &pipestate, VkRenderPass newRp, + VkImageView newColorAtt = VK_NULL_HANDLE, + VkFormat newColorFormat = VK_FORMAT_UNDEFINED, uint32_t colorIdx = 0) { - ResourceId rp = pipestate.renderPass; + if(pipestate.dynamicRendering.active) + { + VulkanRenderState::DynamicRendering &dyn = pipestate.dynamicRendering; + + // patch the color, if we're doing that + if(newColorAtt != VK_NULL_HANDLE) + { + // colorIdx shouldn't be greater as we pushed back a new attachment in PatchRenderPass, but + // just in case fixup here + if(colorIdx >= (uint32_t)dyn.color.size()) + colorIdx = uint32_t(dyn.color.size() - 1); + + dyn.color[colorIdx].imageView = newColorAtt; + } + + // patch the D/S view + dyn.depth.imageView = dyn.stencil.imageView = m_CallbackInfo.dsImageView; + + return VK_NULL_HANDLE; + } + + ResourceId rp = pipestate.GetRenderPass(); ResourceId origFb = pipestate.GetFramebuffer(); const VulkanCreationInfo::RenderPass &rpInfo = m_pDriver->GetDebugManager()->GetRenderPassInfo(rp); @@ -860,6 +960,9 @@ protected: VkResult vkr = m_pDriver->vkCreateFramebuffer(m_pDriver->GetDev(), &fbCI, NULL, &framebuffer); m_pDriver->CheckVkResult(vkr); m_FbsToDestroy.push_back(framebuffer); + + pipestate.SetFramebuffer(m_pDriver, GetResID(framebuffer)); + return framebuffer; } @@ -1040,7 +1143,7 @@ protected: bool HasMultipleSubpasses() { - ResourceId rp = m_pDriver->GetCmdRenderState().renderPass; + ResourceId rp = m_pDriver->GetCmdRenderState().GetRenderPass(); if(rp == ResourceId()) return false; const VulkanCreationInfo::RenderPass &rpInfo = @@ -1050,12 +1153,10 @@ protected: // Returns teh color attachment index that corresponds to the target image for // pixel history. - uint32_t GetColorAttachmentIndex(const VulkanRenderState &renderstate) + uint32_t GetColorAttachmentIndex(const VulkanRenderState &renderstate, + uint32_t *framebufferIndex = NULL) { - if(IsDepthOrStencilFormat(m_CallbackInfo.targetImageFormat)) - return 0; - - uint32_t framebufferIndex = 0; + uint32_t fbIndex = 0; const rdcarray &atts = renderstate.GetFramebufferAttachments(); for(uint32_t i = 0; i < atts.size(); i++) @@ -1063,17 +1164,45 @@ protected: ResourceId img = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[i]).image; if(img == GetResID(m_CallbackInfo.targetImage)) { - framebufferIndex = i; + fbIndex = i; break; } } + if(framebufferIndex) + *framebufferIndex = fbIndex; + + if(IsDepthOrStencilFormat(m_CallbackInfo.targetImageFormat)) + { + if(framebufferIndex && renderstate.dynamicRendering.active) + *framebufferIndex = ~0U; + return 0; + } + + if(renderstate.dynamicRendering.active) + { + for(size_t i = 0; i < renderstate.dynamicRendering.color.size(); i++) + { + VkImageView v = renderstate.dynamicRendering.color[i].imageView; + if(v != VK_NULL_HANDLE) + { + ResourceId img = m_pDriver->GetDebugManager()->GetImageViewInfo(GetResID(v)).image; + if(img == GetResID(m_CallbackInfo.targetImage)) + { + if(framebufferIndex) + *framebufferIndex = (uint32_t)i; + return (uint32_t)i; + } + } + } + } + const VulkanCreationInfo::RenderPass &rpInfo = - m_pDriver->GetDebugManager()->GetRenderPassInfo(renderstate.renderPass); + m_pDriver->GetDebugManager()->GetRenderPassInfo(renderstate.GetRenderPass()); const VulkanCreationInfo::RenderPass::Subpass &sub = rpInfo.subpasses.front(); for(uint32_t i = 0; i < sub.colorAttachments.size(); i++) { - if(framebufferIndex == sub.colorAttachments[i]) + if(fbIndex == sub.colorAttachments[i]) return i; } return 0; @@ -1270,22 +1399,19 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback VulkanRenderState &pipestate = m_pDriver->GetCmdRenderState(); pipestate.EndRenderPass(cmd); + // if dynamic rendering is in use and the renderpass just suspended, we need to be sure it is + // really finished. This will just store as we always patch the load/store ops. + pipestate.FinishSuspendedRenderPass(cmd); // Get pre-modification values size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo); CopyPixel(eid, cmd, storeOffset); - ResourceId prevRenderpass = pipestate.renderPass; - ResourceId prevFramebuffer = pipestate.GetFramebuffer(); - rdcarray prevFBattachments = pipestate.GetFramebufferAttachments(); - - uint32_t prevSubpass = pipestate.subpass; - { bool multiview = false; - VkRenderPass newRp = CreateRenderPass(pipestate.renderPass, multiview); - VkFramebuffer newFb = CreateFramebuffer(pipestate, newRp); + VkRenderPass newRp = PatchRenderPass(pipestate, multiview); + PatchFramebuffer(pipestate, newRp); PipelineReplacements replacements = GetPipelineReplacements( eid, pipestate.graphics.pipeline, newRp, GetColorAttachmentIndex(prevState)); @@ -1298,8 +1424,6 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback // Replay the draw with a fixed color shader that never discards, and stencil // increment to count number of fragments. We will get the number of fragments // not accounting for shader discard. - pipestate.SetFramebuffer(m_pDriver, GetResID(newFb)); - pipestate.renderPass = GetResID(newRp); pipestate.graphics.pipeline = GetResID(replacements.fixedShaderStencil); pipestate.front.compare = pipestate.front.write = 0xff; pipestate.front.ref = 0; @@ -1327,14 +1451,11 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback } // Restore the state. - m_pDriver->GetCmdRenderState() = prevState; - pipestate.SetFramebuffer(prevFramebuffer, prevFBattachments); - pipestate.renderPass = prevRenderpass; - pipestate.subpass = prevSubpass; + pipestate = prevState; // TODO: Need to re-start on the correct subpass. if(pipestate.graphics.pipeline != ResourceId()) - pipestate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics); + pipestate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics, true); } bool PostDraw(uint32_t eid, VkCommandBuffer cmd) @@ -1353,13 +1474,16 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback } m_pDriver->GetCmdRenderState().EndRenderPass(cmd); + // if dynamic rendering is in use and the renderpass just suspended, we need to be sure it is + // really finished. This will just store as we always patch the load/store ops. + m_pDriver->GetCmdRenderState().FinishSuspendedRenderPass(cmd); size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo); CopyPixel(eid, cmd, storeOffset + offsetof(struct EventInfo, postmod)); - m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState(m_pDriver, cmd, - VulkanRenderState::BindGraphics); + m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState( + m_pDriver, cmd, VulkanRenderState::BindGraphics, true); // Get post-modification values m_EventIndices.insert(std::make_pair(eid, m_EventIndices.size())); @@ -1399,17 +1523,22 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback return; } - if(m_pDriver->GetCmdRenderState().renderPass != ResourceId()) + if(m_pDriver->GetCmdRenderState().ActiveRenderPass()) + { m_pDriver->GetCmdRenderState().EndRenderPass(cmd); + // if dynamic rendering is in use and the renderpass just suspended, we need to be sure it is + // really finished. This will just store as we always patch the load/store ops. + m_pDriver->GetCmdRenderState().FinishSuspendedRenderPass(cmd); + } // Copy size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo); CopyPixel(eventId, cmd, storeOffset); m_EventIndices.insert(std::make_pair(eventId, m_EventIndices.size())); - if(m_pDriver->GetCmdRenderState().renderPass != ResourceId()) - m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState(m_pDriver, cmd, - VulkanRenderState::BindNone); + if(m_pDriver->GetCmdRenderState().ActiveRenderPass()) + m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState( + m_pDriver, cmd, VulkanRenderState::BindNone, true); } void PostCmdExecute(uint32_t baseEid, uint32_t secondaryFirst, uint32_t secondaryLast, @@ -1440,9 +1569,15 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback return; } - if(m_pDriver->GetCmdRenderState().renderPass != ResourceId()) + if(m_pDriver->GetCmdRenderState().ActiveRenderPass()) + { m_pDriver->GetCmdRenderState().EndRenderPass(cmd); + // if dynamic rendering is in use and the renderpass just suspended, we need to be sure it is + // really finished. This will just store as we always patch the load/store ops. + m_pDriver->GetCmdRenderState().FinishSuspendedRenderPass(cmd); + } + size_t storeOffset = 0; auto it = m_EventIndices.find(eventId); if(it != m_EventIndices.end()) @@ -1456,9 +1591,9 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback } CopyPixel(eventId, cmd, storeOffset + offsetof(struct EventInfo, postmod)); - if(m_pDriver->GetCmdRenderState().renderPass != ResourceId()) - m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState(m_pDriver, cmd, - VulkanRenderState::BindNone); + if(m_pDriver->GetCmdRenderState().ActiveRenderPass()) + m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState( + m_pDriver, cmd, VulkanRenderState::BindNone, true); } void PreDispatch(uint32_t eid, VkCommandBuffer cmd) @@ -1507,13 +1642,19 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback return false; } if(flags & ActionFlags::BeginPass) + { m_pDriver->GetCmdRenderState().EndRenderPass(cmd); + // if dynamic rendering is in use and the renderpass just suspended, we need to be sure it is + // really finished. This will just store as we always patch the load/store ops. + m_pDriver->GetCmdRenderState().FinishSuspendedRenderPass(cmd); + } + bool ret = PostDispatch(eid, cmd); if(flags & ActionFlags::BeginPass) - m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState(m_pDriver, cmd, - VulkanRenderState::BindNone); + m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState( + m_pDriver, cmd, VulkanRenderState::BindNone, true); return ret; } @@ -1575,37 +1716,61 @@ private: const VulkanRenderState &state = m_pDriver->GetCmdRenderState(); - if(state.renderPass != ResourceId()) + ResourceId depthImageId; + VkImageLayout depthLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if(state.dynamicRendering.active) + { + VkImageView dsView = state.dynamicRendering.depth.imageView; + depthLayout = state.dynamicRendering.depth.imageLayout; + if(dsView == VK_NULL_HANDLE && state.dynamicRendering.stencil.imageView != VK_NULL_HANDLE) + { + dsView = state.dynamicRendering.stencil.imageView; + depthLayout = state.dynamicRendering.stencil.imageLayout; + } + + if(dsView != VK_NULL_HANDLE) + { + depthImageId = m_pDriver->GetDebugManager()->GetImageViewInfo(GetResID(dsView)).image; + } + } + else if(state.GetRenderPass() != ResourceId()) { const VulkanCreationInfo::RenderPass &rpInfo = - m_pDriver->GetDebugManager()->GetRenderPassInfo(state.renderPass); + m_pDriver->GetDebugManager()->GetRenderPassInfo(state.GetRenderPass()); const rdcarray &atts = state.GetFramebufferAttachments(); int32_t att = rpInfo.subpasses[state.subpass].depthstencilAttachment; if(att >= 0) { - ResourceId resId = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[att]).image; - VkImage depthImage = m_pDriver->GetResourceManager()->GetCurrentHandle(resId); - - const VulkanCreationInfo::Image &imginfo = m_pDriver->GetDebugManager()->GetImageInfo(resId); - CopyPixelParams depthCopyParams = targetCopyParams; - depthCopyParams.srcImage = depthImage; - depthCopyParams.srcImageLayout = rpInfo.subpasses[state.subpass].depthLayout; - depthCopyParams.srcImageFormat = imginfo.format; - depthCopyParams.multisampled = (imginfo.samples != VK_SAMPLE_COUNT_1_BIT); - CopyImagePixel(cmd, depthCopyParams, offset + offsetof(struct PixelHistoryValue, depth)); - m_DepthFormats.insert(std::make_pair(eid, imginfo.format)); + depthImageId = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[att]).image; + depthLayout = rpInfo.subpasses[state.subpass].depthLayout; } } + + if(depthImageId != ResourceId()) + { + VkImage depthImage = m_pDriver->GetResourceManager()->GetCurrentHandle(depthImageId); + + const VulkanCreationInfo::Image &imginfo = + m_pDriver->GetDebugManager()->GetImageInfo(depthImageId); + CopyPixelParams depthCopyParams = targetCopyParams; + depthCopyParams.srcImage = depthImage; + depthCopyParams.srcImageLayout = depthLayout; + depthCopyParams.srcImageFormat = imginfo.format; + depthCopyParams.multisampled = (imginfo.samples != VK_SAMPLE_COUNT_1_BIT); + CopyImagePixel(cmd, depthCopyParams, offset + offsetof(struct PixelHistoryValue, depth)); + m_DepthFormats.insert(std::make_pair(eid, imginfo.format)); + } } // ReplayDraw begins renderpass, executes a single draw defined by the eventId and // ends the renderpass. void ReplayDraw(VkCommandBuffer cmd, uint32_t eventId, bool clear = false) { - m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState(m_pDriver, cmd, - VulkanRenderState::BindGraphics); + m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState( + m_pDriver, cmd, VulkanRenderState::BindGraphics, false); ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff); ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff); @@ -1809,14 +1974,26 @@ private: flags |= TestMustFail_Culling; } - // Depth and Stencil tests. - const VulkanCreationInfo::RenderPass &rpInfo = - m_pDriver->GetDebugManager()->GetRenderPassInfo(pipestate.renderPass); - // TODO: this should retrieve the correct subpass, once multiple subpasses - // are supported. - const VulkanCreationInfo::RenderPass::Subpass &sub = rpInfo.subpasses.front(); + bool hasDepthStencil = false; - if(sub.depthstencilAttachment != -1) + if(pipestate.dynamicRendering.active) + { + hasDepthStencil = pipestate.dynamicRendering.depth.imageView != VK_NULL_HANDLE || + pipestate.dynamicRendering.stencil.imageView != VK_NULL_HANDLE; + } + else + { + // Depth and Stencil tests. + const VulkanCreationInfo::RenderPass &rpInfo = + m_pDriver->GetDebugManager()->GetRenderPassInfo(pipestate.GetRenderPass()); + // TODO: this should retrieve the correct subpass, once multiple subpasses + // are supported. + const VulkanCreationInfo::RenderPass::Subpass &sub = rpInfo.subpasses.front(); + + hasDepthStencil = (sub.depthstencilAttachment != -1); + } + + if(hasDepthStencil) { if(pipestate.depthBoundsTestEnable) flags |= TestEnabled_DepthBounds; @@ -2221,51 +2398,41 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback VulkanRenderState &state = m_pDriver->GetCmdRenderState(); ResourceId curPipeline = state.graphics.pipeline; state.EndRenderPass(cmd); + // if dynamic rendering is in use and the renderpass just suspended, we need to be sure it is + // really finished. This will just store as we always patch the load/store ops. + state.FinishSuspendedRenderPass(cmd); uint32_t numFragmentsInEvent = m_EventFragments[eid]; uint32_t framebufferIndex = 0; - uint32_t colorOutputIndex = 0; - const rdcarray &atts = prevState.GetFramebufferAttachments(); - const VulkanCreationInfo::RenderPass &rpInfo = - m_pDriver->GetDebugManager()->GetRenderPassInfo(prevState.renderPass); - const VulkanCreationInfo::RenderPass::Subpass &sub = rpInfo.subpasses.front(); + uint32_t colorOutputIndex = GetColorAttachmentIndex(prevState, &framebufferIndex); if(IsDepthOrStencilFormat(m_CallbackInfo.targetImageFormat)) { - // Going to add another color attachment. - framebufferIndex = (uint32_t)atts.size(); - colorOutputIndex = (uint32_t)sub.colorAttachments.size(); - } - else - { - for(uint32_t i = 0; i < atts.size(); i++) + if(prevState.dynamicRendering.active) { - ResourceId img = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[i]).image; - if(img == GetResID(m_CallbackInfo.targetImage)) - { - framebufferIndex = i; - break; - } + framebufferIndex = colorOutputIndex = (uint32_t)prevState.dynamicRendering.color.size(); } - for(uint32_t i = 0; i < sub.colorAttachments.size(); i++) + else { - if(framebufferIndex == sub.colorAttachments[i]) - { - colorOutputIndex = i; - break; - } + const VulkanCreationInfo::RenderPass &rpInfo = + m_pDriver->GetDebugManager()->GetRenderPassInfo(prevState.GetRenderPass()); + const VulkanCreationInfo::RenderPass::Subpass &sub = rpInfo.subpasses.front(); + + // Going to add another color attachment. + framebufferIndex = (uint32_t)prevState.GetFramebufferAttachments().size(); + colorOutputIndex = (uint32_t)sub.colorAttachments.size(); } } bool multiview = false; - VkRenderPass newRp = CreateRenderPass(state.renderPass, multiview, - VK_FORMAT_R32G32B32A32_SFLOAT, framebufferIndex); + VkRenderPass newRp = + PatchRenderPass(state, multiview, VK_FORMAT_R32G32B32A32_SFLOAT, framebufferIndex); + PatchFramebuffer(state, newRp, m_CallbackInfo.subImageView, VK_FORMAT_R32G32B32A32_SFLOAT, + framebufferIndex); - VkFramebuffer newFb = - CreateFramebuffer(state, newRp, m_CallbackInfo.subImageView, framebufferIndex); - - Pipelines pipes = CreatePerFragmentPipelines(curPipeline, newRp, eid, 0, colorOutputIndex); + Pipelines pipes = CreatePerFragmentPipelines(curPipeline, newRp, eid, 0, + VK_FORMAT_R32G32B32A32_SFLOAT, colorOutputIndex); for(uint32_t i = 0; i < state.views.size(); i++) { @@ -2276,9 +2443,6 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback state.scissors[i].extent = {2, 2}; } - state.renderPass = GetResID(newRp); - state.SetFramebuffer(m_pDriver, GetResID(newFb)); - VkPipeline pipesIter[2]; pipesIter[0] = pipes.primitiveIdPipe; pipesIter[1] = pipes.shaderOutPipe; @@ -2386,7 +2550,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback m_pDriver->GetCmdRenderState().graphics.pipeline = GetResID(pipesIter[i]); m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState( - m_pDriver, cmd, VulkanRenderState::BindGraphics); + m_pDriver, cmd, VulkanRenderState::BindGraphics, false); // Update stencil reference to the current fragment index, so that we get values // for a single fragment only. @@ -2416,18 +2580,47 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback VkImage depthImage = VK_NULL_HANDLE; VkFormat depthFormat = VK_FORMAT_UNDEFINED; - int32_t depthAtt = rpInfo.subpasses[prevState.subpass].depthstencilAttachment; - if(depthAtt >= 0) + VkImageLayout depthLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if(prevState.dynamicRendering.active) { - ResourceId resId = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[depthAtt]).image; - depthImage = m_pDriver->GetResourceManager()->GetCurrentHandle(resId); - const VulkanCreationInfo::Image &imginfo = m_pDriver->GetDebugManager()->GetImageInfo(resId); - depthFormat = imginfo.format; + VkImageView dsView = state.dynamicRendering.depth.imageView; + depthLayout = state.dynamicRendering.depth.imageLayout; + if(dsView == VK_NULL_HANDLE && state.dynamicRendering.stencil.imageView != VK_NULL_HANDLE) + { + dsView = state.dynamicRendering.stencil.imageView; + depthLayout = state.dynamicRendering.stencil.imageLayout; + } + + if(dsView != VK_NULL_HANDLE) + { + ResourceId resId = m_pDriver->GetDebugManager()->GetImageViewInfo(GetResID(dsView)).image; + depthImage = m_pDriver->GetResourceManager()->GetCurrentHandle(resId); + const VulkanCreationInfo::Image &imginfo = m_pDriver->GetDebugManager()->GetImageInfo(resId); + depthFormat = imginfo.format; + } + } + else + { + const VulkanCreationInfo::RenderPass &rpInfo = + m_pDriver->GetDebugManager()->GetRenderPassInfo(prevState.GetRenderPass()); + const rdcarray &atts = prevState.GetFramebufferAttachments(); + + int32_t depthAtt = rpInfo.subpasses[prevState.subpass].depthstencilAttachment; + if(depthAtt >= 0) + { + ResourceId resId = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[depthAtt]).image; + depthImage = m_pDriver->GetResourceManager()->GetCurrentHandle(resId); + const VulkanCreationInfo::Image &imginfo = m_pDriver->GetDebugManager()->GetImageInfo(resId); + depthFormat = imginfo.format; + depthLayout = rpInfo.subpasses[prevState.subpass].depthLayout; + } } // use the original renderpass and framebuffer attachment - state.renderPass = prevState.renderPass; + state.SetRenderPass(prevState.GetRenderPass()); state.SetFramebuffer(prevState.GetFramebuffer(), prevState.GetFramebufferAttachments()); + state.dynamicRendering = prevState.dynamicRendering; colourCopyParams.srcImage = m_CallbackInfo.targetImage; colourCopyParams.srcImageFormat = m_CallbackInfo.targetImageFormat; @@ -2448,7 +2641,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback // Get post-modification value, use the original framebuffer attachment. state.graphics.pipeline = GetResID(pipes.postModPipe); - state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics); + state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); // Have to reset stencil. VkClearAttachment att = {}; att.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; @@ -2495,7 +2688,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback { CopyPixelParams depthCopyParams = colourCopyParams; depthCopyParams.srcImage = depthImage; - depthCopyParams.srcImageLayout = sub.depthLayout; + depthCopyParams.srcImageLayout = depthLayout; depthCopyParams.srcImageFormat = depthFormat; CopyImagePixel(cmd, depthCopyParams, (fragsProcessed + f) * sizeof(PerFragmentInfo) + offsetof(struct PerFragmentInfo, postMod) + @@ -2507,14 +2700,15 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback fragsProcessed += numFragmentsInEvent; m_pDriver->GetCmdRenderState() = prevState; - m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState(m_pDriver, cmd, - VulkanRenderState::BindGraphics); + m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState( + m_pDriver, cmd, VulkanRenderState::BindGraphics, true); } bool PostDraw(uint32_t eid, VkCommandBuffer cmd) { return false; } void PostRedraw(uint32_t eid, VkCommandBuffer cmd) {} // CreatePerFragmentPipelines for getting per fragment information. Pipelines CreatePerFragmentPipelines(ResourceId pipe, VkRenderPass rp, uint32_t eid, - uint32_t fragmentIndex, uint32_t colorOutputIndex) + uint32_t fragmentIndex, VkFormat colorOutputFormat, + uint32_t colorOutputIndex) { const VulkanCreationInfo::Pipeline &p = m_pDriver->GetDebugManager()->GetPipelineInfo(pipe); VkGraphicsPipelineCreateInfo pipeCreateInfo = {}; @@ -2523,6 +2717,30 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback AddDynamicStates(pipeCreateInfo); + // if RP is null we need to patch the pipeline rendering info + if(rp == VK_NULL_HANDLE) + { + VkPipelineRenderingCreateInfoKHR *dynRenderCreate = + (VkPipelineRenderingCreateInfoKHR *)FindNextStruct( + &pipeCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); + + RDCASSERT(dynRenderCreate); + + // if we're patching color, we know we can safely add a new attachment if needed + if(colorOutputFormat != VK_NULL_HANDLE) + { + if(colorOutputIndex >= dynRenderCreate->colorAttachmentCount) + dynRenderCreate->colorAttachmentCount++; + + RDCASSERT(colorOutputIndex < dynRenderCreate->colorAttachmentCount); + + VkFormat *fmts = (VkFormat *)dynRenderCreate->pColorAttachmentFormats; + fmts[colorOutputIndex] = colorOutputFormat; + } + + dynRenderCreate->depthAttachmentFormat = m_CallbackInfo.dsFormat; + } + VkPipelineDepthStencilStateCreateInfo *ds = (VkPipelineDepthStencilStateCreateInfo *)pipeCreateInfo.pDepthStencilState; diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index 9812c1f69..c7683201f 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -1628,8 +1628,13 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state) uint32_t numViews = 1; + if(state.dynamicRendering.active) { - const VulkanCreationInfo::RenderPass &rp = creationInfo.m_RenderPass[state.renderPass]; + numViews = RDCMAX(numViews, Log2Ceil(state.dynamicRendering.viewMask + 1)); + } + else + { + const VulkanCreationInfo::RenderPass &rp = creationInfo.m_RenderPass[state.GetRenderPass()]; if(state.subpass < rp.subpasses.size()) { @@ -2806,7 +2811,8 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state) m_PostVS.Data[eventId].gsout.idxbufmem = VK_NULL_HANDLE; } - if(!creationInfo.m_RenderPass[state.renderPass].subpasses[state.subpass].multiviews.empty()) + if(state.dynamicRendering.viewMask > 1 || + !creationInfo.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].multiviews.empty()) { RDCWARN("Multipass is active for this draw, no GS/Tess mesh output is available"); return; @@ -2951,7 +2957,8 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state) state.graphics.pipeline = GetResID(pipe); state.SetFramebuffer(m_pDriver, GetResID(fb)); - state.renderPass = GetResID(rp); + state.SetRenderPass(GetResID(rp)); + state.dynamicRendering = VulkanRenderState::DynamicRendering(); state.subpass = 0; state.renderArea.offset.x = 0; state.renderArea.offset.y = 0; @@ -3082,7 +3089,7 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state) // wait for the above fill to finish. DoPipelineBarrier(cmd, 1, &meshbufbarrier); - state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics); + state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); ObjDisp(cmd)->CmdBeginQuery(Unwrap(cmd), Unwrap(m_PostVS.XFBQueryPool), 0, 0); @@ -3137,7 +3144,7 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state) ObjDisp(dev)->CmdResetQueryPool(Unwrap(cmd), Unwrap(m_PostVS.XFBQueryPool), 0, action->numInstances); - state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics); + state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); ActionDescription act = *action; @@ -3329,7 +3336,8 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId, VulkanRenderState state) VulkanCreationInfo &creationInfo = m_pDriver->m_CreationInfo; - if(state.graphics.pipeline == ResourceId() || state.renderPass == ResourceId()) + if(state.graphics.pipeline == ResourceId() || + (state.GetRenderPass() == ResourceId() && !state.dynamicRendering.active)) return; const VulkanCreationInfo::Pipeline &pipeInfo = creationInfo.m_Pipeline[state.graphics.pipeline]; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index ca4c0f99b..0740ca374 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -1514,27 +1514,164 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) ret.colorBlend.blends.clear(); } - if(state.renderPass != ResourceId()) + if(state.dynamicRendering.active) + { + VKPipe::RenderPass &rpState = ret.currentPass.renderpass; + VKPipe::Framebuffer &fbState = ret.currentPass.framebuffer; + const VulkanRenderState::DynamicRendering &dyn = state.dynamicRendering; + + rpState.dynamic = true; + rpState.suspended = dyn.suspended; + rpState.resourceId = ResourceId(); + rpState.subpass = 0; + + fbState.resourceId = ResourceId(); + // dynamic rendering does not provide a framebuffer dimension, it's implicit from the image + // views + fbState.width = 0; + fbState.height = 0; + fbState.layers = dyn.layerCount; + + fbState.attachments.clear(); + rpState.inputAttachments.clear(); + rpState.colorAttachments.clear(); + rpState.resolveAttachments.clear(); + + size_t attIdx = 0; + for(size_t i = 0; i < dyn.color.size(); i++) + { + fbState.attachments.push_back({}); + + ResourceId viewid = GetResID(dyn.color[i].imageView); + + if(viewid != ResourceId()) + { + fbState.attachments.back().viewResourceId = rm->GetOriginalID(viewid); + ret.currentPass.framebuffer.attachments[attIdx].imageResourceId = + rm->GetOriginalID(c.m_ImageView[viewid].image); + + fbState.attachments.back().viewFormat = MakeResourceFormat(c.m_ImageView[viewid].format); + fbState.attachments.back().firstMip = c.m_ImageView[viewid].range.baseMipLevel; + fbState.attachments.back().firstSlice = c.m_ImageView[viewid].range.baseArrayLayer; + fbState.attachments.back().numMips = c.m_ImageView[viewid].range.levelCount; + fbState.attachments.back().numSlices = c.m_ImageView[viewid].range.layerCount; + + Convert(fbState.attachments.back().swizzle, c.m_ImageView[viewid].componentMapping); + } + else + { + fbState.attachments.back().viewResourceId = ResourceId(); + fbState.attachments.back().imageResourceId = ResourceId(); + + fbState.attachments.back().firstMip = 0; + fbState.attachments.back().firstSlice = 0; + fbState.attachments.back().numMips = 1; + fbState.attachments.back().numSlices = 1; + } + + rpState.colorAttachments.push_back(uint32_t(attIdx++)); + + if(dyn.color[i].resolveMode && dyn.color[i].resolveImageView != VK_NULL_HANDLE) + { + fbState.attachments.push_back({}); + + viewid = GetResID(dyn.color[i].resolveImageView); + + fbState.attachments.back().viewResourceId = rm->GetOriginalID(viewid); + ret.currentPass.framebuffer.attachments[attIdx].imageResourceId = + rm->GetOriginalID(c.m_ImageView[viewid].image); + + fbState.attachments.back().viewFormat = MakeResourceFormat(c.m_ImageView[viewid].format); + fbState.attachments.back().firstMip = c.m_ImageView[viewid].range.baseMipLevel; + fbState.attachments.back().firstSlice = c.m_ImageView[viewid].range.baseArrayLayer; + fbState.attachments.back().numMips = c.m_ImageView[viewid].range.levelCount; + fbState.attachments.back().numSlices = c.m_ImageView[viewid].range.layerCount; + + Convert(fbState.attachments.back().swizzle, c.m_ImageView[viewid].componentMapping); + + rpState.resolveAttachments.push_back(uint32_t(attIdx++)); + } + } + + if(dyn.depth.imageView != VK_NULL_HANDLE || dyn.stencil.imageView != VK_NULL_HANDLE) + { + fbState.attachments.push_back({}); + + ResourceId viewid = GetResID(dyn.depth.imageView); + if(dyn.depth.imageView == VK_NULL_HANDLE) + viewid = GetResID(dyn.stencil.imageView); + + fbState.attachments.back().viewResourceId = rm->GetOriginalID(viewid); + ret.currentPass.framebuffer.attachments[attIdx].imageResourceId = + rm->GetOriginalID(c.m_ImageView[viewid].image); + + fbState.attachments.back().viewFormat = MakeResourceFormat(c.m_ImageView[viewid].format); + fbState.attachments.back().firstMip = c.m_ImageView[viewid].range.baseMipLevel; + fbState.attachments.back().firstSlice = c.m_ImageView[viewid].range.baseArrayLayer; + fbState.attachments.back().numMips = c.m_ImageView[viewid].range.levelCount; + fbState.attachments.back().numSlices = c.m_ImageView[viewid].range.layerCount; + + Convert(fbState.attachments.back().swizzle, c.m_ImageView[viewid].componentMapping); + + rpState.depthstencilAttachment = int32_t(attIdx++); + } + else + { + rpState.depthstencilAttachment = -1; + } + + if(dyn.fragmentDensityView != VK_NULL_HANDLE) + { + fbState.attachments.push_back({}); + + ResourceId viewid = GetResID(dyn.fragmentDensityView); + + fbState.attachments.back().viewResourceId = rm->GetOriginalID(viewid); + ret.currentPass.framebuffer.attachments[attIdx].imageResourceId = + rm->GetOriginalID(c.m_ImageView[viewid].image); + + fbState.attachments.back().viewFormat = MakeResourceFormat(c.m_ImageView[viewid].format); + fbState.attachments.back().firstMip = c.m_ImageView[viewid].range.baseMipLevel; + fbState.attachments.back().firstSlice = c.m_ImageView[viewid].range.baseArrayLayer; + fbState.attachments.back().numMips = c.m_ImageView[viewid].range.levelCount; + fbState.attachments.back().numSlices = c.m_ImageView[viewid].range.layerCount; + + Convert(fbState.attachments.back().swizzle, c.m_ImageView[viewid].componentMapping); + + rpState.fragmentDensityAttachment = int32_t(attIdx++); + } + else + { + rpState.fragmentDensityAttachment = -1; + } + + rpState.multiviews.clear(); + for(uint32_t v = 0; v < 32; v++) + { + if(dyn.viewMask & (1 << v)) + rpState.multiviews.push_back(v); + } + } + else if(state.GetRenderPass() != ResourceId()) { // Renderpass - ret.currentPass.renderpass.resourceId = rm->GetOriginalID(state.renderPass); + ret.currentPass.renderpass.dynamic = false; + ret.currentPass.renderpass.resourceId = rm->GetOriginalID(state.GetRenderPass()); ret.currentPass.renderpass.subpass = state.subpass; - if(state.renderPass != ResourceId()) - { - ret.currentPass.renderpass.inputAttachments = - c.m_RenderPass[state.renderPass].subpasses[state.subpass].inputAttachments; - ret.currentPass.renderpass.colorAttachments = - c.m_RenderPass[state.renderPass].subpasses[state.subpass].colorAttachments; - ret.currentPass.renderpass.resolveAttachments = - c.m_RenderPass[state.renderPass].subpasses[state.subpass].resolveAttachments; - ret.currentPass.renderpass.depthstencilAttachment = - c.m_RenderPass[state.renderPass].subpasses[state.subpass].depthstencilAttachment; - ret.currentPass.renderpass.fragmentDensityAttachment = - c.m_RenderPass[state.renderPass].subpasses[state.subpass].fragmentDensityAttachment; - ret.currentPass.renderpass.multiviews = - c.m_RenderPass[state.renderPass].subpasses[state.subpass].multiviews; - } + ret.currentPass.renderpass.inputAttachments = + c.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].inputAttachments; + ret.currentPass.renderpass.colorAttachments = + c.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].colorAttachments; + ret.currentPass.renderpass.resolveAttachments = + c.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].resolveAttachments; + ret.currentPass.renderpass.depthstencilAttachment = + c.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].depthstencilAttachment; + ret.currentPass.renderpass.fragmentDensityAttachment = + c.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].fragmentDensityAttachment; + + ret.currentPass.renderpass.multiviews = + c.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].multiviews; ResourceId fb = state.GetFramebuffer(); diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index c40b37652..a4ff673a9 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -163,6 +163,7 @@ DECL_VKFLAG_EXT(VkSubmit, KHR); DECL_VKFLAG_EXT(VkPipelineStage, 2KHR); DECL_VKFLAG_EXT(VkAccess, 2KHR); DECL_VKFLAG_EXT(VkFormatFeature, 2KHR); +DECL_VKFLAG_EXT(VkRendering, KHR); // serialise a member as flags - cast to the Bits enum for serialisation so the stringification // picks up the bitfield and doesn't treat it as uint32_t. Then we rename the type back to the base @@ -941,6 +942,18 @@ SERIALISE_VK_HANDLES(); /* VK_KHR_driver_properties */ \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, VkPhysicalDeviceDriverProperties) \ \ + /* VK_KHR_dynamic_rendering */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, VkRenderingAttachmentInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, VkRenderingInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, \ + VkPipelineRenderingCreateInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR, \ + VkPhysicalDeviceDynamicRenderingFeaturesKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, \ + VkCommandBufferInheritanceRenderingInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT, \ + VkRenderingFragmentDensityMapAttachmentInfoEXT) \ + \ /* VK_KHR_external_fence_capabilities */ \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, \ VkPhysicalDeviceExternalFenceInfo) \ @@ -1358,6 +1371,8 @@ SERIALISE_VK_HANDLES(); PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR) \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR) \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR) \ + /* Interaction with VK_KHR_dynamic_rendering */ \ + PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR) \ \ /* VK_KHR_pipeline_library */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR) \ @@ -1411,6 +1426,8 @@ SERIALISE_VK_HANDLES(); \ /* VK_NV_framebuffer_mixed_samples */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV) \ + /* Interaction with VK_KHR_dynamic_rendering */ \ + PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV) \ \ /* VK_NV_inherited_viewport_scissor */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV) \ @@ -1485,6 +1502,8 @@ SERIALISE_VK_HANDLES(); \ /* VK_NVX_multiview_per_view_attributes */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX) \ + /* Interaction with VK_KHR_dynamic_rendering */ \ + PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX) \ \ /* VK_QCOM_render_pass_transform */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM) \ @@ -7415,6 +7434,128 @@ void Deserialise(const VkPhysicalDeviceDriverProperties &el) DeserialiseNext(el.pNext); } +template +void DoSerialise(SerialiserType &ser, VkPhysicalDeviceDynamicRenderingFeaturesKHR &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(dynamicRendering); +} + +template <> +void Deserialise(const VkPhysicalDeviceDynamicRenderingFeaturesKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkRenderingFragmentDensityMapAttachmentInfoEXT &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(imageView); + SERIALISE_MEMBER(imageLayout); +} + +template <> +void Deserialise(const VkRenderingFragmentDensityMapAttachmentInfoEXT &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkCommandBufferInheritanceRenderingInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(viewMask); + SERIALISE_MEMBER(colorAttachmentCount); + SERIALISE_MEMBER_ARRAY(pColorAttachmentFormats, colorAttachmentCount); + SERIALISE_MEMBER(depthAttachmentFormat); + SERIALISE_MEMBER(stencilAttachmentFormat); + SERIALISE_MEMBER(rasterizationSamples); +} + +template <> +void Deserialise(const VkCommandBufferInheritanceRenderingInfoKHR &el) +{ + DeserialiseNext(el.pNext); + delete[] el.pColorAttachmentFormats; +} + +template +void DoSerialise(SerialiserType &ser, VkPipelineRenderingCreateInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(viewMask); + SERIALISE_MEMBER(colorAttachmentCount); + SERIALISE_MEMBER_ARRAY(pColorAttachmentFormats, colorAttachmentCount); + SERIALISE_MEMBER(depthAttachmentFormat); + SERIALISE_MEMBER(stencilAttachmentFormat); +} + +template <> +void Deserialise(const VkPipelineRenderingCreateInfoKHR &el) +{ + DeserialiseNext(el.pNext); + delete[] el.pColorAttachmentFormats; +} + +template +void DoSerialise(SerialiserType &ser, VkRenderingAttachmentInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(imageView); + SERIALISE_MEMBER(imageLayout); + SERIALISE_MEMBER(resolveMode); + SERIALISE_MEMBER(resolveImageView); + SERIALISE_MEMBER(resolveImageLayout); + SERIALISE_MEMBER(loadOp); + SERIALISE_MEMBER(storeOp); + SERIALISE_MEMBER(clearValue); +} + +template <> +void Deserialise(const VkRenderingAttachmentInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkRenderingInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_RENDERING_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_VKFLAGS(VkRenderingFlagsKHR, flags).Important(); + SERIALISE_MEMBER(renderArea); + SERIALISE_MEMBER(layerCount); + SERIALISE_MEMBER(viewMask); + SERIALISE_MEMBER(colorAttachmentCount).Important(); + SERIALISE_MEMBER_ARRAY(pColorAttachments, colorAttachmentCount); + SERIALISE_MEMBER_OPT(pDepthAttachment); + SERIALISE_MEMBER_OPT(pStencilAttachment); +} + +template <> +void Deserialise(const VkRenderingInfoKHR &el) +{ + DeserialiseNext(el.pNext); + delete[] el.pColorAttachments; + delete el.pDepthAttachment; + delete el.pStencilAttachment; +} + template void DoSerialise(SerialiserType &ser, VkPhysicalDeviceExternalFenceInfo &el) { @@ -9722,6 +9863,7 @@ INSTANTIATE_SERIALISE_TYPE(VkCalibratedTimestampInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkCommandBufferAllocateInfo); INSTANTIATE_SERIALISE_TYPE(VkCommandBufferBeginInfo); INSTANTIATE_SERIALISE_TYPE(VkCommandBufferInheritanceConditionalRenderingInfoEXT); +INSTANTIATE_SERIALISE_TYPE(VkCommandBufferInheritanceRenderingInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkCommandBufferInheritanceInfo); INSTANTIATE_SERIALISE_TYPE(VkCommandBufferSubmitInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkCommandPoolCreateInfo); @@ -9858,6 +10000,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDescriptorIndexingFeatures) INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDescriptorIndexingProperties) INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDiscardRectanglePropertiesEXT); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDriverProperties); +INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceDynamicRenderingFeaturesKHR); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicStateFeaturesEXT); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceExternalBufferInfo); @@ -9974,6 +10117,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationDepthClipStateCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationLineStateCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationStateCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationStateStreamCreateInfoEXT); +INSTANTIATE_SERIALISE_TYPE(VkPipelineRenderingCreateInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkPipelineSampleLocationsStateCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkPipelineShaderStageCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT); @@ -9994,6 +10138,9 @@ INSTANTIATE_SERIALISE_TYPE(VkQueryPoolPerformanceCreateInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkQueueFamilyGlobalPriorityPropertiesEXT); INSTANTIATE_SERIALISE_TYPE(VkQueueFamilyProperties2); INSTANTIATE_SERIALISE_TYPE(VkRefreshCycleDurationGOOGLE); +INSTANTIATE_SERIALISE_TYPE(VkRenderingAttachmentInfoKHR); +INSTANTIATE_SERIALISE_TYPE(VkRenderingFragmentDensityMapAttachmentInfoEXT); +INSTANTIATE_SERIALISE_TYPE(VkRenderingInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkRenderPassAttachmentBeginInfo); INSTANTIATE_SERIALISE_TYPE(VkRenderPassBeginInfo); INSTANTIATE_SERIALISE_TYPE(VkRenderPassCreateInfo); diff --git a/renderdoc/driver/vulkan/vk_shader_cache.cpp b/renderdoc/driver/vulkan/vk_shader_cache.cpp index 34eddb513..230d2640d 100644 --- a/renderdoc/driver/vulkan/vk_shader_cache.cpp +++ b/renderdoc/driver/vulkan/vk_shader_cache.cpp @@ -878,6 +878,22 @@ void VulkanShaderCache::MakeGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo &p 0, // base pipeline index }; + static VkFormat colFormats[16] = {}; + static VkPipelineRenderingCreateInfoKHR dynRenderCreate = { + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, NULL, pipeInfo.viewMask, 0, colFormats, + }; + + if(pipeInfo.renderpass == ResourceId()) + { + dynRenderCreate.depthAttachmentFormat = pipeInfo.depthFormat; + dynRenderCreate.stencilAttachmentFormat = pipeInfo.depthFormat; + dynRenderCreate.colorAttachmentCount = (uint32_t)pipeInfo.colorFormats.size(); + memcpy(colFormats, pipeInfo.colorFormats.data(), pipeInfo.colorFormats.byteSize()); + + dynRenderCreate.pNext = ret.pNext; + ret.pNext = &dynRenderCreate; + } + static VkPipelineDiscardRectangleStateCreateInfoEXT discardRects = { VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT, }; diff --git a/renderdoc/driver/vulkan/vk_shader_feedback.cpp b/renderdoc/driver/vulkan/vk_shader_feedback.cpp index 68b9f3673..bb4ad95de 100644 --- a/renderdoc/driver/vulkan/vk_shader_feedback.cpp +++ b/renderdoc/driver/vulkan/vk_shader_feedback.cpp @@ -1367,8 +1367,9 @@ void VulkanReplay::FetchShaderFeedback(uint32_t eventId) { m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(graphicsInfo, state.graphics.pipeline); - graphicsInfo.renderPass = - creationInfo.m_RenderPass[GetResID(graphicsInfo.renderPass)].loadRPs[graphicsInfo.subpass]; + if(graphicsInfo.renderPass != VK_NULL_HANDLE) + graphicsInfo.renderPass = + creationInfo.m_RenderPass[GetResID(graphicsInfo.renderPass)].loadRPs[graphicsInfo.subpass]; graphicsInfo.subpass = 0; } @@ -1735,7 +1736,8 @@ void VulkanReplay::FetchShaderFeedback(uint32_t eventId) } else { - modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics); + modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics, + false); m_pDriver->ReplayDraw(cmd, *action); diff --git a/renderdoc/driver/vulkan/vk_shaderdebug.cpp b/renderdoc/driver/vulkan/vk_shaderdebug.cpp index 0c35aba05..330ec8cb3 100644 --- a/renderdoc/driver/vulkan/vk_shaderdebug.cpp +++ b/renderdoc/driver/vulkan/vk_shaderdebug.cpp @@ -3882,7 +3882,12 @@ ShaderDebugTrace *VulkanReplay::DebugVertex(uint32_t eventId, uint32_t vertid, u new VulkanAPIWrapper(m_pDriver, c, VK_SHADER_STAGE_VERTEX_BIT, eventId); // clamp the view index to the number of multiviews, just to be sure - size_t numViews = c.m_RenderPass[state.renderPass].subpasses[state.subpass].multiviews.size(); + size_t numViews; + + if(state.dynamicRendering.active) + numViews = Log2Ceil(state.dynamicRendering.viewMask + 1); + else + numViews = c.m_RenderPass[state.GetRenderPass()].subpasses[state.subpass].multiviews.size(); if(numViews > 1) view = RDCMIN((uint32_t)numViews - 1, view); else @@ -4522,7 +4527,8 @@ ShaderDebugTrace *VulkanReplay::DebugPixel(uint32_t eventId, uint32_t x, uint32_ // wait for the above fill to finish. DoPipelineBarrier(cmd, 1, &feedbackbufBarrier); - modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics); + modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics, + false); m_pDriver->ReplayDraw(cmd, *action); diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp index b41aaa379..928b4b149 100644 --- a/renderdoc/driver/vulkan/vk_state.cpp +++ b/renderdoc/driver/vulkan/vk_state.cpp @@ -35,49 +35,114 @@ VulkanRenderState::VulkanRenderState() } void VulkanRenderState::BeginRenderPassAndApplyState(WrappedVulkan *vk, VkCommandBuffer cmd, - PipelineBinding binding) + PipelineBinding binding, bool obeySuspending) { - RDCASSERT(renderPass != ResourceId()); - - // clear values don't matter as we're using the load renderpass here, that - // has all load ops set to load (as we're doing a partial replay - can't - // just clear the targets that are partially written to). - - VkClearValue empty[16] = {}; - - RDCASSERT(ARRAY_COUNT(empty) >= - vk->GetDebugManager()->GetRenderPassInfo(renderPass).attachments.size()); - - VulkanCreationInfo::Framebuffer fbinfo = vk->GetDebugManager()->GetFramebufferInfo(framebuffer); - - VkRenderPassBeginInfo rpbegin = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - NULL, - Unwrap(vk->GetDebugManager()->GetRenderPassInfo(renderPass).loadRPs[subpass]), - Unwrap(fbinfo.loadFBs[subpass]), - renderArea, - (uint32_t)vk->GetDebugManager()->GetRenderPassInfo(renderPass).attachments.size(), - empty, - }; - - VkRenderPassAttachmentBeginInfo imagelessAttachments = { - VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, - }; - rdcarray imagelessViews; - - if(fbinfo.imageless) + if(dynamicRendering.active) { - rpbegin.pNext = &imagelessAttachments; - imagelessAttachments.attachmentCount = (uint32_t)fbattachments.size(); + VkRenderingInfoKHR info = {}; + info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; - for(size_t i = 0; i < fbattachments.size(); i++) - imagelessViews.push_back( - Unwrap(vk->GetResourceManager()->GetCurrentHandle(fbattachments[i]))); + // for action callbacks that want to stop the renderpass, do something, then start it with + // original state, we need to preserve the suspending flag instead of removing it. For other + // uses, we remove both flags as we're just doing a manual start/stop and we're not in a + // suspended pass + if(obeySuspending) + { + info.flags = dynamicRendering.flags & ~VK_RENDERING_RESUMING_BIT_KHR; + } + else + { + info.flags = dynamicRendering.flags & + ~(VK_RENDERING_RESUMING_BIT_KHR | VK_RENDERING_SUSPENDING_BIT_KHR); + } - imagelessAttachments.pAttachments = imagelessViews.data(); + info.layerCount = dynamicRendering.layerCount; + info.renderArea = renderArea; + info.viewMask = dynamicRendering.viewMask; + + VkRenderingAttachmentInfoKHR depth = dynamicRendering.depth; + info.pDepthAttachment = &depth; + if(depth.imageLayout == VK_IMAGE_LAYOUT_UNDEFINED) + info.pDepthAttachment = NULL; + VkRenderingAttachmentInfoKHR stencil = dynamicRendering.depth; + info.pStencilAttachment = &stencil; + if(stencil.imageLayout == VK_IMAGE_LAYOUT_UNDEFINED) + info.pStencilAttachment = NULL; + + rdcarray color = dynamicRendering.color; + + info.colorAttachmentCount = (uint32_t)color.size(); + info.pColorAttachments = color.data(); + + // patch the load/store actions and unwrap + for(uint32_t i = 0; i < (uint32_t)color.size() + 2; i++) + { + VkRenderingAttachmentInfoKHR *att = (VkRenderingAttachmentInfoKHR *)info.pColorAttachments + i; + + if(i == info.colorAttachmentCount) + att = (VkRenderingAttachmentInfoKHR *)info.pDepthAttachment; + else if(i == info.colorAttachmentCount + 1) + att = (VkRenderingAttachmentInfoKHR *)info.pStencilAttachment; + + if(!att) + continue; + + if(att->loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT) + att->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + + if(att->storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT) + att->storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + att->imageView = Unwrap(att->imageView); + att->resolveImageView = Unwrap(att->resolveImageView); + } + + ObjDisp(cmd)->CmdBeginRenderingKHR(Unwrap(cmd), &info); } + else + { + RDCASSERT(renderPass != ResourceId()); - ObjDisp(cmd)->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE); + // clear values don't matter as we're using the load renderpass here, that + // has all load ops set to load (as we're doing a partial replay - can't + // just clear the targets that are partially written to). + + VkClearValue empty[16] = {}; + + RDCASSERT(ARRAY_COUNT(empty) >= + vk->GetDebugManager()->GetRenderPassInfo(renderPass).attachments.size()); + + VulkanCreationInfo::Framebuffer fbinfo = vk->GetDebugManager()->GetFramebufferInfo(framebuffer); + + VkRenderPassBeginInfo rpbegin = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + NULL, + Unwrap(vk->GetDebugManager()->GetRenderPassInfo(renderPass).loadRPs[subpass]), + Unwrap(fbinfo.loadFBs[subpass]), + renderArea, + (uint32_t)vk->GetDebugManager()->GetRenderPassInfo(renderPass).attachments.size(), + empty, + }; + + VkRenderPassAttachmentBeginInfo imagelessAttachments = { + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, + }; + rdcarray imagelessViews; + + if(fbinfo.imageless) + { + rpbegin.pNext = &imagelessAttachments; + imagelessAttachments.attachmentCount = (uint32_t)fbattachments.size(); + + for(size_t i = 0; i < fbattachments.size(); i++) + imagelessViews.push_back( + Unwrap(vk->GetResourceManager()->GetCurrentHandle(fbattachments[i]))); + + imagelessAttachments.pAttachments = imagelessViews.data(); + } + + ObjDisp(cmd)->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE); + } BindPipeline(vk, cmd, binding, true); @@ -97,7 +162,72 @@ void VulkanRenderState::BeginRenderPassAndApplyState(WrappedVulkan *vk, VkComman void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd) { - ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd)); + if(dynamicRendering.active) + { + if(!dynamicRendering.suspended) + ObjDisp(cmd)->CmdEndRenderingKHR(Unwrap(cmd)); + } + else + { + ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd)); + } +} + +void VulkanRenderState::FinishSuspendedRenderPass(VkCommandBuffer cmd) +{ + if(dynamicRendering.active && dynamicRendering.suspended) + { + VkRenderingInfoKHR info = {}; + info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; + + // still resume the existing pass, but don't suspend again after that + info.flags = dynamicRendering.flags & ~VK_RENDERING_SUSPENDING_BIT_KHR; + + info.layerCount = dynamicRendering.layerCount; + info.renderArea = renderArea; + info.viewMask = dynamicRendering.viewMask; + + VkRenderingAttachmentInfoKHR depth = dynamicRendering.depth; + info.pDepthAttachment = &depth; + if(depth.imageLayout == VK_IMAGE_LAYOUT_UNDEFINED) + info.pDepthAttachment = NULL; + VkRenderingAttachmentInfoKHR stencil = dynamicRendering.depth; + info.pStencilAttachment = &stencil; + if(stencil.imageLayout == VK_IMAGE_LAYOUT_UNDEFINED) + info.pStencilAttachment = NULL; + + rdcarray color = dynamicRendering.color; + + info.colorAttachmentCount = (uint32_t)color.size(); + info.pColorAttachments = color.data(); + + // patch the load/store actions and unwrap + for(uint32_t i = 0; i < (uint32_t)color.size() + 2; i++) + { + VkRenderingAttachmentInfoKHR *att = (VkRenderingAttachmentInfoKHR *)info.pColorAttachments + i; + + if(i == info.colorAttachmentCount) + att = (VkRenderingAttachmentInfoKHR *)info.pDepthAttachment; + else if(i == info.colorAttachmentCount + 1) + att = (VkRenderingAttachmentInfoKHR *)info.pStencilAttachment; + + if(!att) + continue; + + if(att->loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT) + att->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + + if(att->storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT) + att->storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + att->imageView = Unwrap(att->imageView); + att->resolveImageView = Unwrap(att->resolveImageView); + } + + // do nothing, just resume and then end without suspending + ObjDisp(cmd)->CmdBeginRenderingKHR(Unwrap(cmd), &info); + ObjDisp(cmd)->CmdEndRenderingKHR(Unwrap(cmd)); + } } void VulkanRenderState::EndTransformFeedback(WrappedVulkan *vk, VkCommandBuffer cmd) @@ -133,6 +263,13 @@ bool VulkanRenderState::IsConditionalRenderingEnabled() void VulkanRenderState::BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd, PipelineBinding binding, bool subpass0) { + // subpass0 is a patched version of the pipeline created against subpass 0, in case for old style + // renderpasses we need to use a pipeline that was previously in subpass 1 against our loadrp with + // only one subpass. It's not needed for dynamic rendering, we can always use the original + // pipeline + if(subpass0 && dynamicRendering.active) + subpass0 = false; + if(binding == BindGraphics || binding == BindInitial) { bool dynamicStates[VkDynamicCount] = {}; diff --git a/renderdoc/driver/vulkan/vk_state.h b/renderdoc/driver/vulkan/vk_state.h index 487663598..3b7dc6248 100644 --- a/renderdoc/driver/vulkan/vk_state.h +++ b/renderdoc/driver/vulkan/vk_state.h @@ -56,7 +56,8 @@ struct VulkanRenderState VulkanRenderState(); bool IsConditionalRenderingEnabled(); - void BeginRenderPassAndApplyState(WrappedVulkan *vk, VkCommandBuffer cmd, PipelineBinding binding); + void BeginRenderPassAndApplyState(WrappedVulkan *vk, VkCommandBuffer cmd, PipelineBinding binding, + bool obeySuspending); void BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd, PipelineBinding binding, bool subpass0); void BindDescriptorSets(WrappedVulkan *vk, VkCommandBuffer cmd, VulkanStatePipeline &pipe, @@ -66,6 +67,7 @@ struct VulkanRenderState VkPipelineBindPoint bindPoint, uint32_t setIndex, uint32_t *dynamicOffsets); void EndRenderPass(VkCommandBuffer cmd); + void FinishSuspendedRenderPass(VkCommandBuffer cmd); void EndTransformFeedback(WrappedVulkan *vk, VkCommandBuffer cmd); @@ -113,7 +115,6 @@ struct VulkanRenderState // the actual number of bytes that have been uploaded uint32_t pushConstSize = 0; - ResourceId renderPass; uint32_t subpass = 0; VkSubpassContents subpassContents; @@ -131,6 +132,14 @@ struct VulkanRenderState const rdcarray &GetFramebufferAttachments() const { return fbattachments; } // + // same for renderpass + void SetRenderPass(ResourceId rp) + { + renderPass = rp; + dynamicRendering = DynamicRendering(); + } + ResourceId GetRenderPass() const { return renderPass; } + bool ActiveRenderPass() const { return renderPass != ResourceId() || dynamicRendering.active; } VkRect2D renderArea = {}; VulkanStatePipeline compute, graphics; @@ -205,7 +214,24 @@ struct VulkanRenderState rdcarray vertexBindings; rdcarray vertexAttributes; + // dynamic rendering + struct DynamicRendering + { + bool active = false; + bool suspended = false; + VkRenderingFlagsKHR flags = 0; + uint32_t layerCount = 0; + uint32_t viewMask = 0; + rdcarray color = {}; + VkRenderingAttachmentInfoKHR depth = {}; + VkRenderingAttachmentInfoKHR stencil = {}; + + VkImageView fragmentDensityView = VK_NULL_HANDLE; + VkImageLayout fragmentDensityLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } dynamicRendering; + private: + ResourceId renderPass; ResourceId framebuffer; rdcarray fbattachments; }; diff --git a/renderdoc/driver/vulkan/vk_stringise.cpp b/renderdoc/driver/vulkan/vk_stringise.cpp index a0da49117..761fed950 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 == 1173, "Chunks changed without updating names"); + RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1175, "Chunks changed without updating names"); BEGIN_ENUM_STRINGISE(VulkanChunk) { @@ -205,6 +205,8 @@ rdcstr DoStringise(const VulkanChunk &el) STRINGISE_ENUM_CLASS(vkCmdSetPrimitiveRestartEnableEXT) STRINGISE_ENUM_CLASS(vkCmdSetRasterizerDiscardEnableEXT) STRINGISE_ENUM_CLASS(vkCmdSetVertexInputEXT) + STRINGISE_ENUM_CLASS(vkCmdBeginRenderingKHR) + STRINGISE_ENUM_CLASS(vkCmdEndRenderingKHR) STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk"); } END_ENUM_STRINGISE() @@ -312,6 +314,10 @@ rdcstr DoStringise(const VkPipelineCreateFlagBits &el) STRINGISE_BITFIELD_BIT(VK_PIPELINE_CREATE_DERIVATIVE_BIT); STRINGISE_BITFIELD_BIT(VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT); STRINGISE_BITFIELD_BIT(VK_PIPELINE_CREATE_DISPATCH_BASE_BIT); + STRINGISE_BITFIELD_BIT( + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR); + STRINGISE_BITFIELD_BIT( + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT); STRINGISE_BITFIELD_BIT(VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR); STRINGISE_BITFIELD_BIT(VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR); STRINGISE_BITFIELD_BIT(VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR); @@ -1230,7 +1236,7 @@ rdcstr DoStringise(const VkAttachmentStoreOp &el) { STRINGISE_ENUM(VK_ATTACHMENT_STORE_OP_STORE) STRINGISE_ENUM(VK_ATTACHMENT_STORE_OP_DONT_CARE) - STRINGISE_ENUM(VK_ATTACHMENT_STORE_OP_NONE_EXT) + STRINGISE_ENUM(VK_ATTACHMENT_STORE_OP_NONE_KHR) } END_ENUM_STRINGISE(); } @@ -1692,6 +1698,15 @@ rdcstr DoStringise(const VkStructureType &el) STRINGISE_ENUM(VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX) STRINGISE_ENUM(VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX) STRINGISE_ENUM(VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_RENDERING_INFO_KHR) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD) + STRINGISE_ENUM(VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX) STRINGISE_ENUM(VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP) STRINGISE_ENUM(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV) STRINGISE_ENUM(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV) @@ -3208,6 +3223,18 @@ rdcstr DoStringise(const VkFormatFeatureFlagBits2KHR &el) END_BITFIELD_STRINGISE(); } +template <> +rdcstr DoStringise(const VkRenderingFlagBitsKHR &el) +{ + BEGIN_BITFIELD_STRINGISE(VkRenderingFlagBitsKHR); + { + STRINGISE_BITFIELD_BIT(VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR); + STRINGISE_BITFIELD_BIT(VK_RENDERING_SUSPENDING_BIT_KHR); + STRINGISE_BITFIELD_BIT(VK_RENDERING_RESUMING_BIT_KHR); + } + END_BITFIELD_STRINGISE(); +} + template <> rdcstr DoStringise(const VkExtent3D &el) { diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index c0be96f52..20e7f4fa3 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -54,7 +54,7 @@ static rdcstr ToHumanStr(const VkAttachmentStoreOp &el) void WrappedVulkan::AddImplicitResolveResourceUsage(uint32_t subpass) { - ResourceId rp = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass; + ResourceId rp = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.GetRenderPass(); const VulkanCreationInfo::RenderPass &rpinfo = m_CreationInfo.m_RenderPass[rp]; // Ending a render pass instance performs any multisample operations @@ -105,14 +105,14 @@ rdcarray WrappedVulkan::GetImplicitRenderPassBarriers(uint if(m_LastCmdBufferID == ResourceId()) { - rp = m_RenderState.renderPass; + rp = m_RenderState.GetRenderPass(); fb = m_RenderState.GetFramebuffer(); fbattachments = m_RenderState.GetFramebufferAttachments(); } else { const VulkanRenderState &renderstate = GetCmdRenderState(); - rp = renderstate.renderPass; + rp = renderstate.GetRenderPass(); fb = renderstate.GetFramebuffer(); fbattachments = renderstate.GetFramebufferAttachments(); } @@ -331,10 +331,113 @@ rdcstr WrappedVulkan::MakeRenderPassOpString(bool store) { rdcstr opDesc = ""; - const VulkanCreationInfo::RenderPass &info = - m_CreationInfo.m_RenderPass[m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass]; + const VulkanRenderState &state = m_BakedCmdBufferInfo[m_LastCmdBufferID].state; + + if(state.dynamicRendering.active) + { + const VulkanRenderState::DynamicRendering &dyn = state.dynamicRendering; + + if(dyn.color.empty() && dyn.depth.imageView == VK_NULL_HANDLE && + dyn.stencil.imageView == VK_NULL_HANDLE) + { + opDesc = "-"; + } + else + { + bool colsame = true; + for(size_t i = 1; i < dyn.color.size(); i++) + { + if(store) + { + if(dyn.color[i].storeOp != dyn.color[0].storeOp) + colsame = false; + } + else + { + if(dyn.color[i].loadOp != dyn.color[0].loadOp) + colsame = false; + } + } + + // handle depth only passes + if(dyn.color.empty()) + { + } + else if(!colsame) + { + // if we have different storage for the colour, don't display + // the full details + + opDesc = store ? "Different store ops" : "Different load ops"; + } + else + { + // all colour ops are the same, print it + opDesc = store ? ToHumanStr(dyn.color[0].storeOp) : ToHumanStr(dyn.color[0].loadOp); + } + + // do we have depth? + if(dyn.depth.imageView != VK_NULL_HANDLE || dyn.stencil.imageView != VK_NULL_HANDLE) + { + // could be empty if this is a depth-only pass + if(!opDesc.empty()) + opDesc = "C=" + opDesc + ", "; + + // if there's no stencil, just print depth op + if(dyn.stencil.imageView == VK_NULL_HANDLE) + { + opDesc += "D=" + (store ? ToHumanStr(dyn.depth.storeOp) : ToHumanStr(dyn.depth.loadOp)); + } + // same for stencil-only + else if(dyn.depth.imageView == VK_NULL_HANDLE) + { + opDesc += "S=" + (store ? ToHumanStr(dyn.stencil.storeOp) : ToHumanStr(dyn.stencil.loadOp)); + } + else + { + if(store) + { + // if depth and stencil have same op, print together, otherwise separately + if(dyn.depth.storeOp == dyn.stencil.storeOp) + opDesc += "DS=" + ToHumanStr(dyn.depth.storeOp); + else + opDesc += + "D=" + ToHumanStr(dyn.depth.storeOp) + ", S=" + ToHumanStr(dyn.stencil.storeOp); + } + else + { + // if depth and stencil have same op, print together, otherwise separately + if(dyn.depth.loadOp == dyn.stencil.loadOp) + opDesc += "DS=" + ToHumanStr(dyn.depth.loadOp); + else + opDesc += "D=" + ToHumanStr(dyn.depth.loadOp) + ", S=" + ToHumanStr(dyn.stencil.loadOp); + } + } + } + } + + // prepend suspend/resume info + if(!store && (dyn.flags & VK_RENDERING_RESUMING_BIT_KHR)) + { + if(opDesc.empty()) + opDesc = "Resume"; + else + opDesc = "Resume, " + opDesc; + } + else if(store && (dyn.flags & VK_RENDERING_SUSPENDING_BIT_KHR)) + { + if(opDesc.empty()) + opDesc = "Suspend"; + else + opDesc = "Suspend, " + opDesc; + } + + return opDesc; + } + + const VulkanCreationInfo::RenderPass &info = m_CreationInfo.m_RenderPass[state.GetRenderPass()]; const VulkanCreationInfo::Framebuffer &fbinfo = - m_CreationInfo.m_Framebuffer[m_BakedCmdBufferInfo[m_LastCmdBufferID].state.GetFramebuffer()]; + m_CreationInfo.m_Framebuffer[state.GetFramebuffer()]; const rdcarray &atts = info.attachments; @@ -346,7 +449,7 @@ rdcstr WrappedVulkan::MakeRenderPassOpString(bool store) { bool colsame = true; - uint32_t subpass = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass; + uint32_t subpass = state.subpass; // find which attachment is the depth-stencil one int32_t dsAttach = info.subpasses[subpass].depthstencilAttachment; @@ -912,8 +1015,8 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman BeginInfo.flags |= VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; if(BeginInfo.pInheritanceInfo->renderPass != VK_NULL_HANDLE) - m_BakedCmdBufferInfo[BakedCommandBuffer].state.renderPass = - GetResID(BeginInfo.pInheritanceInfo->renderPass); + m_BakedCmdBufferInfo[BakedCommandBuffer].state.SetRenderPass( + GetResID(BeginInfo.pInheritanceInfo->renderPass)); if(BeginInfo.pInheritanceInfo->framebuffer != VK_NULL_HANDLE) m_BakedCmdBufferInfo[BakedCommandBuffer].state.SetFramebuffer( this, GetResID(BeginInfo.pInheritanceInfo->framebuffer)); @@ -1133,59 +1236,145 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(SerialiserType &ser, VkCommandB if(m_Partial[Primary].partialParent == BakedCommandBuffer && m_Partial[Primary].renderPassActive) { - uint32_t numSubpasses = - (uint32_t)m_CreationInfo.m_RenderPass[renderstate.renderPass].subpasses.size(); - - // for each subpass we skip, and for the finalLayout transition at the end of the - // renderpass, record these barriers. These are executed implicitly but because we want to - // pretend they never happened, we then reverse their effects so that our layout tracking - // is accurate and the images end up in the layout they were in during the last active - // subpass - rdcflatmap renderPassEndStates; - - for(uint32_t sub = renderstate.subpass + 1; sub < numSubpasses; sub++) + if(renderstate.dynamicRendering.active) { - ObjDisp(commandBuffer)->CmdNextSubpass(Unwrap(commandBuffer), VK_SUBPASS_CONTENTS_INLINE); + // there are two ways dynamic rendering can be active in a partial command buffer - + // either if it's suspended, for which we need to resume and then end without + // suspending. Or if we were partial way in and never saw the end, in which case we need + // to end and then check if that end itself was a suspend, and do a resume/full end. - rdcarray subpassBarriers = GetImplicitRenderPassBarriers(); + bool suspended = renderstate.dynamicRendering.suspended; + + // if we're not suspended, we were inside an active begin/end pair, so end it + if(!suspended) + { + ObjDisp(commandBuffer)->CmdEndRenderingKHR(Unwrap(commandBuffer)); + + // now update the suspended state depending on what was declared when we began + suspended = (renderstate.dynamicRendering.flags & VK_RENDERING_SUSPENDING_BIT_KHR) != 0; + } + + // if we were suspended, or are now suspended after that end, do a quick resume & end + if(suspended) + { + VkRenderingInfoKHR info = {}; + info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; + + // resume but don't suspend - end for real + info.flags = renderstate.dynamicRendering.flags & + ~(VK_RENDERING_RESUMING_BIT_KHR | VK_RENDERING_SUSPENDING_BIT_KHR); + info.flags |= VK_RENDERING_RESUMING_BIT_KHR; + + info.layerCount = renderstate.dynamicRendering.layerCount; + info.renderArea = renderstate.renderArea; + info.viewMask = renderstate.dynamicRendering.viewMask; + + info.pDepthAttachment = &renderstate.dynamicRendering.depth; + if(renderstate.dynamicRendering.depth.imageLayout == VK_IMAGE_LAYOUT_UNDEFINED) + info.pDepthAttachment = NULL; + info.pStencilAttachment = &renderstate.dynamicRendering.stencil; + if(renderstate.dynamicRendering.stencil.imageLayout == VK_IMAGE_LAYOUT_UNDEFINED) + info.pStencilAttachment = NULL; + + info.colorAttachmentCount = (uint32_t)renderstate.dynamicRendering.color.size(); + info.pColorAttachments = renderstate.dynamicRendering.color.data(); + + VkRenderingFragmentDensityMapAttachmentInfoEXT fragmentDensity = { + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT, NULL, + renderstate.dynamicRendering.fragmentDensityView, + renderstate.dynamicRendering.fragmentDensityLayout, + }; + + if(renderstate.dynamicRendering.fragmentDensityView != VK_NULL_HANDLE) + info.pNext = &fragmentDensity; + + byte *tempMem = GetTempMemory(GetNextPatchSize(&info)); + VkRenderingInfoKHR *unwrappedInfo = UnwrapStructAndChain(m_State, tempMem, &info); + + // do the same load/store patching as normal here too + if(m_ReplayOptions.optimisation != ReplayOptimisationLevel::Fastest) + { + for(uint32_t i = 0; i < unwrappedInfo->colorAttachmentCount + 2; i++) + { + VkRenderingAttachmentInfoKHR *att = + (VkRenderingAttachmentInfoKHR *)unwrappedInfo->pColorAttachments + i; + + if(i == unwrappedInfo->colorAttachmentCount) + att = (VkRenderingAttachmentInfoKHR *)unwrappedInfo->pDepthAttachment; + else if(i == unwrappedInfo->colorAttachmentCount + 1) + att = (VkRenderingAttachmentInfoKHR *)unwrappedInfo->pStencilAttachment; + + if(!att) + continue; + + if(att->storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT) + att->storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + if(att->loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE) + att->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + } + } + + ObjDisp(commandBuffer)->CmdBeginRenderingKHR(Unwrap(commandBuffer), unwrappedInfo); + ObjDisp(commandBuffer)->CmdEndRenderingKHR(Unwrap(commandBuffer)); + } + } + else + { + uint32_t numSubpasses = + (uint32_t)m_CreationInfo.m_RenderPass[renderstate.GetRenderPass()].subpasses.size(); + + // for each subpass we skip, and for the finalLayout transition at the end of the + // renderpass, record these barriers. These are executed implicitly but because we want + // to pretend they never happened, we then reverse their effects so that our layout + // tracking is accurate and the images end up in the layout they were in during the last + // active subpass + rdcflatmap renderPassEndStates; + + for(uint32_t sub = renderstate.subpass + 1; sub < numSubpasses; sub++) + { + ObjDisp(commandBuffer)->CmdNextSubpass(Unwrap(commandBuffer), VK_SUBPASS_CONTENTS_INLINE); + + rdcarray subpassBarriers = GetImplicitRenderPassBarriers(); + + GetResourceManager()->RecordBarriers( + renderPassEndStates, FindCommandQueueFamily(m_LastCmdBufferID), + (uint32_t)subpassBarriers.size(), subpassBarriers.data()); + } + + rdcarray finalBarriers = GetImplicitRenderPassBarriers(~0U); GetResourceManager()->RecordBarriers( renderPassEndStates, FindCommandQueueFamily(m_LastCmdBufferID), - (uint32_t)subpassBarriers.size(), subpassBarriers.data()); - } + (uint32_t)finalBarriers.size(), finalBarriers.data()); - rdcarray finalBarriers = GetImplicitRenderPassBarriers(~0U); + ObjDisp(commandBuffer)->CmdEndRenderPass(Unwrap(commandBuffer)); - GetResourceManager()->RecordBarriers(renderPassEndStates, - FindCommandQueueFamily(m_LastCmdBufferID), - (uint32_t)finalBarriers.size(), finalBarriers.data()); + // undo any implicit transitions we just went through, so that we can pretend that the + // image stayed in the same layout as it was when we stopped partially replaying. - ObjDisp(commandBuffer)->CmdEndRenderPass(Unwrap(commandBuffer)); - - // undo any implicit transitions we just went through, so that we can pretend that the - // image stayed in the same layout as it was when we stopped partially replaying. - - for(auto it = renderPassEndStates.begin(); it != renderPassEndStates.end(); ++it) - { - ResourceId id = it->first; - ImageState &endState = it->second; - endState.SetOverlay(); - LockedConstImageStateRef current = FindConstImageState(id); - if(!current) + for(auto it = renderPassEndStates.begin(); it != renderPassEndStates.end(); ++it) { - RDCERR("Unknown image %s", ToStr(id).c_str()); - } - else - { - ImageBarrierSequence barriers; - endState.Transition(*current, VK_ACCESS_ALL_WRITE_BITS, VK_ACCESS_ALL_READ_BITS, - barriers, GetImageTransitionInfo()); - InlineCleanupImageBarriers(commandBuffer, barriers); - if(!barriers.empty()) + ResourceId id = it->first; + ImageState &endState = it->second; + endState.SetOverlay(); + LockedConstImageStateRef current = FindConstImageState(id); + if(!current) { - // This should not happen, because the cleanup barriers are just image layout - // transitions, no queue family transitions - RDCERR("Partial RenderPass replay cleanup barriers could not all be inlined"); + RDCERR("Unknown image %s", ToStr(id).c_str()); + } + else + { + ImageBarrierSequence barriers; + endState.Transition(*current, VK_ACCESS_ALL_WRITE_BITS, VK_ACCESS_ALL_READ_BITS, + barriers, GetImageTransitionInfo()); + InlineCleanupImageBarriers(commandBuffer, barriers); + if(!barriers.empty()) + { + // This should not happen, because the cleanup barriers are just image layout + // transitions, no queue family transitions + RDCERR("Partial RenderPass replay cleanup barriers could not all be inlined"); + } } } } @@ -1352,7 +1541,7 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman { VulkanRenderState &renderstate = GetCmdRenderState(); renderstate.subpass = 0; - renderstate.renderPass = GetResID(RenderPassBegin.renderPass); + renderstate.SetRenderPass(GetResID(RenderPassBegin.renderPass)); renderstate.renderArea = RenderPassBegin.renderArea; renderstate.subpassContents = contents; @@ -1378,7 +1567,7 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman } const VulkanCreationInfo::RenderPass &rpinfo = - m_CreationInfo.m_RenderPass[GetCmdRenderState().renderPass]; + m_CreationInfo.m_RenderPass[GetCmdRenderState().GetRenderPass()]; rdcarray imgBarriers = GetImplicitRenderPassBarriers(); @@ -1547,7 +1736,8 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman // track while reading, for fetching the right set of outputs in AddAction m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass = 0; - m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = GetResID(RenderPassBegin.renderPass); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.SetRenderPass( + GetResID(RenderPassBegin.renderPass)); ResourceId fb = GetResID(RenderPassBegin.framebuffer); @@ -1838,7 +2028,7 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass(SerialiserType &ser, VkCommandB rdcarray attachments; VkRect2D renderArea; const VulkanCreationInfo::RenderPass &rpinfo = - m_CreationInfo.m_RenderPass[GetCmdRenderState().renderPass]; + m_CreationInfo.m_RenderPass[GetCmdRenderState().GetRenderPass()]; { VulkanRenderState &renderstate = GetCmdRenderState(); @@ -1846,7 +2036,7 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass(SerialiserType &ser, VkCommandB attachments = GetCmdRenderState().GetFramebufferAttachments(); renderArea = GetCmdRenderState().renderArea; - renderstate.renderPass = ResourceId(); + renderstate.SetRenderPass(ResourceId()); renderstate.SetFramebuffer(ResourceId(), rdcarray()); renderstate.subpassContents = VK_SUBPASS_CONTENTS_MAX_ENUM; } @@ -1914,7 +2104,7 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass(SerialiserType &ser, VkCommandB // track while reading, reset this to empty so AddAction sets no outputs, // but only AFTER the above AddAction (we want it grouped together) - m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = ResourceId(); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.SetRenderPass(ResourceId()); m_BakedCmdBufferInfo[m_LastCmdBufferID].state.SetFramebuffer(ResourceId(), rdcarray()); } @@ -1996,7 +2186,7 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass2(SerialiserType &ser, { VulkanRenderState &renderstate = GetCmdRenderState(); renderstate.subpass = 0; - renderstate.renderPass = GetResID(RenderPassBegin.renderPass); + renderstate.SetRenderPass(GetResID(RenderPassBegin.renderPass)); renderstate.renderArea = RenderPassBegin.renderArea; renderstate.subpassContents = SubpassBegin.contents; @@ -2022,7 +2212,7 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass2(SerialiserType &ser, } const VulkanCreationInfo::RenderPass &rpinfo = - m_CreationInfo.m_RenderPass[GetCmdRenderState().renderPass]; + m_CreationInfo.m_RenderPass[GetCmdRenderState().GetRenderPass()]; if(m_ReplayOptions.optimisation != ReplayOptimisationLevel::Fastest) { @@ -2173,7 +2363,8 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass2(SerialiserType &ser, // track while reading, for fetching the right set of outputs in AddAction m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass = 0; - m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = GetResID(RenderPassBegin.renderPass); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.SetRenderPass( + GetResID(RenderPassBegin.renderPass)); ResourceId fb = GetResID(RenderPassBegin.framebuffer); @@ -2502,7 +2693,7 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass2(SerialiserType &ser, VkCommand rdcarray attachments; VkRect2D renderArea; const VulkanCreationInfo::RenderPass &rpinfo = - m_CreationInfo.m_RenderPass[GetCmdRenderState().renderPass]; + m_CreationInfo.m_RenderPass[GetCmdRenderState().GetRenderPass()]; { VulkanRenderState &renderstate = GetCmdRenderState(); @@ -2510,7 +2701,7 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass2(SerialiserType &ser, VkCommand attachments = GetCmdRenderState().GetFramebufferAttachments(); renderArea = GetCmdRenderState().renderArea; - renderstate.renderPass = ResourceId(); + renderstate.SetRenderPass(ResourceId()); renderstate.SetFramebuffer(ResourceId(), rdcarray()); renderstate.subpassContents = VK_SUBPASS_CONTENTS_MAX_ENUM; } @@ -2573,7 +2764,7 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass2(SerialiserType &ser, VkCommand // track while reading, reset this to empty so AddAction sets no outputs, // but only AFTER the above AddAction (we want it grouped together) - m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = ResourceId(); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.SetRenderPass(ResourceId()); m_BakedCmdBufferInfo[m_LastCmdBufferID].state.SetFramebuffer(ResourceId(), rdcarray()); } @@ -4253,7 +4444,7 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman parentCmdBufInfo.curEventID++; // should we add framebuffer usage to the child draws. - bool framebufferUsage = parentCmdBufInfo.state.renderPass != ResourceId() && + bool framebufferUsage = parentCmdBufInfo.state.GetRenderPass() != ResourceId() && parentCmdBufInfo.state.GetFramebuffer() != ResourceId(); for(uint32_t c = 0; c < commandBufferCount; c++) @@ -4275,7 +4466,7 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman AddAction(marker); parentCmdBufInfo.curEventID++; - if(m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass == ResourceId() && + if(m_BakedCmdBufferInfo[m_LastCmdBufferID].state.GetRenderPass() == ResourceId() && (cmdBufInfo.beginFlags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { AddDebugMessage( @@ -4298,9 +4489,7 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman for(size_t i = 0; i < numChildren; i++) { AddFramebufferUsageAllChildren( - parentCmdBufInfo.action->children[total - numChildren + i], - parentCmdBufInfo.state.renderPass, parentCmdBufInfo.state.GetFramebuffer(), - parentCmdBufInfo.state.subpass, parentCmdBufInfo.state.GetFramebufferAttachments()); + parentCmdBufInfo.action->children[total - numChildren + i], parentCmdBufInfo.state); } } @@ -4391,7 +4580,7 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman ResourceId cmd = GetResourceManager()->GetOriginalID(GetResID(pCommandBuffers[c])); // propagate renderpass state - m_BakedCmdBufferInfo[cmd].state.renderPass = parentCmdBufInfo.state.renderPass; + m_BakedCmdBufferInfo[cmd].state.SetRenderPass(parentCmdBufInfo.state.GetRenderPass()); m_BakedCmdBufferInfo[cmd].state.subpass = parentCmdBufInfo.state.subpass; m_BakedCmdBufferInfo[cmd].state.SetFramebuffer( parentCmdBufInfo.state.GetFramebuffer(), @@ -6332,6 +6521,7 @@ void WrappedVulkan::vkCmdEndConditionalRenderingEXT(VkCommandBuffer commandBuffe record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } + template bool WrappedVulkan::Serialise_vkCmdSetVertexInputEXT( SerialiserType &ser, VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, @@ -6423,6 +6613,495 @@ void WrappedVulkan::vkCmdSetVertexInputEXT( } } +template +bool WrappedVulkan::Serialise_vkCmdBeginRenderingKHR(SerialiserType &ser, + VkCommandBuffer commandBuffer, + const VkRenderingInfoKHR *pRenderingInfo) +{ + SERIALISE_ELEMENT(commandBuffer); + SERIALISE_ELEMENT_LOCAL(RenderingInfo, *pRenderingInfo).Named("pRenderingInfo"_lit).Important(); + + Serialise_DebugMessages(ser); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer)); + + byte *tempMem = GetTempMemory(GetNextPatchSize(pRenderingInfo)); + VkRenderingInfoKHR *unwrappedInfo = UnwrapStructAndChain(m_State, tempMem, &RenderingInfo); + + if(IsActiveReplaying(m_State)) + { + if(InRerecordRange(m_LastCmdBufferID)) + { + commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); + + // only if we're partially recording do we update this state + if(ShouldUpdateRenderState(m_LastCmdBufferID, true)) + { + m_Partial[Primary].renderPassActive = true; + } + + VulkanRenderState &renderstate = GetCmdRenderState(); + + { + renderstate.subpass = 0; + renderstate.SetRenderPass(ResourceId()); + renderstate.renderArea = RenderingInfo.renderArea; + renderstate.dynamicRendering = VulkanRenderState::DynamicRendering(); + renderstate.dynamicRendering.active = true; + renderstate.dynamicRendering.suspended = false; + renderstate.dynamicRendering.flags = RenderingInfo.flags; + renderstate.dynamicRendering.layerCount = RenderingInfo.layerCount; + renderstate.dynamicRendering.viewMask = RenderingInfo.viewMask; + renderstate.dynamicRendering.color.assign(RenderingInfo.pColorAttachments, + RenderingInfo.colorAttachmentCount); + if(RenderingInfo.pDepthAttachment) + renderstate.dynamicRendering.depth = *RenderingInfo.pDepthAttachment; + if(RenderingInfo.pStencilAttachment) + renderstate.dynamicRendering.stencil = *RenderingInfo.pStencilAttachment; + + VkRenderingFragmentDensityMapAttachmentInfoEXT *fragmentDensityAttachment = + (VkRenderingFragmentDensityMapAttachmentInfoEXT *)FindNextStruct( + &RenderingInfo, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT); + + if(fragmentDensityAttachment) + { + renderstate.dynamicRendering.fragmentDensityView = fragmentDensityAttachment->imageView; + renderstate.dynamicRendering.fragmentDensityLayout = + fragmentDensityAttachment->imageLayout; + } + + rdcarray attachments; + + for(size_t i = 0; i < renderstate.dynamicRendering.color.size(); i++) + attachments.push_back(GetResID(renderstate.dynamicRendering.color[i].imageView)); + + attachments.push_back(GetResID(renderstate.dynamicRendering.depth.imageView)); + attachments.push_back(GetResID(renderstate.dynamicRendering.stencil.imageView)); + + renderstate.SetFramebuffer(ResourceId(), attachments); + } + + // only do discards when not resuming! + if(m_ReplayOptions.optimisation != ReplayOptimisationLevel::Fastest && + (RenderingInfo.flags & VK_RENDERING_RESUMING_BIT_KHR) == 0) + { + 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.loadOp != + renderstate.dynamicRendering.stencil.loadOp)) + { + 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].loadOp == VK_ATTACHMENT_LOAD_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::RenderPassLoad, + image, dynAtts[i].imageLayout, range, + renderstate.renderArea); + } + } + } + + ActionFlags drawFlags = ActionFlags::PassBoundary | ActionFlags::BeginPass; + uint32_t eventId = HandlePreCallback(commandBuffer, drawFlags); + + // do the same load/store op patching that we do for regular renderpass creates to enable + // introspection. It doesn't matter that we don't do this before during load because the + // effects of that are never user-visible. + if(m_ReplayOptions.optimisation != ReplayOptimisationLevel::Fastest) + { + for(uint32_t i = 0; i < unwrappedInfo->colorAttachmentCount + 2; i++) + { + VkRenderingAttachmentInfoKHR *att = + (VkRenderingAttachmentInfoKHR *)unwrappedInfo->pColorAttachments + i; + + if(i == unwrappedInfo->colorAttachmentCount) + att = (VkRenderingAttachmentInfoKHR *)unwrappedInfo->pDepthAttachment; + else if(i == unwrappedInfo->colorAttachmentCount + 1) + att = (VkRenderingAttachmentInfoKHR *)unwrappedInfo->pStencilAttachment; + + if(!att) + continue; + + if(att->storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT) + att->storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + if(att->loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE) + att->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + } + } + + ObjDisp(commandBuffer)->CmdBeginRenderingKHR(Unwrap(commandBuffer), unwrappedInfo); + + if(eventId && m_ActionCallback->PostMisc(eventId, drawFlags, commandBuffer)) + { + // Do not call vkCmdBeginRenderingKHR again. + m_ActionCallback->PostRemisc(eventId, drawFlags, commandBuffer); + } + } + } + else + { + ObjDisp(commandBuffer)->CmdBeginRenderingKHR(Unwrap(commandBuffer), unwrappedInfo); + + VulkanRenderState &renderstate = m_BakedCmdBufferInfo[m_LastCmdBufferID].state; + + { + renderstate.renderArea = RenderingInfo.renderArea; + renderstate.dynamicRendering = VulkanRenderState::DynamicRendering(); + renderstate.dynamicRendering.active = true; + renderstate.dynamicRendering.suspended = false; + renderstate.dynamicRendering.flags = RenderingInfo.flags; + renderstate.dynamicRendering.layerCount = RenderingInfo.layerCount; + renderstate.dynamicRendering.viewMask = RenderingInfo.viewMask; + renderstate.dynamicRendering.color.assign(RenderingInfo.pColorAttachments, + RenderingInfo.colorAttachmentCount); + if(RenderingInfo.pDepthAttachment) + renderstate.dynamicRendering.depth = *RenderingInfo.pDepthAttachment; + if(RenderingInfo.pStencilAttachment) + renderstate.dynamicRendering.stencil = *RenderingInfo.pStencilAttachment; + + VkRenderingFragmentDensityMapAttachmentInfoEXT *fragmentDensityAttachment = + (VkRenderingFragmentDensityMapAttachmentInfoEXT *)FindNextStruct( + &RenderingInfo, VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT); + + if(fragmentDensityAttachment) + { + renderstate.dynamicRendering.fragmentDensityView = fragmentDensityAttachment->imageView; + renderstate.dynamicRendering.fragmentDensityLayout = fragmentDensityAttachment->imageLayout; + } + + rdcarray attachments; + + for(size_t i = 0; i < renderstate.dynamicRendering.color.size(); i++) + attachments.push_back( + m_CreationInfo.m_ImageView[GetResID(renderstate.dynamicRendering.color[i].imageView)].image); + + attachments.push_back( + m_CreationInfo.m_ImageView[GetResID(renderstate.dynamicRendering.depth.imageView)].image); + attachments.push_back( + m_CreationInfo.m_ImageView[GetResID(renderstate.dynamicRendering.stencil.imageView)].image); + + renderstate.SetFramebuffer(ResourceId(), attachments); + } + + AddEvent(); + ActionDescription action; + action.customName = + StringFormat::Fmt("vkCmdBeginRenderingKHR(%s)", MakeRenderPassOpString(false).c_str()); + action.flags |= ActionFlags::PassBoundary | ActionFlags::BeginPass; + + AddAction(action); + } + } + + return true; +} + +void WrappedVulkan::vkCmdBeginRenderingKHR(VkCommandBuffer commandBuffer, + const VkRenderingInfoKHR *pRenderingInfo) +{ + SCOPED_DBG_SINK(); + + byte *tempMem = GetTempMemory(GetNextPatchSize(pRenderingInfo)); + VkRenderingInfoKHR *unwrappedInfo = UnwrapStructAndChain(m_State, tempMem, pRenderingInfo); + + SERIALISE_TIME_CALL( + ObjDisp(commandBuffer)->CmdBeginRenderingKHR(Unwrap(commandBuffer), unwrappedInfo)); + + if(IsCaptureMode(m_State)) + { + VkResourceRecord *record = GetRecord(commandBuffer); + + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginRenderingKHR); + Serialise_vkCmdBeginRenderingKHR(ser, commandBuffer, pRenderingInfo); + + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); + + for(uint32_t i = 0; i < pRenderingInfo->colorAttachmentCount + 2; i++) + { + const VkRenderingAttachmentInfoKHR *att = pRenderingInfo->pColorAttachments + i; + + if(i == pRenderingInfo->colorAttachmentCount) + att = pRenderingInfo->pDepthAttachment; + else if(i == pRenderingInfo->colorAttachmentCount + 1) + att = pRenderingInfo->pStencilAttachment; + + if(!att) + continue; + + FrameRefType refType = eFrameRef_ReadBeforeWrite; + + VkResourceRecord *viewRecord = GetRecord(att->imageView); + const ImageInfo &imInfo = viewRecord->resInfo->imageInfo; + + // if the view covers the whole image + if(viewRecord->viewRange.baseArrayLayer == 0 && viewRecord->viewRange.baseMipLevel == 0 && + viewRecord->viewRange.layerCount() == imInfo.layerCount && + viewRecord->viewRange.levelCount() == imInfo.levelCount && + // and we're rendering to all layers + pRenderingInfo->layerCount == imInfo.layerCount && + // and the render area covers the whole image dimension + pRenderingInfo->renderArea.offset.x == 0 && pRenderingInfo->renderArea.offset.y == 0 && + pRenderingInfo->renderArea.extent.width == imInfo.extent.width && + pRenderingInfo->renderArea.extent.height == imInfo.extent.height) + { + // if we're either clearing or discarding, this can be considered completely written + if(att->loadOp != VK_ATTACHMENT_LOAD_OP_LOAD && att->loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT) + { + refType = eFrameRef_CompleteWrite; + } + } + + // if we're completely writing this resource (i.e. nothing from previous data is visible) and + // it's also DONT_CARE storage (so nothing from this render pass will be visible after) then + // it's completely written and discarded in one go. + if(refType == eFrameRef_CompleteWrite && att->storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE) + { + refType = eFrameRef_CompleteWriteAndDiscard; + } + + record->MarkImageViewFrameReferenced(viewRecord, ImageRange(), refType); + if(att->resolveMode) + record->MarkImageViewFrameReferenced(GetRecord(att->resolveImageView), ImageRange(), refType); + } + } +} + +template +bool WrappedVulkan::Serialise_vkCmdEndRenderingKHR(SerialiserType &ser, VkCommandBuffer commandBuffer) +{ + SERIALISE_ELEMENT(commandBuffer); + + 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(); + + bool suspending = (renderstate.dynamicRendering.flags & VK_RENDERING_SUSPENDING_BIT_KHR) != 0; + + if(ShouldUpdateRenderState(m_LastCmdBufferID, true)) + { + // if this rendering is just being suspended, the pass is still active + if(!suspending) + m_Partial[Primary].renderPassActive = false; + } + + ActionFlags drawFlags = ActionFlags::PassBoundary | ActionFlags::EndPass; + uint32_t eventId = HandlePreCallback(commandBuffer, drawFlags); + + ObjDisp(commandBuffer)->CmdEndRenderingKHR(Unwrap(commandBuffer)); + + if(eventId && m_ActionCallback->PostMisc(eventId, drawFlags, commandBuffer)) + { + // Do not call vkCmdEndRenderingKHR 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 + { + ObjDisp(commandBuffer)->CmdEndRenderingKHR(Unwrap(commandBuffer)); + + // 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_KHR) != 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("vkCmdEndRenderingKHR(%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::vkCmdEndRenderingKHR(VkCommandBuffer commandBuffer) +{ + SCOPED_DBG_SINK(); + + SERIALISE_TIME_CALL(ObjDisp(commandBuffer)->CmdEndRenderingKHR(Unwrap(commandBuffer))); + + if(IsCaptureMode(m_State)) + { + VkResourceRecord *record = GetRecord(commandBuffer); + + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndRenderingKHR); + Serialise_vkCmdEndRenderingKHR(ser, commandBuffer); + + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); + } +} + INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateCommandPool, VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool); @@ -6586,3 +7265,8 @@ INSTANTIATE_FUNCTION_SERIALISED( const VkVertexInputBindingDescription2EXT *pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT *pVertexAttributeDescriptions); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdBeginRenderingKHR, VkCommandBuffer commandBuffer, + const VkRenderingInfoKHR *pRenderingInfo); + +INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdEndRenderingKHR, VkCommandBuffer commandBuffer); diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 577c882a7..e9365e85c 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -2828,6 +2828,13 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi m_DynVertexInput = (ext->vertexInputDynamicState != VK_FALSE); } END_PHYS_EXT_CHECK(); + + BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceDynamicRenderingFeaturesKHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR); + { + CHECK_PHYS_EXT_FEATURE(dynamicRendering); + } + END_PHYS_EXT_CHECK(); } if(availFeatures.depthClamp) diff --git a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp index 08e943700..b25c221b0 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp @@ -161,7 +161,8 @@ bool WrappedVulkan::IsDrawInRenderPass() { BakedCmdBufferInfo &cmd = m_BakedCmdBufferInfo[m_LastCmdBufferID]; - if(cmd.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY && cmd.state.renderPass == ResourceId()) + if(cmd.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY && cmd.state.GetRenderPass() == ResourceId() && + (!cmd.state.dynamicRendering.active || cmd.state.dynamicRendering.suspended)) { // for primary command buffers, we just check the per-command buffer tracked state return false; @@ -2503,9 +2504,9 @@ bool WrappedVulkan::Serialise_vkCmdClearAttachments(SerialiserType &ser, VulkanActionTreeNode &actionNode = GetActionStack().back()->children.back(); const VulkanRenderState &state = m_BakedCmdBufferInfo[m_LastCmdBufferID].state; - if(state.renderPass != ResourceId() && state.GetFramebuffer() != ResourceId()) + if(state.GetRenderPass() != ResourceId() && state.GetFramebuffer() != ResourceId()) { - VulkanCreationInfo::RenderPass &rp = m_CreationInfo.m_RenderPass[state.renderPass]; + VulkanCreationInfo::RenderPass &rp = m_CreationInfo.m_RenderPass[state.GetRenderPass()]; RDCASSERT(state.subpass < rp.subpasses.size()); @@ -2540,6 +2541,34 @@ bool WrappedVulkan::Serialise_vkCmdClearAttachments(SerialiserType &ser, } } } + else if(state.dynamicRendering.active) + { + const VulkanRenderState::DynamicRendering &dyn = state.dynamicRendering; + + for(size_t a = 0; a < dyn.color.size(); a++) + { + actionNode.resourceUsage.push_back( + make_rdcpair(m_CreationInfo.m_ImageView[GetResID(dyn.color[a].imageView)].image, + EventUsage(actionNode.action.eventId, ResourceUsage::Clear, + GetResID(dyn.color[a].imageView)))); + } + + if(dyn.depth.imageView != VK_NULL_HANDLE) + { + actionNode.resourceUsage.push_back( + make_rdcpair(m_CreationInfo.m_ImageView[GetResID(dyn.depth.imageView)].image, + EventUsage(actionNode.action.eventId, ResourceUsage::Clear, + GetResID(dyn.depth.imageView)))); + } + + if(dyn.stencil.imageView != VK_NULL_HANDLE && dyn.depth.imageView != dyn.stencil.imageView) + { + actionNode.resourceUsage.push_back( + make_rdcpair(m_CreationInfo.m_ImageView[GetResID(dyn.stencil.imageView)].image, + EventUsage(actionNode.action.eventId, ResourceUsage::Clear, + GetResID(dyn.stencil.imageView)))); + } + } } } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp index 909bbf607..fa24a0fdf 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp @@ -463,19 +463,23 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines( ResourceId renderPassID = GetResID(CreateInfo.renderPass); - CreateInfo.renderPass = m_CreationInfo.m_RenderPass[renderPassID].loadRPs[CreateInfo.subpass]; - CreateInfo.subpass = 0; + if(CreateInfo.renderPass != VK_NULL_HANDLE) + { + CreateInfo.renderPass = + m_CreationInfo.m_RenderPass[renderPassID].loadRPs[CreateInfo.subpass]; + CreateInfo.subpass = 0; - unwrapped = UnwrapInfos(&CreateInfo, 1); - ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), Unwrap(pipelineCache), 1, - unwrapped, NULL, &pipeInfo.subpass0pipe); - RDCASSERTEQUAL(ret, VK_SUCCESS); + unwrapped = UnwrapInfos(&CreateInfo, 1); + ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), Unwrap(pipelineCache), 1, + unwrapped, NULL, &pipeInfo.subpass0pipe); + RDCASSERTEQUAL(ret, VK_SUCCESS); - ResourceId subpass0id = - GetResourceManager()->WrapResource(Unwrap(device), pipeInfo.subpass0pipe); + ResourceId subpass0id = + GetResourceManager()->WrapResource(Unwrap(device), pipeInfo.subpass0pipe); - // register as a live-only resource, so it is cleaned up properly - GetResourceManager()->AddLiveResource(subpass0id, pipeInfo.subpass0pipe); + // register as a live-only resource, so it is cleaned up properly + GetResourceManager()->AddLiveResource(subpass0id, pipeInfo.subpass0pipe); + } } } @@ -488,8 +492,10 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines( if(CreateInfo.basePipelineHandle != VK_NULL_HANDLE) DerivedResource(CreateInfo.basePipelineHandle, Pipeline); } - DerivedResource(origRP, Pipeline); - DerivedResource(CreateInfo.layout, Pipeline); + if(origRP != VK_NULL_HANDLE) + DerivedResource(origRP, Pipeline); + if(CreateInfo.layout != VK_NULL_HANDLE) + DerivedResource(CreateInfo.layout, Pipeline); for(uint32_t i = 0; i < CreateInfo.stageCount; i++) DerivedResource(CreateInfo.pStages[i].module, Pipeline); } @@ -582,11 +588,17 @@ VkResult WrappedVulkan::vkCreateGraphicsPipelines(VkDevice device, VkPipelineCac record->AddParent(cacherecord); } - VkResourceRecord *rprecord = GetRecord(pCreateInfos[i].renderPass); - record->AddParent(rprecord); + if(pCreateInfos[i].renderPass != VK_NULL_HANDLE) + { + VkResourceRecord *rprecord = GetRecord(pCreateInfos[i].renderPass); + record->AddParent(rprecord); + } - VkResourceRecord *layoutrecord = GetRecord(pCreateInfos[i].layout); - record->AddParent(layoutrecord); + if(pCreateInfos[i].layout != VK_NULL_HANDLE) + { + VkResourceRecord *layoutrecord = GetRecord(pCreateInfos[i].layout); + record->AddParent(layoutrecord); + } for(uint32_t s = 0; s < pCreateInfos[i].stageCount; s++) { diff --git a/util/test/demos/3rdparty/volk/volk.c b/util/test/demos/3rdparty/volk/volk.c index 5143d836b..eb6684a82 100644 --- a/util/test/demos/3rdparty/volk/volk.c +++ b/util/test/demos/3rdparty/volk/volk.c @@ -724,6 +724,10 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)load(context, "vkCmdDrawIndexedIndirectCountKHR"); vkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)load(context, "vkCmdDrawIndirectCountKHR"); #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)load(context, "vkCmdBeginRenderingKHR"); + vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)load(context, "vkCmdEndRenderingKHR"); +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_fd) vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)load(context, "vkGetFenceFdKHR"); vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)load(context, "vkImportFenceFdKHR"); @@ -1299,6 +1303,10 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)load(context, "vkCmdDrawIndexedIndirectCountKHR"); table->vkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)load(context, "vkCmdDrawIndirectCountKHR"); #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + table->vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)load(context, "vkCmdBeginRenderingKHR"); + table->vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)load(context, "vkCmdEndRenderingKHR"); +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_fd) table->vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)load(context, "vkGetFenceFdKHR"); table->vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)load(context, "vkImportFenceFdKHR"); @@ -1978,6 +1986,10 @@ PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) +PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; +PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_capabilities) PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; #endif /* defined(VK_KHR_external_fence_capabilities) */ diff --git a/util/test/demos/3rdparty/volk/volk.h b/util/test/demos/3rdparty/volk/volk.h index 4f6af9fcb..c9e3255c3 100644 --- a/util/test/demos/3rdparty/volk/volk.h +++ b/util/test/demos/3rdparty/volk/volk.h @@ -15,7 +15,7 @@ #endif /* VOLK_GENERATE_VERSION_DEFINE */ -#define VOLK_HEADER_VERSION 196 +#define VOLK_HEADER_VERSION 197 /* VOLK_GENERATE_VERSION_DEFINE */ #ifndef VK_NO_PROTOTYPES @@ -506,6 +506,10 @@ struct VolkDeviceTable PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; + PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_fd) PFN_vkGetFenceFdKHR vkGetFenceFdKHR; PFN_vkImportFenceFdKHR vkImportFenceFdKHR; @@ -1177,6 +1181,10 @@ extern PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; extern PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; extern PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) +extern PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; +extern PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_capabilities) extern PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; #endif /* defined(VK_KHR_external_fence_capabilities) */ diff --git a/util/test/demos/vk/official/vulkan/vulkan_core.h b/util/test/demos/vk/official/vulkan/vulkan_core.h index 056deb6ed..a2f4e7717 100644 --- a/util/test/demos/vk/official/vulkan/vulkan_core.h +++ b/util/test/demos/vk/official/vulkan/vulkan_core.h @@ -72,7 +72,7 @@ extern "C" { #define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 196 +#define VK_HEADER_VERSION 197 // Complete version of this file #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 2, VK_HEADER_VERSION) @@ -514,6 +514,15 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT = 1000040007, #endif VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + VK_STRUCTURE_TYPE_RENDERING_INFO_KHR = 1000044000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR = 1000044001, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR = 1000044002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = 1000044003, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = 1000044004, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, @@ -900,6 +909,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD, VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, @@ -1768,8 +1778,9 @@ typedef enum VkAttachmentLoadOp { typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_STORE = 0, VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, - VK_ATTACHMENT_STORE_OP_NONE_EXT = 1000301000, - VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE_EXT, + VK_ATTACHMENT_STORE_OP_NONE_KHR = 1000301000, + VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE_KHR, + VK_ATTACHMENT_STORE_OP_NONE_EXT = VK_ATTACHMENT_STORE_OP_NONE_KHR, VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentStoreOp; @@ -2203,6 +2214,8 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, @@ -6486,6 +6499,116 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" +#define VK_KHR_dynamic_rendering 1 +#define VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION 1 +#define VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME "VK_KHR_dynamic_rendering" + +typedef enum VkRenderingFlagBitsKHR { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = 0x00000001, + VK_RENDERING_SUSPENDING_BIT_KHR = 0x00000002, + VK_RENDERING_RESUMING_BIT_KHR = 0x00000004, + VK_RENDERING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRenderingFlagBitsKHR; +typedef VkFlags VkRenderingFlagsKHR; +typedef struct VkRenderingAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkResolveModeFlagBits resolveMode; + VkImageView resolveImageView; + VkImageLayout resolveImageLayout; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkClearValue clearValue; +} VkRenderingAttachmentInfoKHR; + +typedef struct VkRenderingInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingFlagsKHR flags; + VkRect2D renderArea; + uint32_t layerCount; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkRenderingAttachmentInfoKHR* pColorAttachments; + const VkRenderingAttachmentInfoKHR* pDepthAttachment; + const VkRenderingAttachmentInfoKHR* pStencilAttachment; +} VkRenderingInfoKHR; + +typedef struct VkPipelineRenderingCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkPipelineRenderingCreateInfoKHR; + +typedef struct VkPhysicalDeviceDynamicRenderingFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRendering; +} VkPhysicalDeviceDynamicRenderingFeaturesKHR; + +typedef struct VkCommandBufferInheritanceRenderingInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingFlagsKHR flags; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; + VkSampleCountFlagBits rasterizationSamples; +} VkCommandBufferInheritanceRenderingInfoKHR; + +typedef struct VkRenderingFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkExtent2D shadingRateAttachmentTexelSize; +} VkRenderingFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkRenderingFragmentDensityMapAttachmentInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; +} VkRenderingFragmentDensityMapAttachmentInfoEXT; + +typedef struct VkAttachmentSampleCountInfoAMD { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const VkSampleCountFlagBits* pColorAttachmentSamples; + VkSampleCountFlagBits depthStencilAttachmentSamples; +} VkAttachmentSampleCountInfoAMD; + +typedef VkAttachmentSampleCountInfoAMD VkAttachmentSampleCountInfoNV; + +typedef struct VkMultiviewPerViewAttributesInfoNVX { + VkStructureType sType; + const void* pNext; + VkBool32 perViewAttributes; + VkBool32 perViewAttributesPositionXOnly; +} VkMultiviewPerViewAttributesInfoNVX; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderingKHR)(VkCommandBuffer commandBuffer, const VkRenderingInfoKHR* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderingKHR)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderingKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInfoKHR* pRenderingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( + VkCommandBuffer commandBuffer); +#endif + + #define VK_KHR_multiview 1 #define VK_KHR_MULTIVIEW_SPEC_VERSION 1 #define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview"