Refactor GetByteSize and GetPlaneByteSize using GetBlockShape

This eliminates a substantial amount duplicate code between `GetByteSize` and
`GetBlockShape`.

Also added explicit tests of `GetPlateByteSize` independent of `GetByteSize`.
This commit is contained in:
Benson Joeris
2019-02-19 16:24:40 -05:00
committed by Baldur Karlsson
parent 0f1e1faf48
commit 47b351c566
+100 -539
View File
@@ -1188,520 +1188,6 @@ VkFormat GetViewCastedFormat(VkFormat f, CompType typeHint)
return f;
}
uint32_t GetByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, uint32_t mip)
{
uint32_t w = RDCMAX(Width >> mip, 1U);
uint32_t h = RDCMAX(Height >> mip, 1U);
uint32_t d = RDCMAX(Depth >> mip, 1U);
uint32_t ret = w * h * d;
uint32_t astc[2] = {0, 0};
switch(Format)
{
case VK_FORMAT_R64G64B64A64_UINT:
case VK_FORMAT_R64G64B64A64_SINT:
case VK_FORMAT_R64G64B64A64_SFLOAT: ret *= 32; break;
case VK_FORMAT_R64G64B64_UINT:
case VK_FORMAT_R64G64B64_SINT:
case VK_FORMAT_R64G64B64_SFLOAT: ret *= 24; break;
case VK_FORMAT_R32G32B32A32_UINT:
case VK_FORMAT_R32G32B32A32_SINT:
case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_R64G64_UINT:
case VK_FORMAT_R64G64_SINT:
case VK_FORMAT_R64G64_SFLOAT: ret *= 16; break;
case VK_FORMAT_R32G32B32_UINT:
case VK_FORMAT_R32G32B32_SINT:
case VK_FORMAT_R32G32B32_SFLOAT: ret *= 12; break;
case VK_FORMAT_R16G16B16A16_UNORM:
case VK_FORMAT_R16G16B16A16_SNORM:
case VK_FORMAT_R16G16B16A16_USCALED:
case VK_FORMAT_R16G16B16A16_SSCALED:
case VK_FORMAT_R16G16B16A16_UINT:
case VK_FORMAT_R16G16B16A16_SINT:
case VK_FORMAT_R16G16B16A16_SFLOAT:
case VK_FORMAT_R32G32_UINT:
case VK_FORMAT_R32G32_SINT:
case VK_FORMAT_R32G32_SFLOAT:
case VK_FORMAT_R64_UINT:
case VK_FORMAT_R64_SINT:
case VK_FORMAT_R64_SFLOAT: ret *= 8; break;
case VK_FORMAT_R16G16B16_UNORM:
case VK_FORMAT_R16G16B16_SNORM:
case VK_FORMAT_R16G16B16_USCALED:
case VK_FORMAT_R16G16B16_SSCALED:
case VK_FORMAT_R16G16B16_UINT:
case VK_FORMAT_R16G16B16_SINT:
case VK_FORMAT_R16G16B16_SFLOAT: ret *= 6; break;
case VK_FORMAT_D32_SFLOAT_S8_UINT: ret *= 8; break;
case VK_FORMAT_R8G8B8_UNORM:
case VK_FORMAT_R8G8B8_SNORM:
case VK_FORMAT_R8G8B8_USCALED:
case VK_FORMAT_R8G8B8_SSCALED:
case VK_FORMAT_R8G8B8_UINT:
case VK_FORMAT_R8G8B8_SINT:
case VK_FORMAT_R8G8B8_SRGB:
case VK_FORMAT_B8G8R8_UNORM:
case VK_FORMAT_B8G8R8_SNORM:
case VK_FORMAT_B8G8R8_USCALED:
case VK_FORMAT_B8G8R8_SSCALED:
case VK_FORMAT_B8G8R8_UINT:
case VK_FORMAT_B8G8R8_SINT:
case VK_FORMAT_B8G8R8_SRGB: ret *= 3; break;
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
case VK_FORMAT_A2B10G10R10_UINT_PACK32:
case VK_FORMAT_A2B10G10R10_SINT_PACK32:
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
case VK_FORMAT_A2R10G10B10_UINT_PACK32:
case VK_FORMAT_A2R10G10B10_SINT_PACK32:
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_R8G8B8A8_SNORM:
case VK_FORMAT_R8G8B8A8_USCALED:
case VK_FORMAT_R8G8B8A8_SSCALED:
case VK_FORMAT_R8G8B8A8_UINT:
case VK_FORMAT_R8G8B8A8_SINT:
case VK_FORMAT_R8G8B8A8_SRGB:
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SNORM:
case VK_FORMAT_B8G8R8A8_USCALED:
case VK_FORMAT_B8G8R8A8_SSCALED:
case VK_FORMAT_B8G8R8A8_UINT:
case VK_FORMAT_B8G8R8A8_SINT:
case VK_FORMAT_B8G8R8A8_SRGB:
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
case VK_FORMAT_A8B8G8R8_UINT_PACK32:
case VK_FORMAT_A8B8G8R8_SINT_PACK32:
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
case VK_FORMAT_R16G16_UNORM:
case VK_FORMAT_R16G16_SNORM:
case VK_FORMAT_R16G16_USCALED:
case VK_FORMAT_R16G16_SSCALED:
case VK_FORMAT_R16G16_UINT:
case VK_FORMAT_R16G16_SINT:
case VK_FORMAT_R16G16_SFLOAT:
case VK_FORMAT_R32_UINT:
case VK_FORMAT_R32_SINT:
case VK_FORMAT_R32_SFLOAT:
case VK_FORMAT_X8_D24_UNORM_PACK32:
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT:
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: ret *= 4; break;
case VK_FORMAT_D16_UNORM_S8_UINT: ret *= 4; break;
case VK_FORMAT_R8G8_UNORM:
case VK_FORMAT_R8G8_SNORM:
case VK_FORMAT_R8G8_USCALED:
case VK_FORMAT_R8G8_SSCALED:
case VK_FORMAT_R8G8_UINT:
case VK_FORMAT_R8G8_SINT:
case VK_FORMAT_R8G8_SRGB:
case VK_FORMAT_R16_UNORM:
case VK_FORMAT_R16_SNORM:
case VK_FORMAT_R16_USCALED:
case VK_FORMAT_R16_SSCALED:
case VK_FORMAT_R16_UINT:
case VK_FORMAT_R16_SINT:
case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_R5G6B5_UNORM_PACK16:
case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
case VK_FORMAT_B5G6R5_UNORM_PACK16:
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
case VK_FORMAT_B4G4R4A4_UNORM_PACK16: ret *= 2; break;
case VK_FORMAT_R4G4_UNORM_PACK8:
case VK_FORMAT_R8_UNORM:
case VK_FORMAT_R8_SNORM:
case VK_FORMAT_R8_USCALED:
case VK_FORMAT_R8_SSCALED:
case VK_FORMAT_R8_UINT:
case VK_FORMAT_R8_SINT:
case VK_FORMAT_R8_SRGB:
case VK_FORMAT_S8_UINT: ret *= 1; break;
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
case VK_FORMAT_BC4_UNORM_BLOCK:
case VK_FORMAT_BC4_SNORM_BLOCK:
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
case VK_FORMAT_EAC_R11_UNORM_BLOCK:
case VK_FORMAT_EAC_R11_SNORM_BLOCK:
ret = AlignUp4(w) * AlignUp4(h) * d;
ret /= 2;
break;
case VK_FORMAT_BC2_UNORM_BLOCK:
case VK_FORMAT_BC2_SRGB_BLOCK:
case VK_FORMAT_BC3_UNORM_BLOCK:
case VK_FORMAT_BC3_SRGB_BLOCK:
case VK_FORMAT_BC5_UNORM_BLOCK:
case VK_FORMAT_BC5_SNORM_BLOCK:
case VK_FORMAT_BC6H_UFLOAT_BLOCK:
case VK_FORMAT_BC6H_SFLOAT_BLOCK:
case VK_FORMAT_BC7_UNORM_BLOCK:
case VK_FORMAT_BC7_SRGB_BLOCK:
case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
ret = AlignUp4(w) * AlignUp4(h) * d;
ret *= 1;
break;
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
astc[0] = 4;
astc[1] = 4;
break;
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
astc[0] = 5;
astc[1] = 4;
break;
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
astc[0] = 5;
astc[1] = 5;
break;
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
astc[0] = 6;
astc[1] = 5;
break;
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
astc[0] = 6;
astc[1] = 6;
break;
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
astc[0] = 8;
astc[1] = 5;
break;
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
astc[0] = 8;
astc[1] = 6;
break;
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
astc[0] = 8;
astc[1] = 8;
break;
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
astc[0] = 10;
astc[1] = 5;
break;
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
astc[0] = 10;
astc[1] = 6;
break;
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
astc[0] = 10;
astc[1] = 8;
break;
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
astc[0] = 10;
astc[1] = 10;
break;
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
astc[0] = 12;
astc[1] = 10;
break;
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
astc[0] = 12;
astc[1] = 12;
break;
case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
ret = (uint32_t)(ceil(w / 8.0) * ceil(h / 4.0) * 8.0);
break;
case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
ret = (uint32_t)(ceil(w / 4.0) * ceil(h / 4.0) * 8.0);
break;
/*
* YUV planar/packed subsampled textures.
*
* In each diagram we indicate (maybe part) of the data for a 4x4 texture:
*
* +---+---+---+---+
* | 0 | 1 | 2 | 3 |
* +---+---+---+---+
* | 4 | 5 | 6 | 7 |
* +---+---+---+---+
* | 8 | 9 | A | B |
* +---+---+---+---+
* | C | D | E | F |
* +---+---+---+---+
*
*
* FOURCC decoding:
* - char 0: 'Y' = packed, 'P' = planar
* - char 1: '4' = 4:4:4, '2' = 4:2:2, '1' = 4:2:1, '0' = 4:2:0
* - char 2+3: '16' = 16-bit, '10' = 10-bit, '08' = 8-bit
*
* planar = Y is first, all together, then UV comes second.
* packed = YUV is interleaved
*
* ======================= 4:4:4 lossless packed =========================
*
* Equivalent to uncompressed formats, just YUV instead of RGB. For 8-bit:
*
* pixel: 0 1 2 3
* byte: 0 1 2 3 4 5 6 7 8 9 A B C D E F
* Y0 U0 V0 A0 Y1 U1 V1 A1 Y2 U2 V2 A2 Y3 U3 V3 A3
*
* 16-bit is similar with two bytes per sample, 10-bit for uncompressed is
* equivalent to R10G10B10A2 but with RGB=>YUV
*
* ============================ 4:2:2 packed =============================
*
* 50% horizontal subsampling packed, two Y samples for each U/V sample pair. For 8-bit:
*
* pixel: 0 | 1 2 | 3 4 | 5 6 | 7
* byte: 0 1 2 3 4 5 6 7 8 9 A B C D E F
* Y0 U0 Y1 V0 Y2 U1 Y3 V1 Y4 U2 Y5 V2 Y6 U3 Y7 V3
*
* 16-bit is similar with two bytes per sample, 10-bit is stored identically to 16-bit but in
* the most significant bits:
*
* bit: FEDCBA9876543210
* 16-bit: XXXXXXXXXXXXXXXX
* 10-bit: XXXXXXXXXX000000
*
* Since the data is unorm this just spaces out valid values.
*
* ============================ 4:2:0 planar =============================
*
* 50% horizontal and vertical subsampled planar, four Y samples for each U/V sample pair.
* For 8-bit:
*
*
* pixel: 0 1 2 3 4 5 6 7
* byte: 0 1 2 3 4 5 6 7
* Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7
*
* pixel: 8 9 A B C D E F
* byte: 8 9 A B C D E F
* Y8 Y9 Ya Yb Yc Yd Ye Yf
*
* ... all of the rest of Y luma ...
*
* pixel: T&4 | 1&5 2&6 | 3&7
* byte: 0 1 2 3 4 5 6 7
* U0 V0 U1 V1 U2 V2 U3 V3
*
* pixel: 8&C | 9&D A&E | B&F
* byte: 8 9 A B C D E F
* U4 V4 U5 V5 U6 V6 U7 V7
*/
case VK_FORMAT_G8B8G8R8_422_UNORM:
case VK_FORMAT_B8G8R8G8_422_UNORM:
// 4:2:2 packed 8-bit, so 1 byte per pixel for luma and 1 byte per pixel for chroma (2 chroma
// samples, with 50% subsampling = 1 byte per pixel)
ret *= 2;
break;
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
// 4:2:0 planar. Since we can assume even width and height, resulting size is 1 byte per pixel
// for luma, plus 1 byte per 2 pixels for chroma.
// 2 or 3 planes makes no difference to size
ret = ret + ret / 2;
break;
case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
// 4:2:2 planar 8-bit, same as VK_FORMAT_G8B8G8R8_422_UNORM
// 2 or 3 planes makes no difference to size
ret *= 2;
break;
case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
// uncompressed with 3 planes, so 3 bytes per pixel
ret *= 3;
break;
// basically just 16-bit format with only top 10-bits used
// 10-bit and 12-bit formats are stored identically to 16-bit formats
case VK_FORMAT_R10X6_UNORM_PACK16:
case VK_FORMAT_R12X4_UNORM_PACK16: ret *= 2; break;
case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
// just a 16-bit format with only top N-bits used
// 10-bit and 12-bit formats are stored identically to 16-bit formats
ret *= 4;
break;
case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
// just a 16-bit format with only top N-bits used
// 10-bit and 12-bit formats are stored identically to 16-bit formats
ret *= 8;
break;
case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
case VK_FORMAT_B10X6G10X6R10X6G10X6_422_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:
// 10-bit and 12-bit formats are stored identically to 16-bit formats
// 4:2:2 packed 16-bit
ret *= 4;
break;
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:
// 10-bit and 12-bit formats are stored identically to 16-bit formats
// 4:2:0 planar but 16-bit, so pixelCount*2 + (pixelCount*2) / 2
ret *= 2;
ret = ret + ret / 2;
break;
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
// 10-bit and 12-bit formats are stored identically to 16-bit formats
// 4:2:2 16-bit in means 4 bytes per pixel - 2 bytes for luma, then 2 bytes each for chroma
// samples but half the number of samples = 2 bytes for chroma. Packed vs. planar doesn't
// change overall size
ret *= 4;
break;
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:
// 10-bit and 12-bit formats are stored identically to 16-bit formats
// 4:4:4 16-bit in 3 planes means 6 bytes per pixel
ret *= 6;
break;
default:
ret = 1;
RDCERR("Unrecognised Vulkan Format: %d", Format);
break;
}
if(astc[0] > 0 && astc[1] > 0)
{
uint32_t blocks[2] = {(w / astc[0]), (h / astc[1])};
// how many blocks are needed - including any extra partial blocks
blocks[0] += (w % astc[0]) ? 1 : 0;
blocks[1] += (h % astc[1]) ? 1 : 0;
// ASTC blocks are all 128 bits each
return blocks[0] * blocks[1] * 16 * d;
}
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);
}
// The shape of blocks in (a plane of) an image format.
// Non-block formats are considered to have 1x1 blocks.
// For some planar formats, the block shape depends on the plane--
@@ -2060,6 +1546,66 @@ BlockShape GetBlockShape(VkFormat Format, uint32_t plane)
return BlockShape();
}
VkExtent2D GetPlaneShape(uint32_t Width, uint32_t Height, VkFormat Format, uint32_t plane)
{
switch(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:
if(plane == 0)
return {Width, Height};
else
return {RDCMAX(1U, (Width + 1) / 2), RDCMAX(1U, (Height + 1) / 2)};
case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
if(plane == 0)
return {Width, Height};
else
return {RDCMAX(1U, (Width + 1) / 2), Height};
default: return {Width, Height};
}
}
uint32_t GetPlaneByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format,
uint32_t mip, uint32_t plane)
{
uint32_t mipWidth = RDCMAX(Width >> mip, 1U);
uint32_t mipHeight = RDCMAX(Height >> mip, 1U);
uint32_t mipDepth = RDCMAX(Depth >> mip, 1U);
VkExtent2D planeShape = GetPlaneShape(mipWidth, mipHeight, Format, plane);
BlockShape blockShape = GetBlockShape(Format, plane);
uint32_t widthInBlocks = (planeShape.width + blockShape.width - 1) / blockShape.width;
uint32_t heightInBlocks = (planeShape.height + blockShape.height - 1) / blockShape.height;
return blockShape.bytes * widthInBlocks * heightInBlocks * mipDepth;
}
uint32_t GetByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, uint32_t mip)
{
uint32_t planeCount = GetYUVPlaneCount(Format);
uint32_t size = 0;
for(uint32_t p = 0; p < planeCount; p++)
size += GetPlaneByteSize(Width, Height, Depth, Format, mip, p);
return size;
}
ResourceFormat MakeResourceFormat(VkFormat fmt)
{
ResourceFormat ret;
@@ -4259,42 +3805,57 @@ TEST_CASE("Vulkan formats", "[format][vulkan]")
{
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,
})
std::vector<std::pair<VkFormat, std::vector<uint32_t> > > tests = {
{VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, {576, 144, 144}},
{VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, {576, 288}},
{VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, {576, 288, 288}},
{VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, {576, 576}},
{VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, {576, 576, 576}},
{VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, {1152, 288, 288}},
{VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, {1152, 576}},
{VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, {1152, 576, 576}},
{VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, {1152, 1152}},
{VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, {1152, 1152, 1152}},
{VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, {1152, 288, 288}},
{VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, {1152, 576}},
{VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, {1152, 576, 576}},
{VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, {1152, 1152}},
{VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, {1152, 1152, 1152}},
{VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, {1152, 288, 288}},
{VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, {1152, 576}},
{VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, {1152, 576, 576}},
{VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, {1152, 1152}},
{VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, {1152, 1152, 1152}},
};
for(std::pair<VkFormat, std::vector<uint32_t> > e : tests)
{
INFO("Format is " << ToStr(e.first));
for(uint32_t p = 0; p < e.second.size(); p++)
CHECK(e.second[p] == GetPlaneByteSize(width, height, 1, e.first, 0, p));
}
};
SECTION("GetPlaneByteSize is consistent with GetByteSize")
{
const uint32_t width = 24, height = 24;
for(VkFormat f : formats)
{
if(f == VK_FORMAT_UNDEFINED)
continue;
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)