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"