From 4c7ed0cb3c1eb5d822eb827d2bfa628a393c5a59 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 14 Dec 2018 15:40:09 +0000 Subject: [PATCH] Copy each plane aspect of multi-planar images separately on vulkan --- renderdoc/driver/vulkan/vk_initstate.cpp | 253 +++++++++++++++++++---- renderdoc/driver/vulkan/vk_resources.cpp | 169 +++++++++++++++ renderdoc/driver/vulkan/vk_resources.h | 5 + 3 files changed, 384 insertions(+), 43 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index f6c29c5ae..5157ed896 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -176,6 +176,44 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) // backing the array image only. } + uint32_t planeCount = GetYUVPlaneCount(layout->format); + uint32_t horizontalPlaneShift = 0; + uint32_t verticalPlaneShift = 0; + + if(planeCount > 1) + { + switch(layout->format) + { + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + horizontalPlaneShift = verticalPlaneShift = 1; + break; + case VK_FORMAT_G8B8G8R8_422_UNORM: + case VK_FORMAT_B8G8R8G8_422_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: + case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G16B16G16R16_422_UNORM: + case VK_FORMAT_B16G16R16G16_422_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: horizontalPlaneShift = 1; break; + default: break; + } + } + VkFormat sizeFormat = GetDepthOnlyFormat(layout->format); for(int a = 0; a < numLayers; a++) @@ -184,16 +222,27 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) { bufInfo.size = AlignUp(bufInfo.size, bufAlignment); - bufInfo.size += GetByteSize(layout->extent.width, layout->extent.height, - layout->extent.depth, sizeFormat, m); - - if(sizeFormat != layout->format) + if(planeCount > 1) + { + // 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); + } + else { - // 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); + layout->extent.depth, sizeFormat, m); + + if(sizeFormat != layout->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); + } } } } @@ -228,9 +277,21 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; if(IsStencilOnlyFormat(layout->format)) + { aspectFlags = VK_IMAGE_ASPECT_STENCIL_BIT; + } else if(IsDepthOrStencilFormat(layout->format)) + { aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; + } + else if(planeCount > 1) + { + aspectFlags = VK_IMAGE_ASPECT_PLANE_0_BIT; + if(planeCount >= 2) + aspectFlags |= VK_IMAGE_ASPECT_PLANE_1_BIT; + if(planeCount >= 3) + aspectFlags |= VK_IMAGE_ASPECT_PLANE_2_BIT; + } VkImageMemoryBarrier srcimBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -336,29 +397,58 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) extent, }; - bufOffset = AlignUp(bufOffset, bufAlignment); - - region.bufferOffset = bufOffset; - - bufOffset += GetByteSize(layout->extent.width, layout->extent.height, layout->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(planeCount > 1) + { + // need to consider each plane aspect separately + for(uint32_t i = 0; i < planeCount; i++) + { + bufOffset = AlignUp(bufOffset, bufAlignment); + + region.imageExtent = extent; + region.bufferOffset = bufOffset; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << i; + + if(i > 0) + { + region.imageExtent.width >>= horizontalPlaneShift; + region.imageExtent.height >>= verticalPlaneShift; + } + + bufOffset += GetPlaneByteSize(layout->extent.width, layout->extent.height, + layout->extent.depth, sizeFormat, m, i); + + ObjDisp(d)->CmdCopyImageToBuffer(Unwrap(cmd), realim, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Unwrap(dstBuf), + 1, ®ion); + } + } + else { - // if we removed stencil from the format, copy that separately now. bufOffset = AlignUp(bufOffset, bufAlignment); 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); + layout->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 we removed stencil from the format, copy that separately now. + bufOffset = AlignUp(bufOffset, bufAlignment); + + 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); + + ObjDisp(d)->CmdCopyImageToBuffer(Unwrap(cmd), realim, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Unwrap(dstBuf), + 1, ®ion); + } } // update the extent for the next mip @@ -1051,8 +1141,8 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, W VkExtent3D extent = c.extent; VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; - VkFormat fmt = c.format; + if(IsStencilOnlyFormat(fmt)) aspectFlags = VK_IMAGE_ASPECT_STENCIL_BIT; else if(IsDepthOrStencilFormat(fmt)) @@ -1311,12 +1401,14 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, VkInitialContents ini { if(initial.tag == VkInitialContents::ClearColorImage) { - if(IsBlockFormat(m_ImageLayouts[id].format)) + VkFormat format = m_ImageLayouts[id].format; + + if(IsBlockFormat(format) || IsYUVFormat(format)) { RDCWARN( - "Trying to clear a compressed image %llu - should have initial states or be " - "stripped.", - id); + "Trying to clear a compressed/YUV image %llu with format %s - should have initial " + "states or be stripped.", + id, ToStr(format).c_str()); return; } @@ -1671,10 +1763,59 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, VkInitialContents ini VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; VkFormat fmt = m_CreationInfo.m_Image[id].format; + uint32_t planeCount = GetYUVPlaneCount(fmt); + uint32_t horizontalPlaneShift = 0; + uint32_t verticalPlaneShift = 0; if(IsStencilOnlyFormat(fmt)) + { aspectFlags = VK_IMAGE_ASPECT_STENCIL_BIT; + } else if(IsDepthOrStencilFormat(fmt)) + { aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; + } + else if(planeCount > 1) + { + aspectFlags = VK_IMAGE_ASPECT_PLANE_0_BIT; + if(planeCount >= 2) + aspectFlags |= VK_IMAGE_ASPECT_PLANE_1_BIT; + if(planeCount >= 3) + aspectFlags |= VK_IMAGE_ASPECT_PLANE_2_BIT; + } + + if(planeCount > 1) + { + switch(fmt) + { + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + horizontalPlaneShift = verticalPlaneShift = 1; + break; + case VK_FORMAT_G8B8G8R8_422_UNORM: + case VK_FORMAT_B8G8R8G8_422_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: + case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G16B16G16R16_422_UNORM: + case VK_FORMAT_B16G16R16G16_422_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: horizontalPlaneShift = 1; break; + default: break; + } + } VkImageMemoryBarrier dstimBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1751,30 +1892,56 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, VkInitialContents ini extent, }; - bufOffset = AlignUp(bufOffset, bufAlignment); - - region.bufferOffset = bufOffset; - - VkFormat sizeFormat = GetDepthOnlyFormat(fmt); - - // pass 0 for mip since we've already pre-downscaled extent - bufOffset += GetByteSize(extent.width, extent.height, extent.depth, sizeFormat, 0); - - ObjDisp(cmd)->CmdCopyBufferToImage(Unwrap(cmd), Unwrap(buf), ToHandle(live), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - - if(sizeFormat != fmt) + if(planeCount > 1) + { + // need to consider each plane aspect separately + for(uint32_t i = 0; i < planeCount; i++) + { + bufOffset = AlignUp(bufOffset, bufAlignment); + + region.imageExtent = extent; + region.bufferOffset = bufOffset; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << i; + + if(i > 0) + { + region.imageExtent.width >>= horizontalPlaneShift; + region.imageExtent.height >>= verticalPlaneShift; + } + + bufOffset += GetPlaneByteSize(extent.width, extent.height, extent.depth, fmt, 0, i); + + ObjDisp(cmd)->CmdCopyBufferToImage(Unwrap(cmd), Unwrap(buf), ToHandle(live), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + } + } + else { - // if we removed stencil from the format, copy that separately now. bufOffset = AlignUp(bufOffset, bufAlignment); region.bufferOffset = bufOffset; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - bufOffset += GetByteSize(extent.width, extent.height, extent.depth, VK_FORMAT_S8_UINT, 0); + VkFormat sizeFormat = GetDepthOnlyFormat(fmt); + + // pass 0 for mip since we've already pre-downscaled extent + bufOffset += GetByteSize(extent.width, extent.height, extent.depth, sizeFormat, 0); ObjDisp(cmd)->CmdCopyBufferToImage(Unwrap(cmd), Unwrap(buf), ToHandle(live), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + if(sizeFormat != fmt) + { + // if we removed stencil from the format, copy that separately now. + bufOffset = AlignUp(bufOffset, bufAlignment); + + region.bufferOffset = bufOffset; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + + bufOffset += GetByteSize(extent.width, extent.height, extent.depth, VK_FORMAT_S8_UINT, 0); + + ObjDisp(cmd)->CmdCopyBufferToImage(Unwrap(cmd), Unwrap(buf), ToHandle(live), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + } } // update the extent for the next mip diff --git a/renderdoc/driver/vulkan/vk_resources.cpp b/renderdoc/driver/vulkan/vk_resources.cpp index 1ae1df6a7..af2601ed2 100644 --- a/renderdoc/driver/vulkan/vk_resources.cpp +++ b/renderdoc/driver/vulkan/vk_resources.cpp @@ -493,6 +493,54 @@ uint32_t GetYUVNumRows(VkFormat f, uint32_t height) return height; } +VkFormat GetYUVViewPlaneFormat(VkFormat f, uint32_t plane) +{ + switch(f) + { + case VK_FORMAT_G8B8G8R8_422_UNORM: + case VK_FORMAT_B8G8R8G8_422_UNORM: + case VK_FORMAT_R10X6_UNORM_PACK16: + case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: + case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: + case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: + case VK_FORMAT_R12X4_UNORM_PACK16: + case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: + case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: + case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: + case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: + case VK_FORMAT_G16B16G16R16_422_UNORM: + case VK_FORMAT_B16G16R16G16_422_UNORM: return f; + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: return VK_FORMAT_R8_UNORM; + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + return plane == 0 ? VK_FORMAT_R8_UNORM : VK_FORMAT_R8G8_UNORM; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: return VK_FORMAT_R10X6_UNORM_PACK16; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + return plane == 0 ? VK_FORMAT_R10X6_UNORM_PACK16 : VK_FORMAT_R10X6G10X6_UNORM_2PACK16; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: return VK_FORMAT_R12X4_UNORM_PACK16; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + return plane == 0 ? VK_FORMAT_R12X4_UNORM_PACK16 : VK_FORMAT_R12X4G12X4_UNORM_2PACK16; + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: return VK_FORMAT_R16_UNORM; + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: + return plane == 0 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R16G16_UNORM; + default: break; + } + + return f; +} + VkFormat GetDepthOnlyFormat(VkFormat f) { switch(f) @@ -940,6 +988,86 @@ uint32_t GetByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat F return ret; } +uint32_t GetPlaneByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, + uint32_t mip, uint32_t plane) +{ + switch(Format) + { + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + if(plane == 0) + return GetByteSize(Width, Height, Depth, VK_FORMAT_R8_UNORM, mip); + else + return GetByteSize(RDCMAX(1U, Width >> 1), RDCMAX(1U, Height >> 1), Depth, + VK_FORMAT_R8G8_UNORM, mip); + + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + if(plane == 0) + return GetByteSize(Width, Height, Depth, VK_FORMAT_R16_UNORM, mip); + else + return GetByteSize(RDCMAX(1U, Width >> 1), RDCMAX(1U, Height >> 1), Depth, + VK_FORMAT_R16G16_UNORM, mip); + + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + if(plane == 0) + return GetByteSize(Width, Height, Depth, VK_FORMAT_R8_UNORM, mip); + else + return GetByteSize(RDCMAX(1U, Width >> 1), Height, Depth, VK_FORMAT_R8G8_UNORM, mip); + + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + if(plane == 0) + return GetByteSize(Width, Height, Depth, VK_FORMAT_R16_UNORM, mip); + else + return GetByteSize(RDCMAX(1U, Width >> 1), Height, Depth, VK_FORMAT_R16G16_UNORM, mip); + + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + if(plane == 0) + return GetByteSize(Width, Height, Depth, VK_FORMAT_R8_UNORM, mip); + else + return GetByteSize(RDCMAX(1U, Width >> 1), RDCMAX(1U, Height >> 1), Depth, + VK_FORMAT_R8_UNORM, mip); + + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + + if(plane == 0) + return GetByteSize(Width, Height, Depth, VK_FORMAT_R16_UNORM, mip); + else + return GetByteSize(RDCMAX(1U, Width >> 1), RDCMAX(1U, Height >> 1), Depth, + VK_FORMAT_R16_UNORM, mip); + + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + if(plane == 0) + return GetByteSize(Width, Height, Depth, VK_FORMAT_R8_UNORM, mip); + else + return GetByteSize(RDCMAX(1U, Width >> 1), Height, Depth, VK_FORMAT_R8_UNORM, mip); + + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + if(plane == 0) + return GetByteSize(Width, Height, Depth, VK_FORMAT_R16_UNORM, mip); + else + return GetByteSize(RDCMAX(1U, Width >> 1), Height, Depth, VK_FORMAT_R16_UNORM, mip); + + case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: + return GetByteSize(Width, Height, Depth, VK_FORMAT_R8_UNORM, mip); + + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: + case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: + return GetByteSize(Width, Height, Depth, VK_FORMAT_R16_UNORM, mip); + + default: break; + } + + return GetByteSize(Width, Height, Depth, Format, mip); +} + ResourceFormat MakeResourceFormat(VkFormat fmt) { ResourceFormat ret; @@ -3038,6 +3166,47 @@ TEST_CASE("Vulkan formats", "[format][vulkan]") CHECK(yuvsizes[i++] == GetByteSize(width, height, 1, f, 0)); } }; + + SECTION("GetPlaneByteSize for planar YUV formats") + { + const uint32_t width = 24, height = 24; + + for(VkFormat f : { + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, + VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, + VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, + }) + { + INFO("Format is " << ToStr(f)); + + uint32_t planeCount = GetYUVPlaneCount(f); + + CHECK(planeCount > 1); + + uint32_t planeSum = 0; + for(uint32_t p = 0; p < planeCount; p++) + planeSum += GetPlaneByteSize(width, height, 1, f, 0, p); + + CHECK(planeSum == GetByteSize(width, height, 1, f, 0)); + } + } }; #endif // ENABLED(ENABLE_UNIT_TESTS) diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index 4535f57b5..b1c20577d 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -1226,6 +1226,11 @@ bool IsDoubleFormat(VkFormat f); bool IsSIntFormat(VkFormat f); bool IsYUVFormat(VkFormat f); +uint32_t GetYUVPlaneCount(VkFormat f); +uint32_t GetYUVNumRows(VkFormat f, uint32_t height); +VkFormat GetYUVViewPlaneFormat(VkFormat f, uint32_t plane); VkFormat GetDepthOnlyFormat(VkFormat f); uint32_t GetByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, uint32_t mip); +uint32_t GetPlaneByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, + uint32_t mip, uint32_t plane);