mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-12 21:10:42 +00:00
Patch imageless framebuffer image usage/formats to match image patching
This commit is contained in:
@@ -844,6 +844,9 @@ private:
|
||||
template <class T>
|
||||
T *UnwrapInfos(const T *infos, uint32_t count);
|
||||
|
||||
void PatchAttachment(VkFramebufferAttachmentImageInfo *att, VkFormat imgFormat,
|
||||
VkSampleCountFlagBits samples);
|
||||
|
||||
VkIndirectPatchData FetchIndirectData(VkIndirectPatchType type, VkCommandBuffer commandBuffer,
|
||||
VkBuffer dataBuffer, VkDeviceSize dataOffset, uint32_t count,
|
||||
uint32_t stride = 0, VkBuffer counterBuffer = VK_NULL_HANDLE,
|
||||
|
||||
@@ -162,9 +162,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
|
||||
COPY_STRUCT(VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, VkFenceCreateInfo); \
|
||||
COPY_STRUCT(VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT, \
|
||||
VkFilterCubicImageViewImageFormatPropertiesEXT); \
|
||||
COPY_STRUCT(VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, \
|
||||
VkFramebufferAttachmentsCreateInfo) \
|
||||
COPY_STRUCT(VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, VkFramebufferAttachmentImageInfo) \
|
||||
COPY_STRUCT(VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, VkFormatProperties2); \
|
||||
COPY_STRUCT(VK_STRUCTURE_TYPE_HDR_METADATA_EXT, VkHdrMetadataEXT) \
|
||||
COPY_STRUCT(VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR, VkImageBlit2KHR); \
|
||||
@@ -897,6 +894,32 @@ size_t GetNextPatchSize(const void *pNext)
|
||||
memSize += info->attachmentCount * sizeof(VkImageView);
|
||||
break;
|
||||
}
|
||||
// this struct doesn't really need to be unwrapped but we allocate space for it since it
|
||||
// contains arrays that we will very commonly need to patch, to adjust image info/formats.
|
||||
// this saves us needing to iterate it outside and allocate extra space
|
||||
case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
|
||||
{
|
||||
memSize += sizeof(VkFramebufferAttachmentsCreateInfo);
|
||||
|
||||
VkFramebufferAttachmentsCreateInfo *info = (VkFramebufferAttachmentsCreateInfo *)next;
|
||||
memSize += info->attachmentImageInfoCount * sizeof(VkFramebufferAttachmentImageInfo);
|
||||
|
||||
for(uint32_t i = 0; i < info->attachmentImageInfoCount; i++)
|
||||
memSize += GetNextPatchSize(&info->pAttachmentImageInfos[i]);
|
||||
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO:
|
||||
{
|
||||
memSize += sizeof(VkFramebufferAttachmentImageInfo);
|
||||
|
||||
// we add space for an extra VkFormat so we can push one onto the list
|
||||
VkFramebufferAttachmentImageInfo *info = (VkFramebufferAttachmentImageInfo *)next;
|
||||
if(info->viewFormatCount > 0)
|
||||
memSize += (info->viewFormatCount + 1) * sizeof(VkFormat);
|
||||
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
|
||||
{
|
||||
memSize += sizeof(VkGraphicsPipelineCreateInfo);
|
||||
@@ -1624,6 +1647,56 @@ void UnwrapNextChain(CaptureState state, const char *structName, byte *&tempMem,
|
||||
|
||||
break;
|
||||
}
|
||||
// this struct doesn't really need to be unwrapped but we allocate space for it since it
|
||||
// contains arrays that we will very commonly need to patch, to adjust image info/formats.
|
||||
// this saves us needing to iterate it outside and allocate extra space
|
||||
case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
|
||||
{
|
||||
const VkFramebufferAttachmentsCreateInfo *in =
|
||||
(const VkFramebufferAttachmentsCreateInfo *)nextInput;
|
||||
VkFramebufferAttachmentsCreateInfo *out = (VkFramebufferAttachmentsCreateInfo *)tempMem;
|
||||
|
||||
// append immediately so tempMem is incremented
|
||||
AppendModifiedChainedStruct(tempMem, out, nextChainTail);
|
||||
|
||||
// allocate unwrapped array
|
||||
VkFramebufferAttachmentImageInfo *outAtts = (VkFramebufferAttachmentImageInfo *)tempMem;
|
||||
tempMem += sizeof(VkFramebufferAttachmentImageInfo) * in->attachmentImageInfoCount;
|
||||
|
||||
*out = *in;
|
||||
out->pAttachmentImageInfos = outAtts;
|
||||
for(uint32_t i = 0; i < in->attachmentImageInfoCount; i++)
|
||||
{
|
||||
outAtts[i] = in->pAttachmentImageInfos[i];
|
||||
UnwrapNextChain(state, "VkFramebufferAttachmentImageInfo", tempMem,
|
||||
(VkBaseInStructure *)&outAtts[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO:
|
||||
{
|
||||
const VkFramebufferAttachmentImageInfo *in =
|
||||
(const VkFramebufferAttachmentImageInfo *)nextInput;
|
||||
VkFramebufferAttachmentImageInfo *out = (VkFramebufferAttachmentImageInfo *)tempMem;
|
||||
|
||||
// append immediately so tempMem is incremented
|
||||
AppendModifiedChainedStruct(tempMem, out, nextChainTail);
|
||||
|
||||
*out = *in;
|
||||
|
||||
// allocate extra array
|
||||
if(in->viewFormatCount > 0)
|
||||
{
|
||||
VkFormat *outFormats = (VkFormat *)tempMem;
|
||||
tempMem += sizeof(VkFormat) * (in->viewFormatCount + 1);
|
||||
|
||||
out->pViewFormats = outFormats;
|
||||
memcpy(outFormats, in->pViewFormats, sizeof(VkFormat) * in->viewFormatCount);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
|
||||
{
|
||||
const VkGraphicsPipelineCreateInfo *in = (const VkGraphicsPipelineCreateInfo *)nextInput;
|
||||
@@ -2192,6 +2265,14 @@ void CopyNextChainForPatching(const char *structName, byte *&tempMem, VkBaseInSt
|
||||
case VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO:
|
||||
CopyNextChainedStruct(sizeof(VkFramebufferCreateInfo), tempMem, nextInput, nextChainTail);
|
||||
break;
|
||||
case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
|
||||
CopyNextChainedStruct(sizeof(VkFramebufferAttachmentsCreateInfo), tempMem, nextInput,
|
||||
nextChainTail);
|
||||
break;
|
||||
case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO:
|
||||
CopyNextChainedStruct(sizeof(VkFramebufferAttachmentImageInfo), tempMem, nextInput,
|
||||
nextChainTail);
|
||||
break;
|
||||
case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
|
||||
CopyNextChainedStruct(sizeof(VkGraphicsPipelineCreateInfo), tempMem, nextInput,
|
||||
nextChainTail);
|
||||
|
||||
@@ -3251,6 +3251,8 @@ RenderPassInfo::RenderPassInfo(const VkRenderPassCreateInfo &ci)
|
||||
imageAttachments[i].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
imageAttachments[i].barrier.oldLayout = ci.pAttachments[i].initialLayout;
|
||||
imageAttachments[i].barrier.newLayout = ci.pAttachments[i].finalLayout;
|
||||
imageAttachments[i].format = ci.pAttachments[i].format;
|
||||
imageAttachments[i].samples = ci.pAttachments[i].samples;
|
||||
}
|
||||
|
||||
// VK_KHR_multiview
|
||||
@@ -3383,6 +3385,8 @@ RenderPassInfo::RenderPassInfo(const VkRenderPassCreateInfo2 &ci)
|
||||
imageAttachments[a].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
imageAttachments[a].barrier.oldLayout = ci.pAttachments[i].initialLayout;
|
||||
imageAttachments[a].barrier.newLayout = ci.pAttachments[i].finalLayout;
|
||||
imageAttachments[i].format = ci.pAttachments[i].format;
|
||||
imageAttachments[i].samples = ci.pAttachments[i].samples;
|
||||
|
||||
indexRemapTable[i] = a;
|
||||
|
||||
|
||||
@@ -1147,6 +1147,9 @@ struct AttachmentInfo
|
||||
{
|
||||
VkResourceRecord *record;
|
||||
|
||||
VkFormat format;
|
||||
VkSampleCountFlagBits samples;
|
||||
|
||||
// the implicit barrier applied from initialLayout to finalLayout across a render pass
|
||||
// for render passes this is partial (doesn't contain the image pointer), the image
|
||||
// and subresource range are filled in when creating the framebuffer, which is what is
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "../vk_core.h"
|
||||
#include "../vk_debug.h"
|
||||
|
||||
static void PatchSeparateStencil(VkAttachmentDescription &att, const VkAttachmentReference *ref)
|
||||
{
|
||||
@@ -144,24 +145,6 @@ static void MakeSubpassLoadRP(RPCreateInfo &info, const RPCreateInfo *origInfo,
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
VkFramebufferCreateInfo WrappedVulkan::UnwrapInfo(const VkFramebufferCreateInfo *info)
|
||||
{
|
||||
VkFramebufferCreateInfo ret = *info;
|
||||
|
||||
if((ret.flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT) == 0)
|
||||
{
|
||||
VkImageView *unwrapped = GetTempArray<VkImageView>(info->attachmentCount);
|
||||
for(uint32_t i = 0; i < info->attachmentCount; i++)
|
||||
unwrapped[i] = Unwrap(info->pAttachments[i]);
|
||||
ret.pAttachments = unwrapped;
|
||||
}
|
||||
|
||||
ret.renderPass = Unwrap(ret.renderPass);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// note, for threading reasons we ensure to release the wrappers before
|
||||
// releasing the underlying object. Otherwise after releasing the vulkan object
|
||||
// that same handle could be returned by create on another thread, and we
|
||||
@@ -653,6 +636,36 @@ VkResult WrappedVulkan::vkCreateSampler(VkDevice device, const VkSamplerCreateIn
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WrappedVulkan::PatchAttachment(VkFramebufferAttachmentImageInfo *att, VkFormat imgFormat,
|
||||
VkSampleCountFlagBits samples)
|
||||
{
|
||||
// this matches the mutations we do to images, so see vkCreateImage
|
||||
att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
att->usage |= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
att->usage &= ~VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
|
||||
|
||||
if(IsYUVFormat(imgFormat))
|
||||
att->flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||
|
||||
if(samples != VK_SAMPLE_COUNT_1_BIT)
|
||||
{
|
||||
att->usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
att->flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||
|
||||
if(!IsDepthOrStencilFormat(imgFormat))
|
||||
{
|
||||
if(GetDebugManager() && GetShaderCache()->IsArray2MSSupported())
|
||||
att->usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
att->usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
att->flags &= ~VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT;
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool WrappedVulkan::Serialise_vkCreateFramebuffer(SerialiserType &ser, VkDevice device,
|
||||
const VkFramebufferCreateInfo *pCreateInfo,
|
||||
@@ -670,8 +683,25 @@ bool WrappedVulkan::Serialise_vkCreateFramebuffer(SerialiserType &ser, VkDevice
|
||||
{
|
||||
VkFramebuffer fb = VK_NULL_HANDLE;
|
||||
|
||||
VkFramebufferCreateInfo unwrapped = UnwrapInfo(&CreateInfo);
|
||||
VkResult ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), &unwrapped, NULL, &fb);
|
||||
byte *tempMem = GetTempMemory(GetNextPatchSize(&CreateInfo));
|
||||
VkFramebufferCreateInfo *unwrappedInfo = UnwrapStructAndChain(m_State, tempMem, &CreateInfo);
|
||||
|
||||
const VulkanCreationInfo::RenderPass &rpinfo =
|
||||
m_CreationInfo.m_RenderPass[GetResID(CreateInfo.renderPass)];
|
||||
|
||||
VkFramebufferAttachmentsCreateInfo *attachmentsInfo =
|
||||
(VkFramebufferAttachmentsCreateInfo *)FindNextStruct(
|
||||
unwrappedInfo, VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO);
|
||||
|
||||
for(uint32_t a = 0; attachmentsInfo && a < attachmentsInfo->attachmentImageInfoCount; a++)
|
||||
{
|
||||
VkFramebufferAttachmentImageInfo *att =
|
||||
(VkFramebufferAttachmentImageInfo *)&attachmentsInfo->pAttachmentImageInfos[a];
|
||||
|
||||
PatchAttachment(att, rpinfo.attachments[a].format, rpinfo.attachments[a].samples);
|
||||
}
|
||||
|
||||
VkResult ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), unwrappedInfo, NULL, &fb);
|
||||
|
||||
if(ret != VK_SUCCESS)
|
||||
{
|
||||
@@ -701,17 +731,14 @@ bool WrappedVulkan::Serialise_vkCreateFramebuffer(SerialiserType &ser, VkDevice
|
||||
VulkanCreationInfo::Framebuffer fbinfo;
|
||||
fbinfo.Init(GetResourceManager(), m_CreationInfo, &CreateInfo);
|
||||
|
||||
const VulkanCreationInfo::RenderPass &rpinfo =
|
||||
m_CreationInfo.m_RenderPass[GetResID(CreateInfo.renderPass)];
|
||||
|
||||
fbinfo.loadFBs.resize(rpinfo.loadRPs.size());
|
||||
|
||||
// create a render pass for each subpass that maintains attachment layouts
|
||||
for(size_t s = 0; s < fbinfo.loadFBs.size(); s++)
|
||||
{
|
||||
unwrapped.renderPass = Unwrap(rpinfo.loadRPs[s]);
|
||||
unwrappedInfo->renderPass = Unwrap(rpinfo.loadRPs[s]);
|
||||
|
||||
ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), &unwrapped, NULL,
|
||||
ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), unwrappedInfo, NULL,
|
||||
&fbinfo.loadFBs[s]);
|
||||
RDCASSERTEQUAL(ret, VK_SUCCESS);
|
||||
|
||||
@@ -761,9 +788,34 @@ VkResult WrappedVulkan::vkCreateFramebuffer(VkDevice device,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkFramebuffer *pFramebuffer)
|
||||
{
|
||||
VkFramebufferCreateInfo unwrapped = UnwrapInfo(pCreateInfo);
|
||||
byte *tempMem = GetTempMemory(GetNextPatchSize(pCreateInfo));
|
||||
VkFramebufferCreateInfo *unwrappedInfo = UnwrapStructAndChain(m_State, tempMem, pCreateInfo);
|
||||
|
||||
VkFramebufferAttachmentsCreateInfo *attachmentsInfo =
|
||||
(VkFramebufferAttachmentsCreateInfo *)FindNextStruct(
|
||||
unwrappedInfo, VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO);
|
||||
|
||||
AttachmentInfo *capAtts = NULL;
|
||||
VulkanCreationInfo::RenderPass::Attachment *replayAtts = NULL;
|
||||
if(IsCaptureMode(m_State))
|
||||
capAtts = GetRecord(pCreateInfo->renderPass)->renderPassInfo->imageAttachments;
|
||||
else
|
||||
replayAtts = m_CreationInfo.m_RenderPass[GetResID(pCreateInfo->renderPass)].attachments.data();
|
||||
|
||||
// this matches the mutations we do to images, so see vkCreateImage
|
||||
for(uint32_t a = 0; attachmentsInfo && a < attachmentsInfo->attachmentImageInfoCount; a++)
|
||||
{
|
||||
VkFramebufferAttachmentImageInfo *att =
|
||||
(VkFramebufferAttachmentImageInfo *)&attachmentsInfo->pAttachmentImageInfos[a];
|
||||
|
||||
if(IsCaptureMode(m_State))
|
||||
PatchAttachment(att, capAtts[a].format, capAtts[a].samples);
|
||||
else
|
||||
PatchAttachment(att, replayAtts[a].format, replayAtts[a].samples);
|
||||
}
|
||||
|
||||
VkResult ret;
|
||||
SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), &unwrapped,
|
||||
SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), unwrappedInfo,
|
||||
pAllocator, pFramebuffer));
|
||||
|
||||
if(ret == VK_SUCCESS)
|
||||
@@ -795,6 +847,8 @@ VkResult WrappedVulkan::vkCreateFramebuffer(VkDevice device,
|
||||
for(uint32_t i = 0, a = 0; i < pCreateInfo->attachmentCount; i++, a++)
|
||||
{
|
||||
fbInfo->imageAttachments[a].barrier = rpInfo->imageAttachments[a].barrier;
|
||||
fbInfo->imageAttachments[a].format = rpInfo->imageAttachments[a].format;
|
||||
fbInfo->imageAttachments[a].samples = rpInfo->imageAttachments[a].samples;
|
||||
|
||||
if((pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT) == 0)
|
||||
{
|
||||
@@ -854,10 +908,10 @@ VkResult WrappedVulkan::vkCreateFramebuffer(VkDevice device,
|
||||
// create a render pass for each subpass that maintains attachment layouts
|
||||
for(size_t s = 0; s < fbinfo.loadFBs.size(); s++)
|
||||
{
|
||||
unwrapped.renderPass = Unwrap(rpinfo.loadRPs[s]);
|
||||
unwrappedInfo->renderPass = Unwrap(rpinfo.loadRPs[s]);
|
||||
|
||||
ret =
|
||||
ObjDisp(device)->CreateFramebuffer(Unwrap(device), &unwrapped, NULL, &fbinfo.loadFBs[s]);
|
||||
ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), unwrappedInfo, NULL,
|
||||
&fbinfo.loadFBs[s]);
|
||||
RDCASSERTEQUAL(ret, VK_SUCCESS);
|
||||
|
||||
ResourceId loadFBid = GetResourceManager()->WrapResource(Unwrap(device), fbinfo.loadFBs[s]);
|
||||
|
||||
@@ -668,6 +668,18 @@ VkResult WrappedVulkan::vkCreateSwapchainKHR(VkDevice device,
|
||||
|
||||
// make sure we can readback to get the screenshot, and render to it for the text overlay
|
||||
createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
// if the surface supports them, add usage bits we don't need to look more like normal images
|
||||
// (which is important when patching imageless framebuffer usage)
|
||||
VkSurfaceCapabilitiesKHR surfCap = {};
|
||||
ObjDisp(m_PhysicalDevice)
|
||||
->GetPhysicalDeviceSurfaceCapabilitiesKHR(Unwrap(m_PhysicalDevice),
|
||||
Unwrap(createInfo.surface), &surfCap);
|
||||
if(surfCap.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
createInfo.imageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
if(surfCap.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||
createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
|
||||
createInfo.surface = Unwrap(createInfo.surface);
|
||||
createInfo.oldSwapchain = Unwrap(createInfo.oldSwapchain);
|
||||
|
||||
|
||||
@@ -174,6 +174,9 @@ void main()
|
||||
Present();
|
||||
}
|
||||
|
||||
vkDeviceWaitIdle(device);
|
||||
vkDestroyFramebuffer(device, fb, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user