Support VK_EXT_custom_resolve extension

This commit is contained in:
Jake Turner
2026-03-02 13:32:19 +00:00
parent 5c63bfa417
commit 3b8f8989be
13 changed files with 413 additions and 26 deletions
+1
View File
@@ -1404,6 +1404,7 @@ enum class VulkanChunk : uint32_t
vkCmdEndRendering2EXT,
SetQueueAnnotation,
SetCommandAnnotation,
vkCmdBeginCustomResolveEXT,
Max,
};
+70 -18
View File
@@ -1119,6 +1119,12 @@ static const VkExtensionProperties supportedExtensions[] = {
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME,
VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION,
},
#ifdef VK_EXT_custom_resolve
{
VK_EXT_CUSTOM_RESOLVE_EXTENSION_NAME,
VK_EXT_CUSTOM_RESOLVE_SPEC_VERSION,
},
#endif
{
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
VK_EXT_DEBUG_MARKER_SPEC_VERSION,
@@ -4921,6 +4927,8 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
return Serialise_vkCmdPushDescriptorSet2(ser, VK_NULL_HANDLE, NULL);
case VulkanChunk::vkCmdPushDescriptorSetWithTemplate2:
return Serialise_vkCmdPushDescriptorSetWithTemplate2(ser, VK_NULL_HANDLE, NULL);
case VulkanChunk::vkCmdBeginCustomResolveEXT:
return Serialise_vkCmdBeginCustomResolveEXT(ser, VK_NULL_HANDLE, NULL);
case VulkanChunk::SetQueueAnnotation:
return Serialise_SetQueueAnnotation(ser, VK_NULL_HANDLE, rdcstr(), eRENDERDOC_AnnotationMax,
@@ -6561,9 +6569,10 @@ void WrappedVulkan::AddFramebufferUsage(VulkanActionTreeNode &actionNode,
uint32_t att = sub.colorAttachments[i];
if(att == VK_ATTACHMENT_UNUSED)
continue;
actionNode.resourceUsage.push_back(
make_rdcpair(c.m_ImageView[fbattachments[att]].image,
EventUsage(e, ResourceUsage::ColorTarget, fbattachments[att])));
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[fbattachments[att]].image,
EventUsage(e, sub.customResolve ? ResourceUsage::ResolveDst : ResourceUsage::ColorTarget,
fbattachments[att])));
}
if(sub.depthstencilAttachment >= 0)
@@ -6584,23 +6593,66 @@ void WrappedVulkan::AddFramebufferUsage(VulkanActionTreeNode &actionNode,
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))));
bool isCustomResolve = renderState.dynamicRendering.beginCustomResolve &&
(dyn.color[i].resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT);
if(!isCustomResolve)
{
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[GetResID(dyn.color[i].imageView)].image,
EventUsage(e, ResourceUsage::ColorTarget, GetResID(dyn.color[i].imageView))));
}
else
{
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[GetResID(dyn.color[i].imageView)].image,
EventUsage(e, ResourceUsage::InputTarget, GetResID(dyn.color[i].imageView))));
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[GetResID(dyn.color[i].resolveImageView)].image,
EventUsage(e, ResourceUsage::ResolveDst, GetResID(dyn.color[i].resolveImageView))));
}
}
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))));
bool isCustomResolve = renderState.dynamicRendering.beginCustomResolve &&
(dyn.depth.resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT);
if(!isCustomResolve)
{
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[GetResID(dyn.depth.imageView)].image,
EventUsage(e, ResourceUsage::DepthStencilTarget, GetResID(dyn.depth.imageView))));
}
else
{
actionNode.resourceUsage.push_back(
make_rdcpair(c.m_ImageView[GetResID(dyn.depth.imageView)].image,
EventUsage(e, ResourceUsage::InputTarget, GetResID(dyn.depth.imageView))));
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[GetResID(dyn.depth.resolveImageView)].image,
EventUsage(e, ResourceUsage::ResolveDst, GetResID(dyn.depth.resolveImageView))));
}
}
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))));
bool isCustomResolve = renderState.dynamicRendering.beginCustomResolve &&
(dyn.stencil.resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT);
if(!isCustomResolve)
{
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[GetResID(dyn.stencil.imageView)].image,
EventUsage(e, ResourceUsage::DepthStencilTarget, GetResID(dyn.stencil.imageView))));
}
else
{
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[GetResID(dyn.stencil.imageView)].image,
EventUsage(e, ResourceUsage::InputTarget, GetResID(dyn.stencil.imageView))));
actionNode.resourceUsage.push_back(make_rdcpair(
c.m_ImageView[GetResID(dyn.stencil.resolveImageView)].image,
EventUsage(e, ResourceUsage::ResolveDst, GetResID(dyn.stencil.resolveImageView))));
}
}
}
}
@@ -6753,10 +6805,10 @@ bool WrappedVulkan::EraseImageState(ResourceId id)
void WrappedVulkan::UpdateImageStates(const rdcflatmap<ResourceId, ImageState> &dstStates)
{
// this function expects the number of updates to be orders of magnitude fewer than the number of
// existing images. If there are a small number of images in total then it doesn't matter much,
// and if there are a large number of images then it's better to do repeated map lookups rather
// than spend time iterating linearly across the map for a sparse set of updates.
// this function expects the number of updates to be orders of magnitude fewer than the number
// of existing images. If there are a small number of images in total then it doesn't matter
// much, and if there are a large number of images then it's better to do repeated map lookups
// rather than spend time iterating linearly across the map for a sparse set of updates.
SCOPED_LOCK(m_ImageStatesLock);
auto dstIt = dstStates.begin();
ImageTransitionInfo info = GetImageTransitionInfo();
@@ -6800,8 +6852,8 @@ void WrappedVulkan::ReplayDraw(VkCommandBuffer cmd, const ActionDescription &act
}
else
{
// otherwise it's a bit more complex, we need to set up a multidraw with the first N draws nop'd
// out and the parameters added into the last one
// otherwise it's a bit more complex, we need to set up a multidraw with the first N draws
// nop'd out and the parameters added into the last one
VkMarkerRegion::Begin(StringFormat::Fmt("ReplayDraw(drawIndex=%u)", action.drawIndex), cmd);
+7
View File
@@ -854,6 +854,9 @@ private:
// vkCmdNextSubpass for valid barrier counting.
int activeSubpass = 0;
// Is custom resolve active : when it is active the resolve target of the colour attachment is the output
bool customResolve;
ResourceId GetPushDescriptorID(VkPipelineBindPoint bindpoint, uint32_t set)
{
return pushDescriptorID[bindpoint == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR ? 2 : bindpoint][set];
@@ -3359,4 +3362,8 @@ public:
// VK_EXT_image_drm_format_modifier
VkResult vkGetImageDrmFormatModifierPropertiesEXT(VkDevice device, VkImage image,
VkImageDrmFormatModifierPropertiesEXT *pProperties);
// VK_EXT_custom_resolve
IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdBeginCustomResolveEXT, VkCommandBuffer commandBuffer,
const VkBeginCustomResolveInfoEXT *pBeginCustomResolveInfo);
};
+8 -2
View File
@@ -559,7 +559,8 @@
DeclExt(KHR_map_memory2); \
DeclExt(KHR_present_wait2); \
DeclExt(EXT_fragment_density_map_offset); \
DeclExt(EXT_image_drm_format_modifier);
DeclExt(EXT_image_drm_format_modifier); \
DeclExt(EXT_custom_resolve);
// for simplicity and since the check itself is platform agnostic,
// these aren't protected in platform defines
@@ -705,7 +706,8 @@
CheckExt(KHR_map_memory2, VK14); \
CheckExt(KHR_present_wait2, VKXX); \
CheckExt(EXT_fragment_density_map_offset, VKXX); \
CheckExt(EXT_image_drm_format_modifier, VKXX);
CheckExt(EXT_image_drm_format_modifier, VKXX); \
CheckExt(EXT_custom_resolve, VKXX);
#define HookInitVulkanInstanceExts_PhysDev() \
HookInitExtension(KHR_surface, GetPhysicalDeviceSurfaceSupportKHR); \
@@ -983,6 +985,7 @@
HookInitPromotedExtension(KHR_dynamic_rendering, CmdBeginRendering, KHR); \
HookInitPromotedExtension(KHR_dynamic_rendering, CmdEndRendering, KHR); \
HookInitExtension(EXT_fragment_density_map_offset, CmdEndRendering2EXT); \
HookInitExtension(EXT_custom_resolve, CmdBeginCustomResolveEXT); \
HookInitPromotedExtension(KHR_dynamic_rendering_local_read, CmdSetRenderingAttachmentLocations, \
KHR); \
HookInitPromotedExtension(KHR_dynamic_rendering_local_read, \
@@ -1110,6 +1113,7 @@
HookInitPromotedExtension(KHR_map_memory2, UnmapMemory2, KHR); \
HookInitExtension(KHR_present_wait2, WaitForPresent2KHR); \
HookInitExtension(EXT_image_drm_format_modifier, GetImageDrmFormatModifierPropertiesEXT); \
HookInitExtension(EXT_custom_resolve, CmdBeginCustomResolveEXT); \
HookInitExtension_Device_Win32(); \
HookInitExtension_Device_Linux(); \
HookInitExtension_Device_Android(); \
@@ -2082,6 +2086,8 @@
pBindDescriptorBufferEmbeddedSamplersInfo); \
HookDefine3(VkResult, vkGetImageDrmFormatModifierPropertiesEXT, VkDevice, device, VkImage, \
image, VkImageDrmFormatModifierPropertiesEXT *, pProperties); \
HookDefine2(void, vkCmdBeginCustomResolveEXT, VkCommandBuffer, commandBuffer, \
const VkBeginCustomResolveInfoEXT *, pBeginCustomResolveInfo); \
HookDefine_Win32(); \
HookDefine_Linux(); \
HookDefine_Android(); \
+23
View File
@@ -1167,6 +1167,15 @@ void VulkanCreationInfo::ShaderObject::Init(VulkanResourceManager *resourceMan,
}
}
const VkCustomResolveCreateInfoEXT *customResInfo =
(const VkCustomResolveCreateInfoEXT *)FindNextStruct(
pCreateInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
if(customResInfo)
{
hasCustomResCreateInfo = true;
customResolve = (customResInfo->customResolve == VK_TRUE);
}
ShaderModuleReflection &reflData = info.m_ShaderModule[id].m_Reflections[key];
reflData.Init(resourceMan, info, id, info.m_ShaderModule[id].spirv, shad.entryPoint,
@@ -1230,6 +1239,18 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan,
depthFormat = VK_FORMAT_UNDEFINED;
stencilFormat = VK_FORMAT_UNDEFINED;
}
const VkCustomResolveCreateInfoEXT *customResInfo =
(const VkCustomResolveCreateInfoEXT *)FindNextStruct(
pCreateInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
if(customResInfo)
{
hasCustomResCreateInfo = true;
customResCreateInfo.customResolve = (customResInfo->customResolve == VK_TRUE);
customResCreateInfo.colorFormats.assign(customResInfo->pColorAttachmentFormats,
customResInfo->colorAttachmentCount);
customResCreateInfo.depthFormat = customResInfo->depthAttachmentFormat;
customResCreateInfo.stencilFormat = customResInfo->stencilAttachmentFormat;
}
dynamicRenderingLocalRead.Init((const VkBaseInStructure *)pCreateInfo);
@@ -2249,6 +2270,7 @@ void VulkanCreationInfo::RenderPass::Init(VulkanResourceManager *resourceMan,
dst.multiviews.push_back(i);
}
}
dst.customResolve = (src.flags & VK_SUBPASS_DESCRIPTION_CUSTOM_RESOLVE_BIT_EXT) != 0;
}
for(uint32_t i = 0; i < pCreateInfo->dependencyCount; i++)
@@ -2415,6 +2437,7 @@ void VulkanCreationInfo::RenderPass::Init(VulkanResourceManager *resourceMan,
if(src.viewMask & (1 << i))
dst.multiviews.push_back(i);
}
dst.customResolve = (src.flags & VK_SUBPASS_DESCRIPTION_CUSTOM_RESOLVE_BIT_EXT) != 0;
}
}
+16
View File
@@ -312,6 +312,16 @@ struct VulkanCreationInfo
VkFormat depthFormat;
VkFormat stencilFormat;
// VkCustomResolveCreateInfoEXT
bool hasCustomResCreateInfo = false;
struct CustomResInfo
{
bool customResolve;
rdcarray<VkFormat> colorFormats;
VkFormat depthFormat;
VkFormat stencilFormat;
} customResCreateInfo;
// VkRenderingAttachmentLocationInfo and VkRenderingInputAttachmentIndexInfo
DynamicRenderingLocalRead dynamicRenderingLocalRead;
@@ -491,6 +501,11 @@ struct VulkanCreationInfo
// 64-bit aligned and with an offset equal to their ID. In other words this is big enough for the max ID
uint32_t virtualSpecialisationByteSize = 0;
// VkCustomResolveCreateInfoEXT
bool hasCustomResCreateInfo = false;
// For Shader Objects only "customResolve" is used
bool customResolve;
rdcarray<DescriptorAccess> staticDescriptorAccess;
};
std::unordered_map<ResourceId, ShaderObject> m_ShaderObject;
@@ -558,6 +573,7 @@ struct VulkanCreationInfo
bool feedbackLoop;
bool tileOnlyMSAAEnable;
bool customResolve;
};
rdcarray<Subpass> subpasses;
+14
View File
@@ -1331,6 +1331,8 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// don't use dynamic rendering
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
// don't use custom resolve
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
if(!state.graphics.shaderObject)
{
@@ -1377,6 +1379,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
state.SetRenderPass(GetResID(m_Overlay.NoDepthRP));
state.subpass = 0;
state.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB));
state.dynamicRendering.beginCustomResolve = false;
state.subpassContents = VK_SUBPASS_CONTENTS_INLINE;
state.dynamicRendering.flags &= ~VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
@@ -1573,6 +1576,8 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// don't use dynamic rendering
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
// don't use custom resolve
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
VkPipelineShaderStageCreateInfo *fragShader = NULL;
for(uint32_t i = 0; i < pipeCreateInfo.stageCount; i++)
@@ -1640,6 +1645,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
state.SetRenderPass(GetResID(m_Overlay.NoDepthRP));
state.subpass = 0;
state.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB));
state.dynamicRendering.beginCustomResolve = false;
state.graphics.pipeline = GetResID(pipe[0]);
state.scissors = prevstate.scissors;
@@ -1929,6 +1935,8 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// don't use dynamic rendering
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
// don't use custom resolve
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
VkPipelineShaderStageCreateInfo *fragShader = NULL;
@@ -1998,6 +2006,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
state.SetRenderPass(GetResID(m_Overlay.NoDepthRP));
state.subpass = 0;
state.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB));
state.dynamicRendering.beginCustomResolve = false;
state.graphics.pipeline = GetResID(pipe[0]);
@@ -2580,6 +2589,8 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// don't use dynamic rendering
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
// don't use custom resolve
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo,
NULL, &passpipe);
@@ -2642,6 +2653,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
state.SetRenderPass(GetResID(m_Overlay.NoDepthRP));
state.subpass = 0;
state.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB));
state.dynamicRendering.beginCustomResolve = false;
state.graphics.pipeline = GetResID(failpipe);
@@ -3621,6 +3633,8 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// don't use dynamic rendering
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
// don't use custom resolve
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
if(pipeCreateInfo.pDynamicState)
{
+14 -1
View File
@@ -1798,6 +1798,9 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
fbState.attachments.push_back({});
ResourceId viewid = GetResID(dyn.color[i].imageView);
if(state.dynamicRendering.beginCustomResolve &&
(dyn.color[i].resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT))
viewid = GetResID(dyn.color[i].resolveImageView);
if(viewid != ResourceId())
{
@@ -1825,7 +1828,9 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
rpState.colorAttachments.push_back(uint32_t(attIdx++));
if(dyn.color[i].resolveMode && dyn.color[i].resolveImageView != VK_NULL_HANDLE)
if((dyn.color[i].resolveMode != VK_RESOLVE_MODE_NONE) &&
!(dyn.color[i].resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT) &&
(dyn.color[i].resolveImageView != VK_NULL_HANDLE))
{
fbState.attachments.push_back({});
@@ -1851,8 +1856,16 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
fbState.attachments.push_back({});
ResourceId viewid = GetResID(dyn.depth.imageView);
if(state.dynamicRendering.beginCustomResolve &&
(dyn.depth.resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT))
viewid = GetResID(dyn.depth.resolveImageView);
if(dyn.depth.imageView == VK_NULL_HANDLE)
{
viewid = GetResID(dyn.stencil.imageView);
if(state.dynamicRendering.beginCustomResolve &&
(dyn.stencil.resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT))
viewid = GetResID(dyn.stencil.resolveImageView);
}
fbState.attachments.back().view = viewid;
ret.currentPass.framebuffer.attachments[attIdx].resource = c.m_ImageView[viewid].image;
@@ -1056,6 +1056,22 @@ void VulkanShaderCache::MakeGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo &p
ret.pNext = &dynRenderCreate;
}
static VkFormat customResColFormats[16] = {};
static VkCustomResolveCreateInfoEXT customResCreate = {
VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT, NULL, VK_FALSE, 0, customResColFormats};
if(pipeInfo.renderpass == ResourceId() && (pipeInfo.hasCustomResCreateInfo))
{
customResCreate.customResolve = pipeInfo.customResCreateInfo.customResolve;
customResCreate.colorAttachmentCount = (uint32_t)pipeInfo.customResCreateInfo.colorFormats.size();
memcpy(customResColFormats, pipeInfo.customResCreateInfo.colorFormats.data(),
pipeInfo.customResCreateInfo.colorFormats.byteSize());
customResCreate.depthAttachmentFormat = pipeInfo.customResCreateInfo.depthFormat;
customResCreate.stencilAttachmentFormat = pipeInfo.customResCreateInfo.stencilFormat;
customResCreate.pNext = ret.pNext;
ret.pNext = &customResCreate;
}
static VkPipelineDiscardRectangleStateCreateInfoEXT discardRects = {
VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT,
};
@@ -1343,5 +1359,20 @@ void VulkanShaderCache::MakeShaderObjectInfo(VkShaderCreateInfoEXT &shadCreateIn
specInfo.pData = specdata.data();
}
static VkCustomResolveCreateInfoEXT customResCreate = {
VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT,
NULL,
VK_FALSE,
0,
NULL,
VK_FORMAT_UNDEFINED,
VK_FORMAT_UNDEFINED,
};
if(shadInfo.hasCustomResCreateInfo)
{
customResCreate.customResolve = shadInfo.customResolve;
customResCreate.pNext = ret.pNext;
ret.pNext = &customResCreate;
}
shadCreateInfo = ret;
}
+25
View File
@@ -42,6 +42,7 @@ struct RenderingInfoStructs
VkRenderingFragmentDensityMapAttachmentInfoEXT fragmentDensity;
VkRenderingFragmentShadingRateAttachmentInfoKHR shadingRate;
VkMultisampledRenderToSingleSampledInfoEXT tileOnlyMSAA;
VkCustomResolveCreateInfoEXT customResolveCreateInfo;
};
void setupRenderingInfo(const VulkanRenderState::DynamicRendering &dynamicRendering,
@@ -133,6 +134,22 @@ void setupRenderingInfo(const VulkanRenderState::DynamicRendering &dynamicRender
structs->tileOnlyMSAA.pNext = info->pNext;
info->pNext = &structs->tileOnlyMSAA;
}
structs->customResolveCreateInfo = {
VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT,
NULL,
dynamicRendering.customResolveCreateInfo.customResolve,
(uint32_t)dynamicRendering.customResolveCreateInfo.colorAttachmentFormats.size(),
dynamicRendering.customResolveCreateInfo.colorAttachmentFormats.data(),
dynamicRendering.customResolveCreateInfo.depthAttachmentFormat,
dynamicRendering.customResolveCreateInfo.stencilAttachmentFormat,
};
if(dynamicRendering.hasCustomResolveCreateInfo)
{
structs->customResolveCreateInfo.pNext = info->pNext;
info->pNext = &structs->customResolveCreateInfo;
}
}
} // namespace
@@ -267,6 +284,14 @@ void VulkanRenderState::BeginRenderPassAndApplyState(WrappedVulkan *vk, VkComman
{
dynamicRendering.localRead.SetInputIndices(cmd);
}
if(dynamicRendering.beginCustomResolve)
{
VkBeginCustomResolveInfoEXT beginInfo;
beginInfo.sType = VK_STRUCTURE_TYPE_BEGIN_CUSTOM_RESOLVE_INFO_EXT;
beginInfo.pNext = VK_NULL_HANDLE;
ObjDisp(cmd)->CmdBeginCustomResolveEXT(Unwrap(cmd), &beginInfo);
}
}
void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd)
+16
View File
@@ -353,6 +353,10 @@ struct VulkanRenderState
localRead = o.localRead;
beginCustomResolve = o.beginCustomResolve;
hasCustomResolveCreateInfo = o.hasCustomResolveCreateInfo;
customResolveCreateInfo = o.customResolveCreateInfo;
// this will deep copy from the incoming object
CopyAttachmentNexts();
@@ -385,6 +389,18 @@ struct VulkanRenderState
// VK_KHR_dynamic_rendering_local_read
DynamicRenderingLocalRead localRead;
// VK_EXT_custom_resolve
bool beginCustomResolve = false;
bool hasCustomResolveCreateInfo = false;
struct CustomResolveCreateInfoEXT
{
bool customResolve = false;
rdcarray<VkFormat> colorAttachmentFormats;
VkFormat depthAttachmentFormat;
VkFormat stencilAttachmentFormat;
} customResolveCreateInfo;
private:
// VK_KHR_unified_image_layouts
rdcarray<VkAttachmentFeedbackLoopInfoEXT> feedbacks;
+2 -1
View File
@@ -28,7 +28,7 @@
template <>
rdcstr DoStringise(const VulkanChunk &el)
{
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1236, "Chunks changed without updating names");
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1237, "Chunks changed without updating names");
BEGIN_ENUM_STRINGISE(VulkanChunk)
{
@@ -266,6 +266,7 @@ rdcstr DoStringise(const VulkanChunk &el)
STRINGISE_ENUM_CLASS(vkCmdSetDescriptorBufferOffsets2EXT)
STRINGISE_ENUM_CLASS(vkCmdPushDescriptorSet2)
STRINGISE_ENUM_CLASS(vkCmdPushDescriptorSetWithTemplate2)
STRINGISE_ENUM_CLASS(vkCmdBeginCustomResolveEXT)
STRINGISE_ENUM_CLASS_NAMED(SetCommandAnnotation, "Internal::SetCommandAnnotation");
STRINGISE_ENUM_CLASS_NAMED(SetQueueAnnotation, "Internal::SetQueueAnnotation");
STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk");
@@ -7685,6 +7685,36 @@ bool WrappedVulkan::Serialise_vkCmdBeginRendering(SerialiserType &ser, VkCommand
renderstate.dynamicRendering.tileOnlyMSAASampleCount = tileOnlyMSAA->rasterizationSamples;
}
renderstate.dynamicRendering.beginCustomResolve = false;
const VkCustomResolveCreateInfoEXT *customResolveCreateInfo =
(const VkCustomResolveCreateInfoEXT *)FindNextStruct(
&RenderingInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
if(customResolveCreateInfo)
{
renderstate.dynamicRendering.hasCustomResolveCreateInfo = true;
renderstate.dynamicRendering.customResolveCreateInfo.customResolve =
(customResolveCreateInfo->customResolve == VK_TRUE);
for(uint32_t i = 0; i < customResolveCreateInfo->colorAttachmentCount; ++i)
{
renderstate.dynamicRendering.customResolveCreateInfo.colorAttachmentFormats.push_back(
customResolveCreateInfo->pColorAttachmentFormats[i]);
}
renderstate.dynamicRendering.customResolveCreateInfo.depthAttachmentFormat =
customResolveCreateInfo->depthAttachmentFormat;
renderstate.dynamicRendering.customResolveCreateInfo.stencilAttachmentFormat =
customResolveCreateInfo->stencilAttachmentFormat;
}
else
{
renderstate.dynamicRendering.hasCustomResolveCreateInfo = false;
renderstate.dynamicRendering.customResolveCreateInfo.customResolve = false;
renderstate.dynamicRendering.customResolveCreateInfo.colorAttachmentFormats.clear();
renderstate.dynamicRendering.customResolveCreateInfo.depthAttachmentFormat =
VK_FORMAT_UNDEFINED;
renderstate.dynamicRendering.customResolveCreateInfo.stencilAttachmentFormat =
VK_FORMAT_UNDEFINED;
}
rdcarray<ResourceId> attachments;
for(size_t i = 0; i < renderstate.dynamicRendering.color.size(); i++)
@@ -7875,6 +7905,36 @@ bool WrappedVulkan::Serialise_vkCmdBeginRendering(SerialiserType &ser, VkCommand
renderstate.dynamicRendering.tileOnlyMSAASampleCount = tileOnlyMSAA->rasterizationSamples;
}
renderstate.dynamicRendering.beginCustomResolve = false;
const VkCustomResolveCreateInfoEXT *customResolveCreateInfo =
(const VkCustomResolveCreateInfoEXT *)FindNextStruct(
&RenderingInfo, VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT);
if(customResolveCreateInfo)
{
renderstate.dynamicRendering.hasCustomResolveCreateInfo = true;
renderstate.dynamicRendering.customResolveCreateInfo.customResolve =
(customResolveCreateInfo->customResolve == VK_TRUE);
for(uint32_t i = 0; i < customResolveCreateInfo->colorAttachmentCount; ++i)
{
renderstate.dynamicRendering.customResolveCreateInfo.colorAttachmentFormats.push_back(
customResolveCreateInfo->pColorAttachmentFormats[i]);
}
renderstate.dynamicRendering.customResolveCreateInfo.depthAttachmentFormat =
customResolveCreateInfo->depthAttachmentFormat;
renderstate.dynamicRendering.customResolveCreateInfo.stencilAttachmentFormat =
customResolveCreateInfo->stencilAttachmentFormat;
}
else
{
renderstate.dynamicRendering.hasCustomResolveCreateInfo = false;
renderstate.dynamicRendering.customResolveCreateInfo.customResolve = false;
renderstate.dynamicRendering.customResolveCreateInfo.colorAttachmentFormats.clear();
renderstate.dynamicRendering.customResolveCreateInfo.depthAttachmentFormat =
VK_FORMAT_UNDEFINED;
renderstate.dynamicRendering.customResolveCreateInfo.stencilAttachmentFormat =
VK_FORMAT_UNDEFINED;
}
rdcarray<ResourceId> attachments;
for(size_t i = 0; i < renderstate.dynamicRendering.color.size(); i++)
@@ -8228,8 +8288,8 @@ bool WrappedVulkan::Serialise_vkCmdEndRendering(SerialiserType &ser, VkCommandBu
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)
if((dynAtts[i].resolveMode && !(dynAtts[i].resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT)) &&
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)));
@@ -8516,8 +8576,8 @@ bool WrappedVulkan::Serialise_vkCmdEndRendering2EXT(SerialiserType &ser,
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)
if((dynAtts[i].resolveMode && !(dynAtts[i].resolveMode & VK_RESOLVE_MODE_CUSTOM_BIT_EXT)) &&
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)));
@@ -10326,6 +10386,125 @@ void WrappedVulkan::vkCmdPushDescriptorSetWithTemplate2(
}
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCmdBeginCustomResolveEXT(
SerialiserType &ser, VkCommandBuffer commandBuffer,
const VkBeginCustomResolveInfoEXT *pBeginCustomResolveInfo)
{
SERIALISE_ELEMENT(commandBuffer);
SERIALISE_ELEMENT_OPT(pBeginCustomResolveInfo).Important();
if(IsReplayingAndReading())
{
m_LastCmdBufferID = GetResID(commandBuffer);
if(IsActiveReplaying(m_State))
{
if(InRerecordRange(m_LastCmdBufferID))
{
commandBuffer = RerecordCmdBuf(m_LastCmdBufferID);
ObjDisp(commandBuffer)->CmdBeginCustomResolveEXT(Unwrap(commandBuffer), pBeginCustomResolveInfo);
VulkanRenderState &renderstate = GetCmdRenderState();
renderstate.dynamicRendering.beginCustomResolve = true;
// The resolve images are now the framebuffer not the color images
rdcarray<ResourceId> attachments;
for(size_t i = 0; i < renderstate.dynamicRendering.color.size(); i++)
{
VkRenderingAttachmentInfo &attInfo = renderstate.dynamicRendering.color[i];
ResourceId resolveImageView = GetResID(attInfo.resolveImageView);
attachments.push_back(resolveImageView);
// The resolve images data is undefined and has an implicit store
renderstate.dynamicRendering.color[i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
renderstate.dynamicRendering.color[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
const VulkanCreationInfo::ImageView &viewInfo =
m_CreationInfo.m_ImageView[resolveImageView];
ResourceId imageId = viewInfo.image;
m_BakedCmdBufferInfo[m_LastCmdBufferID].resourceUsage.push_back(
make_rdcpair(imageId, EventUsage(m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID,
ResourceUsage::Discard, resolveImageView)));
if(m_ReplayOptions.optimisation != ReplayOptimisationLevel::Fastest)
{
VkImage image = GetResourceManager()->GetHandle<VkImage>(imageId);
GetDebugManager()->FillWithDiscardPattern(commandBuffer, DiscardType::RenderPassLoad,
image, attInfo.resolveImageLayout,
viewInfo.range, renderstate.renderArea);
}
}
attachments.push_back(GetResID(renderstate.dynamicRendering.depth.resolveImageView));
attachments.push_back(GetResID(renderstate.dynamicRendering.stencil.resolveImageView));
renderstate.SetFramebuffer(ResourceId(), attachments);
}
}
else
{
ObjDisp(commandBuffer)->CmdBeginCustomResolveEXT(Unwrap(commandBuffer), pBeginCustomResolveInfo);
VulkanRenderState &renderstate = m_BakedCmdBufferInfo[m_LastCmdBufferID].state;
renderstate.dynamicRendering.beginCustomResolve = true;
// The resolve images are now the framebuffer not the color images
rdcarray<ResourceId> attachments;
for(size_t i = 0; i < renderstate.dynamicRendering.color.size(); i++)
{
ResourceId resolveImageView =
GetResID(renderstate.dynamicRendering.color[i].resolveImageView);
attachments.push_back(resolveImageView);
// The resolve images data is undefined and has an implicit store
renderstate.dynamicRendering.color[i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
renderstate.dynamicRendering.color[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
ResourceId image = m_CreationInfo.m_ImageView[resolveImageView].image;
m_BakedCmdBufferInfo[m_LastCmdBufferID].resourceUsage.push_back(
make_rdcpair(image, EventUsage(m_BakedCmdBufferInfo[m_LastCmdBufferID].curEventID,
ResourceUsage::Discard, resolveImageView)));
}
attachments.push_back(GetResID(renderstate.dynamicRendering.depth.resolveImageView));
attachments.push_back(GetResID(renderstate.dynamicRendering.stencil.resolveImageView));
renderstate.SetFramebuffer(ResourceId(), attachments);
AddEvent();
ActionDescription action;
action.customName = "vkCmdBeginCustomResolveEXT()";
action.flags |= ActionFlags::PassBoundary | ActionFlags::BeginPass | ActionFlags::EndPass;
AddAction(action);
}
}
return true;
}
void WrappedVulkan::vkCmdBeginCustomResolveEXT(
VkCommandBuffer commandBuffer, const VkBeginCustomResolveInfoEXT *pBeginCustomResolveInfo)
{
SCOPED_DBG_SINK();
SERIALISE_TIME_CALL(
ObjDisp(commandBuffer)->CmdBeginCustomResolveEXT(Unwrap(commandBuffer), pBeginCustomResolveInfo));
if(IsCaptureMode(m_State))
{
VkResourceRecord *record = GetRecord(commandBuffer);
CACHE_THREAD_SERIALISER();
ser.SetActionChunk();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginCustomResolveEXT);
Serialise_vkCmdBeginCustomResolveEXT(ser, commandBuffer, pBeginCustomResolveInfo);
record->AddChunk(scope.Get(&record->cmdInfo->alloc));
}
}
INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateCommandPool, VkDevice device,
const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *, VkCommandPool *pCommandPool);
@@ -10553,3 +10732,6 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdPushDescriptorSet2, VkCommandBuffer c
INSTANTIATE_FUNCTION_SERIALISED(
void, vkCmdPushDescriptorSetWithTemplate2, VkCommandBuffer commandBuffer,
const VkPushDescriptorSetWithTemplateInfo *pPushDescriptorSetWithTemplateInfo);
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdBeginCustomResolveEXT, VkCommandBuffer commandBuffer,
const VkBeginCustomResolveInfoEXT *pBeginCustomResolveInfo);