From aa62d20477d67ade0981c6011fcae4d6d687e55a Mon Sep 17 00:00:00 2001 From: Benson Joeris Date: Thu, 6 Jun 2019 14:50:21 -0400 Subject: [PATCH] Vulkan: Make image info available through `ResourceInfo` The image info (layerCount, levelCount, sampleCount, extent, format, type) was previously only available through `ImageLayouts`. This info is now also stored in `ResourceInfo`. Storing this in `ResourceInfo` makes this info easily accessible from `VkResourceRecord`s representing `VkImage`s and `VkImageView`s. This simplifies upcoming changes to the image tracking and avoids the lock protecting the `m_ImageLayouts` map. To simplify this duplication, a new struct `ImageInfo` is added here to hold the image info in both `ResourceInfo` and `ImageLayouts`. Change-Id: I390cbba4c3ce7b0bd6f004521497c21bf4c1e97f --- renderdoc/driver/vulkan/vk_initstate.cpp | 76 ++++++++++--------- renderdoc/driver/vulkan/vk_manager.cpp | 17 +++-- renderdoc/driver/vulkan/vk_rendertexture.cpp | 7 +- renderdoc/driver/vulkan/vk_replay.cpp | 2 +- renderdoc/driver/vulkan/vk_resources.cpp | 14 ++-- renderdoc/driver/vulkan/vk_resources.h | 73 +++++++++++------- renderdoc/driver/vulkan/vk_serialise.cpp | 8 +- .../driver/vulkan/wrappers/vk_draw_funcs.cpp | 8 +- .../vulkan/wrappers/vk_resource_funcs.cpp | 62 ++++++--------- .../driver/vulkan/wrappers/vk_wsi_funcs.cpp | 35 +++++---- 10 files changed, 167 insertions(+), 135 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index a0179147a..cbc55156d 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -97,8 +97,10 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) VkResult vkr = VK_SUCCESS; WrappedVkImage *im = (WrappedVkImage *)res; + const ResourceInfo &resInfo = *im->record->resInfo; + const ImageInfo &imageInfo = resInfo.imageInfo; - if(im->record->resInfo && im->record->resInfo->IsSparse()) + if(resInfo.IsSparse()) { // if the image is sparse we have to do a different kind of initial state prepare, // to serialise out the page mapping. The fetching of memory is also different @@ -133,8 +135,8 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) // must ensure offset remains valid. Must be multiple of block size, or 4, depending on format VkDeviceSize bufAlignment = 4; - if(IsBlockFormat(layout->format)) - bufAlignment = (VkDeviceSize)GetByteSize(1, 1, 1, layout->format, 0); + if(IsBlockFormat(imageInfo.format)) + bufAlignment = (VkDeviceSize)GetByteSize(1, 1, 1, imageInfo.format, 0); VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -147,23 +149,23 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) VkImage arrayIm = VK_NULL_HANDLE; VkImage realim = im->real.As(); - int numLayers = layout->layerCount; + int numLayers = imageInfo.layerCount; - if(layout->sampleCount > 1) + if(imageInfo.sampleCount > 1) { // first decompose to array - numLayers *= layout->sampleCount; + numLayers *= imageInfo.sampleCount; VkImageCreateInfo arrayInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, NULL, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, - VK_IMAGE_TYPE_2D, layout->format, layout->extent, (uint32_t)layout->levelCount, + VK_IMAGE_TYPE_2D, imageInfo.format, imageInfo.extent, (uint32_t)imageInfo.levelCount, (uint32_t)numLayers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 0, NULL, VK_IMAGE_LAYOUT_UNDEFINED, }; - if(IsDepthOrStencilFormat(layout->format)) + if(IsDepthOrStencilFormat(imageInfo.format)) arrayInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; else arrayInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT; @@ -184,13 +186,13 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) // backing the array image only. } - uint32_t planeCount = GetYUVPlaneCount(layout->format); + uint32_t planeCount = GetYUVPlaneCount(imageInfo.format); uint32_t horizontalPlaneShift = 0; uint32_t verticalPlaneShift = 0; if(planeCount > 1) { - switch(layout->format) + switch(imageInfo.format) { case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: @@ -222,11 +224,11 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) } } - VkFormat sizeFormat = GetDepthOnlyFormat(layout->format); + VkFormat sizeFormat = GetDepthOnlyFormat(imageInfo.format); for(int a = 0; a < numLayers; a++) { - for(int m = 0; m < layout->levelCount; m++) + for(int m = 0; m < imageInfo.levelCount; m++) { bufInfo.size = AlignUp(bufInfo.size, bufAlignment); @@ -235,21 +237,21 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) // need to consider each plane aspect separately. We simplify the calculation by just // aligning up the width to a multiple of 4, that ensures each plane will start at a // multiple of 4 because the rowpitch must be a multiple of 4 - bufInfo.size += GetByteSize(AlignUp4(layout->extent.width), layout->extent.height, - layout->extent.depth, sizeFormat, m); + bufInfo.size += GetByteSize(AlignUp4(imageInfo.extent.width), imageInfo.extent.height, + imageInfo.extent.depth, sizeFormat, m); } else { - bufInfo.size += GetByteSize(layout->extent.width, layout->extent.height, - layout->extent.depth, sizeFormat, m); + bufInfo.size += GetByteSize(imageInfo.extent.width, imageInfo.extent.height, + imageInfo.extent.depth, sizeFormat, m); - if(sizeFormat != layout->format) + if(sizeFormat != imageInfo.format) { // if there's stencil and depth, allocate space for stencil bufInfo.size = AlignUp(bufInfo.size, bufAlignment); - bufInfo.size += GetByteSize(layout->extent.width, layout->extent.height, - layout->extent.depth, VK_FORMAT_S8_UINT, m); + bufInfo.size += GetByteSize(imageInfo.extent.width, imageInfo.extent.height, + imageInfo.extent.depth, VK_FORMAT_S8_UINT, m); } } } @@ -284,11 +286,11 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) } VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; - if(IsStencilOnlyFormat(layout->format)) + if(IsStencilOnlyFormat(imageInfo.format)) { aspectFlags = VK_IMAGE_ASPECT_STENCIL_BIT; } - else if(IsDepthOrStencilFormat(layout->format)) + else if(IsDepthOrStencilFormat(imageInfo.format)) { aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; } @@ -311,10 +313,10 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) layout->queueFamilyIndex, m_QueueFamilyIdx, realim, - {aspectFlags, 0, (uint32_t)layout->levelCount, 0, (uint32_t)numLayers}, + {aspectFlags, 0, (uint32_t)imageInfo.levelCount, 0, (uint32_t)numLayers}, }; - if(aspectFlags == VK_IMAGE_ASPECT_DEPTH_BIT && !IsDepthOnlyFormat(layout->format)) + if(aspectFlags == VK_IMAGE_ASPECT_DEPTH_BIT && !IsDepthOnlyFormat(imageInfo.format)) srcimBarrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; // update the real image layout into transfer-source @@ -369,8 +371,9 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) vkr = ObjDisp(d)->EndCommandBuffer(Unwrap(cmd)); RDCASSERTEQUAL(vkr, VK_SUCCESS); - GetDebugManager()->CopyTex2DMSToArray(Unwrap(arrayIm), realim, layout->extent, - layout->layerCount, layout->sampleCount, layout->format); + GetDebugManager()->CopyTex2DMSToArray(Unwrap(arrayIm), realim, imageInfo.extent, + imageInfo.layerCount, imageInfo.sampleCount, + imageInfo.format); cmd = GetNextCmd(); @@ -393,9 +396,9 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) // loop over every slice/mip, copying it to the appropriate point in the buffer for(int a = 0; a < numLayers; a++) { - VkExtent3D extent = layout->extent; + VkExtent3D extent = imageInfo.extent; - for(int m = 0; m < layout->levelCount; m++) + for(int m = 0; m < imageInfo.levelCount; m++) { VkBufferImageCopy region = { 0, @@ -425,8 +428,8 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) region.imageExtent.height >>= verticalPlaneShift; } - bufOffset += GetPlaneByteSize(layout->extent.width, layout->extent.height, - layout->extent.depth, sizeFormat, m, i); + bufOffset += GetPlaneByteSize(imageInfo.extent.width, imageInfo.extent.height, + imageInfo.extent.depth, sizeFormat, m, i); ObjDisp(d)->CmdCopyImageToBuffer(Unwrap(cmd), realim, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Unwrap(dstBuf), @@ -439,13 +442,13 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) region.bufferOffset = bufOffset; - bufOffset += GetByteSize(layout->extent.width, layout->extent.height, - layout->extent.depth, sizeFormat, m); + bufOffset += GetByteSize(imageInfo.extent.width, imageInfo.extent.height, + imageInfo.extent.depth, sizeFormat, m); ObjDisp(d)->CmdCopyImageToBuffer( Unwrap(cmd), realim, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Unwrap(dstBuf), 1, ®ion); - if(sizeFormat != layout->format) + if(sizeFormat != imageInfo.format) { // if we removed stencil from the format, copy that separately now. bufOffset = AlignUp(bufOffset, bufAlignment); @@ -453,8 +456,8 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) region.bufferOffset = bufOffset; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - bufOffset += GetByteSize(layout->extent.width, layout->extent.height, - layout->extent.depth, VK_FORMAT_S8_UINT, m); + bufOffset += GetByteSize(imageInfo.extent.width, imageInfo.extent.height, + imageInfo.extent.depth, VK_FORMAT_S8_UINT, m); ObjDisp(d)->CmdCopyImageToBuffer(Unwrap(cmd), realim, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Unwrap(dstBuf), @@ -470,7 +473,8 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) } RDCASSERTMSG("buffer wasn't sized sufficiently!", bufOffset <= bufInfo.size, bufOffset, - readbackmem.size, layout->extent, layout->format, numLayers, layout->levelCount); + readbackmem.size, imageInfo.extent, imageInfo.format, numLayers, + imageInfo.levelCount); // transfer back to whatever it was srcimBarrier.oldLayout = srcimBarrier.newLayout; @@ -1382,7 +1386,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten { if(initial.tag == VkInitialContents::ClearColorImage) { - VkFormat format = m_ImageLayouts[id].format; + VkFormat format = m_ImageLayouts[id].imageInfo.format; if(IsBlockFormat(format) || IsYUVFormat(format)) { diff --git a/renderdoc/driver/vulkan/vk_manager.cpp b/renderdoc/driver/vulkan/vk_manager.cpp index 5eb883743..f3c653dab 100644 --- a/renderdoc/driver/vulkan/vk_manager.cpp +++ b/renderdoc/driver/vulkan/vk_manager.cpp @@ -210,7 +210,7 @@ void VulkanResourceManager::RecordBarriers(std::vectorsecond.levelCount - t.subresourceRange.baseMipLevel; + nummips = it->second.imageInfo.levelCount - t.subresourceRange.baseMipLevel; else nummips = 1; } @@ -218,7 +218,7 @@ void VulkanResourceManager::RecordBarriers(std::vectorsecond.layerCount - t.subresourceRange.baseArrayLayer; + numslices = it->second.imageInfo.layerCount - t.subresourceRange.baseArrayLayer; else numslices = 1; } @@ -370,9 +370,10 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser, for(auto it = states.begin(); it != states.end(); ++it) { ImageLayouts &layouts = it->second; + const ImageInfo &imageInfo = layouts.imageInfo; if(layouts.subresourceStates.size() > 1 && - layouts.subresourceStates.size() == size_t(layouts.layerCount * layouts.levelCount)) + layouts.subresourceStates.size() == size_t(imageInfo.layerCount * imageInfo.levelCount)) { VkImageLayout layout = layouts.subresourceStates[0].newLayout; @@ -393,8 +394,8 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser, layouts.subresourceStates.end()); layouts.subresourceStates[0].subresourceRange.baseArrayLayer = 0; layouts.subresourceStates[0].subresourceRange.baseMipLevel = 0; - layouts.subresourceStates[0].subresourceRange.layerCount = layouts.layerCount; - layouts.subresourceStates[0].subresourceRange.levelCount = layouts.levelCount; + layouts.subresourceStates[0].subresourceRange.layerCount = imageInfo.layerCount; + layouts.subresourceStates[0].subresourceRange.levelCount = imageInfo.levelCount; } } } @@ -538,12 +539,14 @@ void VulkanResourceManager::ApplyBarriers(uint32_t queueFamilyIndex, if(t.dstQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) stit->second.queueFamilyIndex = queueFamilyIndex; + const ImageInfo &imageInfo = stit->second.imageInfo; + uint32_t nummips = t.subresourceRange.levelCount; uint32_t numslices = t.subresourceRange.layerCount; if(nummips == VK_REMAINING_MIP_LEVELS) - nummips = layouts[id].levelCount; + nummips = imageInfo.levelCount; if(numslices == VK_REMAINING_ARRAY_LAYERS) - numslices = layouts[id].layerCount; + numslices = imageInfo.layerCount; if(nummips == 0) nummips = 1; diff --git a/renderdoc/driver/vulkan/vk_rendertexture.cpp b/renderdoc/driver/vulkan/vk_rendertexture.cpp index 09c8d5169..78e287452 100644 --- a/renderdoc/driver/vulkan/vk_rendertexture.cpp +++ b/renderdoc/driver/vulkan/vk_rendertexture.cpp @@ -164,6 +164,7 @@ bool VulkanReplay::RenderTextureInternal(TextureDisplay cfg, VkRenderPassBeginIn VulkanCreationInfo::Image &iminfo = m_pDriver->m_CreationInfo.m_Image[cfg.resourceId]; TextureDisplayViews &texviews = m_TexRender.TextureViews[cfg.resourceId]; VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle(cfg.resourceId); + const ImageInfo &imageInfo = layouts.imageInfo; CreateTexImageView(liveIm, iminfo, cfg.typeHint, texviews); @@ -189,14 +190,14 @@ bool VulkanReplay::RenderTextureInternal(TextureDisplay cfg, VkRenderPassBeginIn int viewIndex = 0; // if we're displaying the stencil, set up for stencil display - if(layouts.format == VK_FORMAT_S8_UINT || - (IsStencilFormat(layouts.format) && !cfg.red && cfg.green)) + if(imageInfo.format == VK_FORMAT_S8_UINT || + (IsStencilFormat(imageInfo.format) && !cfg.red && cfg.green)) { descSetBinding = 10; displayformat |= TEXDISPLAY_UINT_TEX; // for stencil we use view 1 as long as it's a depth-stencil texture - if(IsDepthAndStencilFormat(layouts.format)) + if(IsDepthAndStencilFormat(imageInfo.format)) viewIndex = 1; // rescale the range so that stencil seems to fit to 0-1 diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 462dd218d..98e0cbfec 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -1788,7 +1788,7 @@ bool VulkanReplay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, { ImageLayouts &layouts = m_pDriver->m_ImageLayouts[texid]; - if(IsDepthAndStencilFormat(layouts.format)) + if(IsDepthAndStencilFormat(layouts.imageInfo.format)) { // for depth/stencil we need to run the code twice - once to fetch depth and once to fetch // stencil - since we can't process float depth and int stencil at the same time diff --git a/renderdoc/driver/vulkan/vk_resources.cpp b/renderdoc/driver/vulkan/vk_resources.cpp index 687ac97aa..66fd69171 100644 --- a/renderdoc/driver/vulkan/vk_resources.cpp +++ b/renderdoc/driver/vulkan/vk_resources.cpp @@ -3075,9 +3075,11 @@ void VkResourceRecord::MarkBufferFrameReferenced(VkResourceRecord *buf, VkDevice MarkMemoryFrameReferenced(buf->baseResource, buf->memOffset + offset, size, refType); } -void VkResourceRecord::MarkBufferImageCopyFrameReferenced( - VkResourceRecord *buf, VkResourceRecord *img, const ImageLayouts &layout, uint32_t regionCount, - const VkBufferImageCopy *regions, FrameRefType bufRefType, FrameRefType imgRefType) +void VkResourceRecord::MarkBufferImageCopyFrameReferenced(VkResourceRecord *buf, + VkResourceRecord *img, uint32_t regionCount, + const VkBufferImageCopy *regions, + FrameRefType bufRefType, + FrameRefType imgRefType) { MarkResourceFrameReferenced(img->GetResourceID(), imgRefType); MarkResourceFrameReferenced(img->baseResource, imgRefType); @@ -3088,16 +3090,18 @@ void VkResourceRecord::MarkBufferImageCopyFrameReferenced( // mark buffer just as read MarkResourceFrameReferenced(buf->GetResourceID(), eFrameRef_Read); + VkFormat imgFormat = img->resInfo->imageInfo.format; + for(uint32_t ri = 0; ri < regionCount; ri++) { const VkBufferImageCopy ®ion = regions[ri]; - VkFormat regionFormat = layout.format; + VkFormat regionFormat = imgFormat; uint32_t plane = 0; switch(region.imageSubresource.aspectMask) { case VK_IMAGE_ASPECT_STENCIL_BIT: regionFormat = VK_FORMAT_S8_UINT; break; - case VK_IMAGE_ASPECT_DEPTH_BIT: regionFormat = GetDepthOnlyFormat(layout.format); break; + case VK_IMAGE_ASPECT_DEPTH_BIT: regionFormat = GetDepthOnlyFormat(imgFormat); break; case VK_IMAGE_ASPECT_PLANE_1_BIT: plane = 1; break; case VK_IMAGE_ASPECT_PLANE_2_BIT: plane = 2; break; default: break; diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index 2642cd1d5..133fb07f4 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -879,6 +879,39 @@ struct SwapchainInfo uint32_t lastPresent; }; +struct ImageInfo +{ + int layerCount = 0; + int levelCount = 0; + int sampleCount = 0; + VkExtent3D extent = {0, 0, 0}; + VkFormat format = VK_FORMAT_UNDEFINED; + VkImageType imageType = VK_IMAGE_TYPE_MAX_ENUM; + ImageInfo() {} + ImageInfo(const VkImageCreateInfo &ci) + : layerCount(ci.arrayLayers), + levelCount(ci.mipLevels), + sampleCount((int)ci.samples), + extent(ci.extent), + format(ci.format), + imageType(ci.imageType) + { + } + ImageInfo(const SwapchainInfo &swapInfo) + : layerCount(swapInfo.arraySize), + levelCount(1), + sampleCount(1), + format(swapInfo.format), + imageType(VK_IMAGE_TYPE_2D) + { + extent.width = swapInfo.extent.width; + extent.height = swapInfo.extent.height; + extent.depth = 1; + } +}; + +DECLARE_REFLECTION_STRUCT(ImageInfo); + // these structs are allocated for images and buffers, then pointed to (non-owning) by views struct ResourceInfo { @@ -903,6 +936,8 @@ struct ResourceInfo // in order of width first, then height, then depth rdcpair *pages[NUM_VK_IMAGE_ASPECTS]; + ImageInfo imageInfo; + bool IsSparse() const { return pages[0] != NULL; } void Update(uint32_t numBindings, const VkSparseMemoryBind *pBindings); void Update(uint32_t numBindings, const VkSparseImageMemoryBind *pBindings); @@ -1274,14 +1309,14 @@ struct ImageLayouts; template FrameRefType MarkImageReferenced(std::map &imgRefs, ResourceId img, - const ImageLayouts &layout, const ImageRange &range, + const ImageInfo &imageInfo, const ImageRange &range, FrameRefType refType, Compose comp); inline FrameRefType MarkImageReferenced(std::map &imgRefs, ResourceId img, - const ImageLayouts &layout, const ImageRange &range, + const ImageInfo &imageInfo, const ImageRange &range, FrameRefType refType) { - return MarkImageReferenced(imgRefs, img, layout, range, refType, ComposeFrameRefs); + return MarkImageReferenced(imgRefs, img, imageInfo, range, refType, ComposeFrameRefs); } template @@ -1443,9 +1478,8 @@ public: void MarkBufferFrameReferenced(VkResourceRecord *buf, VkDeviceSize offset, VkDeviceSize size, FrameRefType refType); void MarkBufferImageCopyFrameReferenced(VkResourceRecord *buf, VkResourceRecord *img, - const ImageLayouts &layout, uint32_t regionCount, - const VkBufferImageCopy *regions, FrameRefType bufRefType, - FrameRefType imgRefType); + uint32_t regionCount, const VkBufferImageCopy *regions, + FrameRefType bufRefType, FrameRefType imgRefType); void MarkBufferViewFrameReferenced(VkResourceRecord *buf, FrameRefType refType); // these are all disjoint, so only a record of the right type will have each // Note some of these need to be deleted in the constructor, so we check the @@ -1549,24 +1583,11 @@ public: struct ImageLayouts { - ImageLayouts() - : layerCount(1), - levelCount(1), - sampleCount(1), - format(VK_FORMAT_UNDEFINED), - imageType(VK_IMAGE_TYPE_MAX_ENUM) - { - extent.width = extent.height = extent.depth = 1; - } - uint32_t queueFamilyIndex = 0; std::vector subresourceStates; - int layerCount, levelCount, sampleCount; - VkExtent3D extent; - VkFormat format; - VkImageType imageType; bool memoryBound = false; VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + ImageInfo imageInfo; }; DECLARE_REFLECTION_STRUCT(ImageLayouts); @@ -1598,7 +1619,7 @@ uint32_t GetPlaneByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFor template FrameRefType MarkImageReferenced(std::map &imgRefs, ResourceId img, - const ImageLayouts &layout, const ImageRange &range, + const ImageInfo &imageInfo, const ImageRange &range, FrameRefType refType, Compose comp) { if(refType == eFrameRef_None) @@ -1606,11 +1627,11 @@ FrameRefType MarkImageReferenced(std::map &imgRefs, Resourc auto refs = imgRefs.find(img); if(refs == imgRefs.end()) { - refs = - imgRefs - .insert(std::make_pair(img, ImgRefs(layout.imageType, FormatImageAspects(layout.format), - layout.levelCount, layout.layerCount, layout.extent))) - .first; + refs = imgRefs + .insert(std::make_pair( + img, ImgRefs(imageInfo.imageType, FormatImageAspects(imageInfo.format), + imageInfo.levelCount, imageInfo.layerCount, imageInfo.extent))) + .first; } return refs->second.Update(range, refType, comp); } diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index a7ceaa7df..bb867ea91 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -3423,6 +3423,12 @@ void DoSerialise(SerialiserType &ser, ImageLayouts &el) SERIALISE_MEMBER(queueFamilyIndex); } SERIALISE_MEMBER(subresourceStates); + SERIALISE_MEMBER(imageInfo); +} + +template +void DoSerialise(SerialiserType &ser, ImageInfo &el) +{ SERIALISE_MEMBER(layerCount); SERIALISE_MEMBER(levelCount); SERIALISE_MEMBER(sampleCount); @@ -7455,4 +7461,4 @@ INSTANTIATE_SERIALISE_TYPE(VkFenceGetWin32HandleInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkSurfaceCapabilitiesFullScreenExclusiveEXT); INSTANTIATE_SERIALISE_TYPE(VkSurfaceFullScreenExclusiveInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkSurfaceFullScreenExclusiveWin32InfoEXT); -#endif \ No newline at end of file +#endif diff --git a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp index eaf080ee3..87f1f4fc0 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp @@ -1770,8 +1770,8 @@ void WrappedVulkan::vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuff record->AddChunk(scope.Get()); record->MarkBufferImageCopyFrameReferenced(GetRecord(srcBuffer), GetRecord(destImage), - m_ImageLayouts[GetResID(destImage)], regionCount, - pRegions, eFrameRef_Read, eFrameRef_PartialWrite); + regionCount, pRegions, eFrameRef_Read, + eFrameRef_PartialWrite); } } @@ -1878,8 +1878,8 @@ void WrappedVulkan::vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImag record->AddChunk(scope.Get()); record->MarkBufferImageCopyFrameReferenced(GetRecord(destBuffer), GetRecord(srcImage), - m_ImageLayouts[GetResID(srcImage)], regionCount, - pRegions, eFrameRef_CompleteWrite, eFrameRef_Read); + regionCount, pRegions, eFrameRef_CompleteWrite, + eFrameRef_Read); } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index 92084d6c0..a43c8ff76 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -1467,14 +1467,10 @@ bool WrappedVulkan::Serialise_vkCreateImage(SerialiserType &ser, VkDevice device range.layerCount = CreateInfo.arrayLayers; ImageLayouts &layouts = m_ImageLayouts[live]; + layouts.imageInfo = ImageInfo(CreateInfo); + layouts.subresourceStates.clear(); - layouts.layerCount = CreateInfo.arrayLayers; - layouts.sampleCount = (int)CreateInfo.samples; - layouts.levelCount = CreateInfo.mipLevels; - layouts.extent = CreateInfo.extent; - layouts.format = CreateInfo.format; - layouts.imageType = CreateInfo.imageType; layouts.initialLayout = CreateInfo.initialLayout; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -1621,6 +1617,13 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pImage); record->AddChunk(chunk); + record->resInfo = new ResourceInfo(); + ResourceInfo &resInfo = *record->resInfo; + resInfo.imageInfo = ImageInfo(*pCreateInfo); + + // pre-populate memory requirements + ObjDisp(device)->GetImageMemoryRequirements(Unwrap(device), Unwrap(*pImage), &resInfo.memreqs); + bool isSparse = (pCreateInfo->flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)) != 0; @@ -1646,14 +1649,8 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * // sure to fetch their contents even if we don't see any writes. if(isSparse || isExternal) { - record->resInfo = new ResourceInfo(); - GetResourceManager()->MarkDirtyResource(id); - // pre-populate memory requirements - ObjDisp(device)->GetImageMemoryRequirements(Unwrap(device), Unwrap(*pImage), - &record->resInfo->memreqs); - // for external images, try creating a non-external version and take the worst case of // memory requirements, in case the non-external one (as we will replay it) needs more // memory or a stricter alignment @@ -1679,16 +1676,15 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * if(mrq.size > 0) { RDCDEBUG("External image requires %llu bytes at %llu alignment, in %x memory types", - record->resInfo->memreqs.size, record->resInfo->memreqs.alignment, - record->resInfo->memreqs.memoryTypeBits); + resInfo.memreqs.size, resInfo.memreqs.alignment, + resInfo.memreqs.memoryTypeBits); RDCDEBUG( "Non-external version requires %llu bytes at %llu alignment, in %x memory types", mrq.size, mrq.alignment, mrq.memoryTypeBits); - record->resInfo->memreqs.size = RDCMAX(record->resInfo->memreqs.size, mrq.size); - record->resInfo->memreqs.alignment = - RDCMAX(record->resInfo->memreqs.size, mrq.alignment); - record->resInfo->memreqs.memoryTypeBits &= mrq.memoryTypeBits; + resInfo.memreqs.size = RDCMAX(resInfo.memreqs.size, mrq.size); + resInfo.memreqs.alignment = RDCMAX(resInfo.memreqs.size, mrq.alignment); + resInfo.memreqs.memoryTypeBits &= mrq.memoryTypeBits; } } else @@ -1714,22 +1710,20 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * RDCASSERT(numreqs > 0); - record->resInfo->pagedim = reqs[0].formatProperties.imageGranularity; - record->resInfo->imgdim = pCreateInfo->extent; - record->resInfo->imgdim.width /= record->resInfo->pagedim.width; - record->resInfo->imgdim.height /= record->resInfo->pagedim.height; - record->resInfo->imgdim.depth /= record->resInfo->pagedim.depth; + resInfo.pagedim = reqs[0].formatProperties.imageGranularity; + resInfo.imgdim = pCreateInfo->extent; + resInfo.imgdim.width /= resInfo.pagedim.width; + resInfo.imgdim.height /= resInfo.pagedim.height; + resInfo.imgdim.depth /= resInfo.pagedim.depth; - uint32_t numpages = record->resInfo->imgdim.width * record->resInfo->imgdim.height * - record->resInfo->imgdim.depth; + uint32_t numpages = resInfo.imgdim.width * resInfo.imgdim.height * resInfo.imgdim.depth; for(uint32_t i = 0; i < numreqs; i++) { // assume all page sizes are the same for all aspects - RDCASSERT( - record->resInfo->pagedim.width == reqs[i].formatProperties.imageGranularity.width && - record->resInfo->pagedim.height == reqs[i].formatProperties.imageGranularity.height && - record->resInfo->pagedim.depth == reqs[i].formatProperties.imageGranularity.depth); + RDCASSERT(resInfo.pagedim.width == reqs[i].formatProperties.imageGranularity.width && + resInfo.pagedim.height == reqs[i].formatProperties.imageGranularity.height && + resInfo.pagedim.depth == reqs[i].formatProperties.imageGranularity.depth); int a = 0; for(a = 0; a < NUM_VK_IMAGE_ASPECTS; a++) @@ -1738,7 +1732,7 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * break; } - record->resInfo->pages[a] = new rdcpair[numpages]; + resInfo.pages[a] = new rdcpair[numpages]; } } else @@ -1765,15 +1759,9 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * SCOPED_LOCK(m_ImageLayoutsLock); layout = &m_ImageLayouts[id]; } + layout->imageInfo = ImageInfo(*pCreateInfo); - layout->layerCount = pCreateInfo->arrayLayers; - layout->levelCount = pCreateInfo->mipLevels; - layout->sampleCount = (int)pCreateInfo->samples; - layout->extent = pCreateInfo->extent; - layout->format = pCreateInfo->format; - layout->imageType = pCreateInfo->imageType; layout->initialLayout = pCreateInfo->initialLayout; - layout->subresourceStates.clear(); range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; diff --git a/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp index fbeae5052..a5adbae25 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp @@ -298,6 +298,9 @@ VkResult WrappedVulkan::vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR record->AddParent(swaprecord); + record->resInfo = new ResourceInfo(); + record->resInfo->imageInfo = ImageInfo(*swaprecord->swapInfo); + // note we add the chunk to the swap record, that way when the swapchain is created it will // always create all of its images on replay. The image's record is kept around for // reference tracking and any other chunks. Because it has a parent relationship on the @@ -446,14 +449,15 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice range.layerCount = CreateInfo.imageArrayLayers; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - m_ImageLayouts[liveId].extent = iminfo.extent; - m_ImageLayouts[liveId].format = iminfo.format; - m_ImageLayouts[liveId].imageType = iminfo.type; - m_ImageLayouts[liveId].memoryBound = true; - m_ImageLayouts[liveId].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + ImageLayouts &layouts = m_ImageLayouts[liveId]; - m_ImageLayouts[liveId].subresourceStates.clear(); - m_ImageLayouts[liveId].subresourceStates.push_back(ImageRegionState( + layouts.imageInfo = ImageInfo(swapinfo); + + layouts.memoryBound = true; + layouts.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + layouts.subresourceStates.clear(); + layouts.subresourceStates.push_back(ImageRegionState( VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED)); } } @@ -584,17 +588,18 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device, range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // fill out image info so we track resource state barriers + ImageLayouts *layout = NULL; { SCOPED_LOCK(m_ImageLayoutsLock); - m_ImageLayouts[imid].format = pCreateInfo->imageFormat; - m_ImageLayouts[imid].imageType = VK_IMAGE_TYPE_2D; - m_ImageLayouts[imid].memoryBound = true; - m_ImageLayouts[imid].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - m_ImageLayouts[imid].subresourceStates.clear(); - m_ImageLayouts[imid].subresourceStates.push_back(ImageRegionState( - VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED)); + layout = &m_ImageLayouts[imid]; } + layout->imageInfo = GetRecord(images[i])->resInfo->imageInfo; + layout->memoryBound = true; + layout->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + layout->subresourceStates.clear(); + layout->subresourceStates.push_back(ImageRegionState( + VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED)); { VkImageViewCreateInfo info = {