*//*--------------------------------------------------------------------*/
#include "vkImageUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
#include "tcuTextureUtil.hpp"
namespace vk
if (isCompressedFormat(format))
return false;
+ if (isYCbCrFormat(format))
+ return false;
+
const tcu::TextureFormat tcuFormat = mapVkFormat(format);
return tcuFormat.order == tcu::TextureFormat::D || tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS;
}
}
}
+bool isYCbCrFormat (VkFormat format)
+{
+ switch (format)
+ {
+ case VK_FORMAT_G8B8G8R8_422_UNORM_KHR:
+ case VK_FORMAT_B8G8R8G8_422_UNORM_KHR:
+ case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR:
+ case VK_FORMAT_R10X6_UNORM_PACK16_KHR:
+ case VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR:
+ case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR:
+ case VK_FORMAT_R12X4_UNORM_PACK16_KHR:
+ case VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR:
+ case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G16B16G16R16_422_UNORM_KHR:
+ case VK_FORMAT_B16G16R16G16_422_UNORM_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+const PlanarFormatDescription& getYCbCrPlanarFormatDescription (VkFormat format)
+{
+ using tcu::TextureFormat;
+
+ const deUint32 chanR = PlanarFormatDescription::CHANNEL_R;
+ const deUint32 chanG = PlanarFormatDescription::CHANNEL_G;
+ const deUint32 chanB = PlanarFormatDescription::CHANNEL_B;
+ const deUint32 chanA = PlanarFormatDescription::CHANNEL_A;
+
+ const deUint8 unorm = (deUint8)tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
+
+ static const PlanarFormatDescription s_formatInfo[] =
+ {
+ // VK_FORMAT_G8B8G8R8_422_UNORM_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 4, 2, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 24, 8, 4 }, // R
+ { 0, unorm, 0, 8, 2 }, // G
+ { 0, unorm, 8, 8, 4 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_B8G8R8G8_422_UNORM_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 4, 2, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 16, 8, 4 }, // R
+ { 0, unorm, 8, 8, 2 }, // G
+ { 0, unorm, 0, 8, 4 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 1, 1, 1 },
+ { 1, 2, 2 },
+ { 1, 2, 2 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 0, 8, 1 }, // R
+ { 0, unorm, 0, 8, 1 }, // G
+ { 1, unorm, 0, 8, 1 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR
+ {
+ 2, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 1, 1, 1 },
+ { 2, 2, 2 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 1, unorm, 8, 8, 2 }, // R
+ { 0, unorm, 0, 8, 1 }, // G
+ { 1, unorm, 0, 8, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 1, 1, 1 },
+ { 1, 2, 1 },
+ { 1, 2, 1 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 0, 8, 1 }, // R
+ { 0, unorm, 0, 8, 1 }, // G
+ { 1, unorm, 0, 8, 1 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR
+ {
+ 2, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 1, 1, 1 },
+ { 2, 2, 1 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 1, unorm, 8, 8, 2 }, // R
+ { 0, unorm, 0, 8, 1 }, // G
+ { 1, unorm, 0, 8, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 1, 1, 1 },
+ { 1, 1, 1 },
+ { 1, 1, 1 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 0, 8, 1 }, // R
+ { 0, unorm, 0, 8, 1 }, // G
+ { 1, unorm, 0, 8, 1 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_R10X6_UNORM_PACK16_KHR
+ {
+ 1, // planes
+ chanR,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 6, 10, 2 }, // R
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ }
+ },
+ // VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR
+ {
+ 1, // planes
+ chanR|chanG,
+ {
+ // Size WDiv HDiv
+ { 4, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 6, 10, 4 }, // R
+ { 0, unorm, 22, 10, 4 }, // G
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ }
+ },
+ // VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 8, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 6, 10, 8 }, // R
+ { 0, unorm, 22, 10, 8 }, // G
+ { 0, unorm, 38, 10, 8 }, // B
+ { 0, unorm, 54, 10, 8 }, // A
+ }
+ },
+ // VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 8, 2, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 54, 10, 8 }, // R
+ { 0, unorm, 6, 10, 4 }, // G
+ { 0, unorm, 22, 10, 8 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 8, 2, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 38, 10, 8 }, // R
+ { 0, unorm, 22, 10, 4 }, // G
+ { 0, unorm, 6, 10, 8 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 2, 2 },
+ { 2, 2, 2 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 6, 10, 2 }, // R
+ { 0, unorm, 6, 10, 2 }, // G
+ { 1, unorm, 6, 10, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR
+ {
+ 2, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 4, 2, 2 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 1, unorm, 22, 10, 4 }, // R
+ { 0, unorm, 6, 10, 2 }, // G
+ { 1, unorm, 6, 10, 4 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 2, 1 },
+ { 2, 2, 1 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 6, 10, 2 }, // R
+ { 0, unorm, 6, 10, 2 }, // G
+ { 1, unorm, 6, 10, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR
+ {
+ 2, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 4, 2, 1 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 1, unorm, 22, 10, 4 }, // R
+ { 0, unorm, 6, 10, 2 }, // G
+ { 1, unorm, 6, 10, 4 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 1, 1 },
+ { 2, 1, 1 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 6, 10, 2 }, // R
+ { 0, unorm, 6, 10, 2 }, // G
+ { 1, unorm, 6, 10, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_R12X4_UNORM_PACK16_KHR
+ {
+ 1, // planes
+ chanR,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 4, 12, 2 }, // R
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ }
+ },
+ // VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR
+ {
+ 1, // planes
+ chanR|chanG,
+ {
+ // Size WDiv HDiv
+ { 4, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 4, 12, 4 }, // R
+ { 0, unorm, 20, 12, 4 }, // G
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ }
+ },
+ // VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 8, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 4, 12, 8 }, // R
+ { 0, unorm, 20, 12, 8 }, // G
+ { 0, unorm, 36, 12, 8 }, // B
+ { 0, unorm, 52, 12, 8 }, // A
+ }
+ },
+ // VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 8, 2, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 52, 12, 8 }, // R
+ { 0, unorm, 4, 12, 4 }, // G
+ { 0, unorm, 20, 12, 8 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 8, 2, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 36, 12, 8 }, // R
+ { 0, unorm, 20, 12, 4 }, // G
+ { 0, unorm, 4, 12, 8 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 2, 2 },
+ { 2, 2, 2 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 4, 12, 2 }, // R
+ { 0, unorm, 4, 12, 2 }, // G
+ { 1, unorm, 4, 12, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR
+ {
+ 2, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 4, 2, 2 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 1, unorm, 20, 12, 4 }, // R
+ { 0, unorm, 4, 12, 2 }, // G
+ { 1, unorm, 4, 12, 4 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 2, 1 },
+ { 2, 2, 1 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 4, 12, 2 }, // R
+ { 0, unorm, 4, 12, 2 }, // G
+ { 1, unorm, 4, 12, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR
+ {
+ 2, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 4, 2, 1 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 1, unorm, 20, 12, 4 }, // R
+ { 0, unorm, 4, 12, 2 }, // G
+ { 1, unorm, 4, 12, 4 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 1, 1 },
+ { 2, 1, 1 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 4, 12, 2 }, // R
+ { 0, unorm, 4, 12, 2 }, // G
+ { 1, unorm, 4, 12, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G16B16G16R16_422_UNORM_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 8, 2, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 48, 16, 8 }, // R
+ { 0, unorm, 0, 16, 4 }, // G
+ { 0, unorm, 16, 16, 8 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_B16G16R16G16_422_UNORM_KHR
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 8, 2, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 32, 16, 8 }, // R
+ { 0, unorm, 16, 16, 4 }, // G
+ { 0, unorm, 0, 16, 8 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 2, 2 },
+ { 2, 2, 2 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 0, 16, 2 }, // R
+ { 0, unorm, 0, 16, 2 }, // G
+ { 1, unorm, 0, 16, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR
+ {
+ 2, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 4, 2, 2 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 1, unorm, 16, 16, 4 }, // R
+ { 0, unorm, 0, 16, 2 }, // G
+ { 1, unorm, 0, 16, 4 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 2, 1 },
+ { 2, 2, 1 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 0, 16, 2 }, // R
+ { 0, unorm, 0, 16, 2 }, // G
+ { 1, unorm, 0, 16, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR
+ {
+ 2, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 4, 2, 1 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 1, unorm, 16, 16, 4 }, // R
+ { 0, unorm, 0, 16, 2 }, // G
+ { 1, unorm, 0, 16, 4 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ // VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR
+ {
+ 3, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 2, 1, 1 },
+ { 2, 1, 1 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 2, unorm, 0, 16, 2 }, // R
+ { 0, unorm, 0, 16, 2 }, // G
+ { 1, unorm, 0, 16, 2 }, // B
+ { 0, 0, 0, 0, 0 }
+ }
+ },
+ };
+
+ const size_t offset = (size_t)VK_FORMAT_G8B8G8R8_422_UNORM_KHR;
+
+ DE_ASSERT(de::inBounds<size_t>((size_t)format, offset, offset+(size_t)DE_LENGTH_OF_ARRAY(s_formatInfo)));
+
+ return s_formatInfo[(size_t)format-offset];
+}
+
+PlanarFormatDescription getCorePlanarFormatDescription (VkFormat format)
+{
+ const deUint8 unorm = (deUint8)tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
+
+ const deUint8 chanR = (deUint8)PlanarFormatDescription::CHANNEL_R;
+ const deUint8 chanG = (deUint8)PlanarFormatDescription::CHANNEL_G;
+ const deUint8 chanB = (deUint8)PlanarFormatDescription::CHANNEL_B;
+ const deUint8 chanA = (deUint8)PlanarFormatDescription::CHANNEL_A;
+
+ DE_ASSERT(de::inBounds<deUint32>(format, VK_FORMAT_UNDEFINED+1, VK_CORE_FORMAT_LAST));
+
+#if (DE_ENDIANNESS != DE_LITTLE_ENDIAN)
+# error "Big-endian is not supported"
+#endif
+
+ switch (format)
+ {
+ case VK_FORMAT_R8_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR,
+ {
+ // Size WDiv HDiv
+ { 1, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 8, 1 }, // R
+ { 0, 0, 0, 0, 0 }, // G
+ { 0, 0, 0, 0, 0 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R8G8_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 8, 2 }, // R
+ { 0, unorm, 8, 8, 2 }, // G
+ { 0, 0, 0, 0, 0 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R16_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 16, 2 }, // R
+ { 0, 0, 0, 0, 0 }, // G
+ { 0, 0, 0, 0, 0 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R16G16_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG,
+ {
+ // Size WDiv HDiv
+ { 4, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 16, 4 }, // R
+ { 0, unorm, 16, 16, 4 }, // G
+ { 0, 0, 0, 0, 0 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 4, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 11, 4 }, // R
+ { 0, unorm, 11, 11, 4 }, // G
+ { 0, unorm, 22, 10, 4 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R4G4_UNORM_PACK8:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG,
+ {
+ // Size WDiv HDiv
+ { 1, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 4, 4, 1 }, // R
+ { 0, unorm, 0, 4, 1 }, // G
+ { 0, 0, 0, 0, 0 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 12, 4, 2 }, // R
+ { 0, unorm, 8, 4, 2 }, // G
+ { 0, unorm, 4, 4, 2 }, // B
+ { 0, unorm, 0, 4, 2 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 4, 4, 2 }, // R
+ { 0, unorm, 8, 4, 2 }, // G
+ { 0, unorm, 12, 4, 2 }, // B
+ { 0, unorm, 0, 4, 2 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R5G6B5_UNORM_PACK16:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 11, 5, 2 }, // R
+ { 0, unorm, 5, 6, 2 }, // G
+ { 0, unorm, 0, 5, 2 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_B5G6R5_UNORM_PACK16:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 5, 2 }, // R
+ { 0, unorm, 5, 6, 2 }, // G
+ { 0, unorm, 11, 5, 2 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 11, 5, 2 }, // R
+ { 0, unorm, 6, 5, 2 }, // G
+ { 0, unorm, 1, 5, 2 }, // B
+ { 0, unorm, 0, 1, 2 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 1, 5, 2 }, // R
+ { 0, unorm, 6, 5, 2 }, // G
+ { 0, unorm, 11, 5, 2 }, // B
+ { 0, unorm, 0, 1, 2 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 2, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 10, 5, 2 }, // R
+ { 0, unorm, 5, 5, 2 }, // G
+ { 0, unorm, 0, 5, 2 }, // B
+ { 0, unorm, 15, 1, 2 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R8G8B8_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 3, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 8, 3 }, // R
+ { 0, unorm, 8, 8, 3 }, // G
+ { 0, unorm, 16, 8, 3 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_B8G8R8_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 3, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 16, 8, 3 }, // R
+ { 0, unorm, 8, 8, 3 }, // G
+ { 0, unorm, 0, 8, 3 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R8G8B8A8_UNORM:
+ case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 4, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 8, 4 }, // R
+ { 0, unorm, 8, 8, 4 }, // G
+ { 0, unorm, 16, 8, 4 }, // B
+ { 0, unorm, 24, 8, 4 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_B8G8R8A8_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 4, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 16, 8, 4 }, // R
+ { 0, unorm, 8, 8, 4 }, // G
+ { 0, unorm, 0, 8, 4 }, // B
+ { 0, unorm, 24, 8, 4 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 4, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 20, 10, 4 }, // R
+ { 0, unorm, 10, 10, 4 }, // G
+ { 0, unorm, 0, 10, 4 }, // B
+ { 0, unorm, 30, 2, 4 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 4, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 10, 4 }, // R
+ { 0, unorm, 10, 10, 4 }, // G
+ { 0, unorm, 20, 10, 4 }, // B
+ { 0, unorm, 30, 2, 4 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R16G16B16_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB,
+ {
+ // Size WDiv HDiv
+ { 6, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 16, 6 }, // R
+ { 0, unorm, 16, 16, 6 }, // G
+ { 0, unorm, 32, 16, 6 }, // B
+ { 0, 0, 0, 0, 0 } // A
+ }
+ };
+ return desc;
+ }
+
+ case VK_FORMAT_R16G16B16A16_UNORM:
+ {
+ const PlanarFormatDescription desc =
+ {
+ 1, // planes
+ chanR|chanG|chanB|chanA,
+ {
+ // Size WDiv HDiv
+ { 16, 1, 1 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ },
+ {
+ // Plane Type Offs Size Stride
+ { 0, unorm, 0, 16, 8 }, // R
+ { 0, unorm, 16, 16, 8 }, // G
+ { 0, unorm, 32, 16, 8 }, // B
+ { 0, unorm, 48, 16, 8 } // A
+ }
+ };
+ return desc;
+ }
+
+ default:
+ TCU_THROW(InternalError, "Not implemented");
+ }
+}
+
+PlanarFormatDescription getPlanarFormatDescription (VkFormat format)
+{
+ if (isYCbCrFormat(format))
+ return getYCbCrPlanarFormatDescription(format);
+ else
+ return getCorePlanarFormatDescription(format);
+}
+
+int getPlaneCount (VkFormat format)
+{
+ switch (format)
+ {
+ case VK_FORMAT_G8B8G8R8_422_UNORM_KHR:
+ case VK_FORMAT_B8G8R8G8_422_UNORM_KHR:
+ case VK_FORMAT_R10X6_UNORM_PACK16_KHR:
+ case VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR:
+ case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_R12X4_UNORM_PACK16_KHR:
+ case VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR:
+ case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G16B16G16R16_422_UNORM_KHR:
+ case VK_FORMAT_B16G16R16G16_422_UNORM_KHR:
+ return 1;
+
+ case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR:
+ return 2;
+
+ case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR:
+ return 3;
+
+ default:
+ DE_FATAL("Not YCbCr format");
+ return 0;
+ }
+}
+
+VkImageAspectFlagBits getPlaneAspect (deUint32 planeNdx)
+{
+ DE_ASSERT(de::inBounds(planeNdx, 0u, 3u));
+ return (VkImageAspectFlagBits)(VK_IMAGE_ASPECT_PLANE_0_BIT_KHR << planeNdx);
+}
+
+deUint32 getAspectPlaneNdx (VkImageAspectFlagBits flags)
+{
+ switch (flags)
+ {
+ case VK_IMAGE_ASPECT_PLANE_0_BIT_KHR: return 0;
+ case VK_IMAGE_ASPECT_PLANE_1_BIT_KHR: return 1;
+ case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR: return 2;
+ default:
+ DE_FATAL("Invalid plane aspect");
+ return 0;
+ }
+}
+
+bool isChromaSubsampled (VkFormat format)
+{
+ switch (format)
+ {
+ case VK_FORMAT_G8B8G8R8_422_UNORM_KHR:
+ case VK_FORMAT_B8G8R8G8_422_UNORM_KHR:
+ case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR:
+ case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR:
+ case VK_FORMAT_G16B16G16R16_422_UNORM_KHR:
+ case VK_FORMAT_B16G16R16G16_422_UNORM_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR:
+ case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
bool isSupportedByFramework (VkFormat format)
{
if (format == VK_FORMAT_UNDEFINED || format > VK_CORE_FORMAT_LAST)
case FMT_CASE(DS, UNSIGNED_INT_24_8_REV): return VK_FORMAT_D24_UNORM_S8_UINT;
case FMT_CASE(DS, FLOAT_UNSIGNED_INT_24_8_REV): return VK_FORMAT_D32_SFLOAT_S8_UINT;
+
+ case FMT_CASE(R, UNORM_SHORT_10): return VK_FORMAT_R10X6_UNORM_PACK16_KHR;
+ case FMT_CASE(RG, UNORM_SHORT_10): return VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR;
+ case FMT_CASE(RGBA, UNORM_SHORT_10): return VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR;
+
+ case FMT_CASE(R, UNORM_SHORT_12): return VK_FORMAT_R12X4_UNORM_PACK16_KHR;
+ case FMT_CASE(RG, UNORM_SHORT_12): return VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR;
+ case FMT_CASE(RGBA, UNORM_SHORT_12): return VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR;
+
default:
TCU_THROW(InternalError, "Unknown texture format");
}
VkFormat mapCompressedTextureFormat (const tcu::CompressedTexFormat format)
{
// update this mapping if CompressedTexFormat changes
- DE_STATIC_ASSERT(tcu::COMPRESSEDTEXFORMAT_LAST == 39);
+ DE_STATIC_ASSERT(tcu::COMPRESSEDTEXFORMAT_LAST == 55);
switch (format)
{
case tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA: return VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
case tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8: return VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK: return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK: return VK_FORMAT_BC1_RGB_SRGB_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK: return VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK: return VK_FORMAT_BC2_UNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK: return VK_FORMAT_BC2_SRGB_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK: return VK_FORMAT_BC3_UNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK: return VK_FORMAT_BC3_SRGB_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK: return VK_FORMAT_BC4_UNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK: return VK_FORMAT_BC4_SNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK: return VK_FORMAT_BC5_UNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK: return VK_FORMAT_BC5_SNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK: return VK_FORMAT_BC6H_UFLOAT_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK: return VK_FORMAT_BC6H_SFLOAT_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK: return VK_FORMAT_BC7_UNORM_BLOCK;
+ case tcu::COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK: return VK_FORMAT_BC7_SRGB_BLOCK;
+
default:
TCU_THROW(InternalError, "Unknown texture format");
return VK_FORMAT_UNDEFINED;
case VK_FORMAT_A2B10G10R10_UINT_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT_1010102_REV);
case VK_FORMAT_A2B10G10R10_SINT_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT_1010102_REV);
+ // YCbCr formats that can be mapped
+ case VK_FORMAT_R10X6_UNORM_PACK16_KHR: return TextureFormat(TextureFormat::R, TextureFormat::UNORM_SHORT_10);
+ case VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR: return TextureFormat(TextureFormat::RG, TextureFormat::UNORM_SHORT_10);
+ case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_10);
+
+ case VK_FORMAT_R12X4_UNORM_PACK16_KHR: return TextureFormat(TextureFormat::R, TextureFormat::UNORM_SHORT_12);
+ case VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR: return TextureFormat(TextureFormat::RG, TextureFormat::UNORM_SHORT_12);
+ case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_12);
+
default:
TCU_THROW(InternalError, "Unknown image format");
}
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA;
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8;
+ case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK;
+ case VK_FORMAT_BC1_RGB_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK;
+ case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK;
+ case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK;
+ case VK_FORMAT_BC2_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK;
+ case VK_FORMAT_BC2_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK;
+ case VK_FORMAT_BC3_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK;
+ case VK_FORMAT_BC3_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK;
+ case VK_FORMAT_BC4_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK;
+ case VK_FORMAT_BC4_SNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK;
+ case VK_FORMAT_BC5_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK;
+ case VK_FORMAT_BC5_SNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK;
+ case VK_FORMAT_BC6H_UFLOAT_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK;
+ case VK_FORMAT_BC6H_SFLOAT_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK;
+ case VK_FORMAT_BC7_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK;
+ case VK_FORMAT_BC7_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK;
+
default:
TCU_THROW(InternalError, "Unknown image format");
return tcu::COMPRESSEDTEXFORMAT_LAST;
}
}
+tcu::TextureFormat getChannelAccessFormat (tcu::TextureChannelClass type,
+ deUint32 offsetBits,
+ deUint32 sizeBits)
+{
+ using tcu::TextureFormat;
+
+ if (offsetBits == 0)
+ {
+ static const TextureFormat::ChannelType s_size8[tcu::TEXTURECHANNELCLASS_LAST] =
+ {
+ TextureFormat::SNORM_INT8, // snorm
+ TextureFormat::UNORM_INT8, // unorm
+ TextureFormat::SIGNED_INT8, // sint
+ TextureFormat::UNSIGNED_INT8, // uint
+ TextureFormat::CHANNELTYPE_LAST, // float
+ };
+ static const TextureFormat::ChannelType s_size16[tcu::TEXTURECHANNELCLASS_LAST] =
+ {
+ TextureFormat::SNORM_INT16, // snorm
+ TextureFormat::UNORM_INT16, // unorm
+ TextureFormat::SIGNED_INT16, // sint
+ TextureFormat::UNSIGNED_INT16, // uint
+ TextureFormat::HALF_FLOAT, // float
+ };
+ static const TextureFormat::ChannelType s_size32[tcu::TEXTURECHANNELCLASS_LAST] =
+ {
+ TextureFormat::SNORM_INT32, // snorm
+ TextureFormat::UNORM_INT32, // unorm
+ TextureFormat::SIGNED_INT32, // sint
+ TextureFormat::UNSIGNED_INT32, // uint
+ TextureFormat::FLOAT, // float
+ };
+
+ TextureFormat::ChannelType chnType = TextureFormat::CHANNELTYPE_LAST;
+
+ if (sizeBits == 8)
+ chnType = s_size8[type];
+ else if (sizeBits == 16)
+ chnType = s_size16[type];
+ else if (sizeBits == 32)
+ chnType = s_size32[type];
+
+ if (chnType != TextureFormat::CHANNELTYPE_LAST)
+ return TextureFormat(TextureFormat::R, chnType);
+ }
+ else
+ {
+ if (type == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT &&
+ offsetBits == 6 &&
+ sizeBits == 10)
+ return TextureFormat(TextureFormat::R, TextureFormat::UNORM_SHORT_10);
+ else if (type == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT &&
+ offsetBits == 4 &&
+ sizeBits == 12)
+ return TextureFormat(TextureFormat::R, TextureFormat::UNORM_SHORT_12);
+ }
+
+ TCU_THROW(InternalError, "Channel access format is not supported");
+}
+
+tcu::PixelBufferAccess getChannelAccess (const PlanarFormatDescription& formatInfo,
+ const tcu::UVec2& size,
+ const deUint32* planeRowPitches,
+ void* const* planePtrs,
+ deUint32 channelNdx)
+{
+ DE_ASSERT(formatInfo.hasChannelNdx(channelNdx));
+
+ const deUint32 planeNdx = formatInfo.channels[channelNdx].planeNdx;
+ const deUint32 planeOffsetBytes = formatInfo.channels[channelNdx].offsetBits / 8;
+ const deUint32 valueOffsetBits = formatInfo.channels[channelNdx].offsetBits % 8;
+ const deUint32 pixelStrideBytes = formatInfo.channels[channelNdx].strideBytes;
+
+ DE_ASSERT(size.x() % formatInfo.planes[planeNdx].widthDivisor == 0);
+ DE_ASSERT(size.y() % formatInfo.planes[planeNdx].heightDivisor == 0);
+
+ deUint32 accessWidth = size.x() / formatInfo.planes[planeNdx].widthDivisor;
+ const deUint32 accessHeight = size.y() / formatInfo.planes[planeNdx].heightDivisor;
+ const deUint32 elementSizeBytes = formatInfo.planes[planeNdx].elementSizeBytes;
+
+ const deUint32 rowPitch = planeRowPitches[planeNdx];
+
+ if (pixelStrideBytes != elementSizeBytes)
+ {
+ DE_ASSERT(elementSizeBytes % pixelStrideBytes == 0);
+ accessWidth *= elementSizeBytes/pixelStrideBytes;
+ }
+
+ return tcu::PixelBufferAccess(getChannelAccessFormat((tcu::TextureChannelClass)formatInfo.channels[channelNdx].type,
+ valueOffsetBits,
+ formatInfo.channels[channelNdx].sizeBits),
+ tcu::IVec3((int)accessWidth, (int)accessHeight, 1),
+ tcu::IVec3((int)pixelStrideBytes, (int)rowPitch, 0),
+ (deUint8*)planePtrs[planeNdx] + planeOffsetBytes);
+}
+
+
+tcu::ConstPixelBufferAccess getChannelAccess (const PlanarFormatDescription& formatInfo,
+ const tcu::UVec2& size,
+ const deUint32* planeRowPitches,
+ const void* const* planePtrs,
+ deUint32 channelNdx)
+{
+ return getChannelAccess(formatInfo, size, planeRowPitches, const_cast<void* const*>(planePtrs), channelNdx);
+}
+
void imageUtilSelfTest (void)
{
for (int formatNdx = 0; formatNdx < VK_CORE_FORMAT_LAST; formatNdx++)
DE_TEST_ASSERT(format == remappedFormat);
}
}
+
+ for (int formatNdx = VK_FORMAT_G8B8G8R8_422_UNORM_KHR; formatNdx <= VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR; formatNdx++)
+ {
+ const VkFormat format = (VkFormat)formatNdx;
+ const PlanarFormatDescription& info = getPlanarFormatDescription(format);
+
+ DE_TEST_ASSERT(isYCbCrFormat(format));
+ DE_TEST_ASSERT(de::inRange<deUint8>(info.numPlanes, 1u, 3u));
+ DE_TEST_ASSERT(info.numPlanes == getPlaneCount(format));
+ }
}
VkFilter mapFilterMode (tcu::Sampler::FilterMode filterMode)
// \note minLod & maxLod are not supported by tcu::Sampler. LOD must be clamped
// before passing it to tcu::Texture*::sample*()
+ tcu::Sampler::ReductionMode reductionMode = tcu::Sampler::WEIGHTED_AVERAGE;
+
+ void const *pNext = samplerCreateInfo.pNext;
+ while (pNext != DE_NULL)
+ {
+ const VkStructureType nextType = *reinterpret_cast<const VkStructureType*>(pNext);
+ switch (nextType)
+ {
+ case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT:
+ {
+ const VkSamplerReductionModeCreateInfoEXT reductionModeCreateInfo = *reinterpret_cast<const VkSamplerReductionModeCreateInfoEXT*>(pNext);
+ reductionMode = mapVkSamplerReductionMode(reductionModeCreateInfo.reductionMode);
+ pNext = reinterpret_cast<const VkSamplerReductionModeCreateInfoEXT*>(pNext)->pNext;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO:
+ pNext = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(pNext)->pNext;
+ break;
+ default:
+ TCU_FAIL("Unrecognized sType in chained sampler create info");
+ }
+ }
+
+
+
tcu::Sampler sampler(mapVkSamplerAddressMode(samplerCreateInfo.addressModeU),
mapVkSamplerAddressMode(samplerCreateInfo.addressModeV),
mapVkSamplerAddressMode(samplerCreateInfo.addressModeW),
: tcu::Sampler::COMPAREMODE_NONE,
0,
tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
- true);
+ true,
+ tcu::Sampler::MODE_DEPTH,
+ reductionMode);
if (samplerCreateInfo.anisotropyEnable)
TCU_THROW(InternalError, "Anisotropic filtering is not supported by tcu::Sampler");
return tcu::Sampler::WRAPMODE_LAST;
}
+tcu::Sampler::ReductionMode mapVkSamplerReductionMode (VkSamplerReductionModeEXT reductionMode)
+{
+ switch (reductionMode)
+ {
+ case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT: return tcu::Sampler::WEIGHTED_AVERAGE;
+ case VK_SAMPLER_REDUCTION_MODE_MIN_EXT: return tcu::Sampler::MIN;
+ case VK_SAMPLER_REDUCTION_MODE_MAX_EXT: return tcu::Sampler::MAX;
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return tcu::Sampler::REDUCTIONMODE_LAST;
+}
+
tcu::Sampler::FilterMode mapVkMinTexFilter (VkFilter filter, VkSamplerMipmapMode mipMode)
{
switch (filter)
}
}
+VkImageAspectFlags getImageAspectFlags (const tcu::TextureFormat textureFormat)
+{
+ VkImageAspectFlags imageAspectFlags = 0;
+
+ if (tcu::hasDepthComponent(textureFormat.order))
+ imageAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ if (tcu::hasStencilComponent(textureFormat.order))
+ imageAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ if (imageAspectFlags == 0)
+ imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ return imageAspectFlags;
+}
+
+VkExtent3D mipLevelExtents (const VkExtent3D& baseExtents, const deUint32 mipLevel)
+{
+ VkExtent3D result;
+
+ result.width = std::max(baseExtents.width >> mipLevel, 1u);
+ result.height = std::max(baseExtents.height >> mipLevel, 1u);
+ result.depth = std::max(baseExtents.depth >> mipLevel, 1u);
+
+ return result;
+}
+
+tcu::UVec3 alignedDivide (const VkExtent3D& extent, const VkExtent3D& divisor)
+{
+ tcu::UVec3 result;
+
+ result.x() = extent.width / divisor.width + ((extent.width % divisor.width != 0) ? 1u : 0u);
+ result.y() = extent.height / divisor.height + ((extent.height % divisor.height != 0) ? 1u : 0u);
+ result.z() = extent.depth / divisor.depth + ((extent.depth % divisor.depth != 0) ? 1u : 0u);
+
+ return result;
+}
+
+void copyBufferToImage (const DeviceInterface& vk,
+ VkDevice device,
+ VkQueue queue,
+ deUint32 queueFamilyIndex,
+ const VkBuffer& buffer,
+ deUint32 bufferSize,
+ const std::vector<VkBufferImageCopy>& copyRegions,
+ const VkSemaphore* waitSemaphore,
+ VkImageAspectFlags imageAspectFlags,
+ deUint32 mipLevels,
+ deUint32 arrayLayers,
+ VkImage destImage,
+ VkImageLayout destImageLayout)
+{
+ Move<VkCommandPool> cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
+ Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ Move<VkFence> fence = createFence(vk, device);
+
+ // Barriers for copying buffer to image
+ const VkBufferMemoryBarrier preBufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ buffer, // VkBuffer buffer;
+ 0u, // VkDeviceSize offset;
+ bufferSize // VkDeviceSize size;
+ };
+
+ const VkImageMemoryBarrier preImageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ destImage, // VkImage image;
+ { // VkImageSubresourceRange subresourceRange;
+ imageAspectFlags, // VkImageAspectFlags aspect;
+ 0u, // deUint32 baseMipLevel;
+ mipLevels, // deUint32 mipLevels;
+ 0u, // deUint32 baseArraySlice;
+ arrayLayers // deUint32 arraySize;
+ }
+ };
+
+ const VkImageMemoryBarrier postImageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
+ destImageLayout, // VkImageLayout newLayout;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ destImage, // VkImage image;
+ { // VkImageSubresourceRange subresourceRange;
+ imageAspectFlags, // VkImageAspectFlags aspect;
+ 0u, // deUint32 baseMipLevel;
+ mipLevels, // deUint32 mipLevels;
+ 0u, // deUint32 baseArraySlice;
+ arrayLayers // deUint32 arraySize;
+ }
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
+ (const VkCommandBufferInheritanceInfo*)DE_NULL,
+ };
+
+ // Copy buffer to image
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier);
+ vk.cmdCopyBufferToImage(*cmdBuffer, buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), copyRegions.data());
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
+ VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+ const VkPipelineStageFlags pipelineStageFlags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
+
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ waitSemaphore ? 1u : 0u, // deUint32 waitSemaphoreCount;
+ waitSemaphore, // const VkSemaphore* pWaitSemaphores;
+ &pipelineStageFlags, // const VkPipelineStageFlags* pWaitDstStageMask;
+ 1u, // deUint32 commandBufferCount;
+ &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
+ 0u, // deUint32 signalSemaphoreCount;
+ DE_NULL // const VkSemaphore* pSignalSemaphores;
+ };
+
+ try
+ {
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+ VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull) /* infinity */));
+ }
+ catch (...)
+ {
+ VK_CHECK(vk.deviceWaitIdle(device));
+ throw;
+ }
+}
+
+void allocateAndBindSparseImage (const DeviceInterface& vk,
+ VkDevice device,
+ const VkPhysicalDevice physicalDevice,
+ const InstanceInterface& instance,
+ const VkImageCreateInfo& imageCreateInfo,
+ const VkSemaphore& signalSemaphore,
+ VkQueue queue,
+ Allocator& allocator,
+ std::vector<de::SharedPtr<Allocation> >& allocations,
+ tcu::TextureFormat format,
+ VkImage destImage)
+{
+ const VkImageAspectFlags imageAspectFlags = getImageAspectFlags(format);
+ const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
+ const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
+ deUint32 sparseMemoryReqCount = 0;
+
+ // Check if the image format supports sparse operations
+ if (!checkSparseImageFormatSupport(physicalDevice, instance, imageCreateInfo))
+ TCU_THROW(NotSupportedError, "The image format does not support sparse operations.");
+
+ vk.getImageSparseMemoryRequirements(device, destImage, &sparseMemoryReqCount, DE_NULL);
+
+ DE_ASSERT(sparseMemoryReqCount != 0);
+
+ std::vector<VkSparseImageMemoryRequirements> sparseImageMemoryRequirements;
+ sparseImageMemoryRequirements.resize(sparseMemoryReqCount);
+
+ vk.getImageSparseMemoryRequirements(device, destImage, &sparseMemoryReqCount, &sparseImageMemoryRequirements[0]);
+
+ const deUint32 noMatchFound = ~((deUint32)0);
+
+ deUint32 aspectIndex = noMatchFound;
+ for (deUint32 memoryReqNdx = 0; memoryReqNdx < sparseMemoryReqCount; ++memoryReqNdx)
+ {
+ if (sparseImageMemoryRequirements[memoryReqNdx].formatProperties.aspectMask == imageAspectFlags)
+ {
+ aspectIndex = memoryReqNdx;
+ break;
+ }
+ }
+
+ deUint32 metadataAspectIndex = noMatchFound;
+ for (deUint32 memoryReqNdx = 0; memoryReqNdx < sparseMemoryReqCount; ++memoryReqNdx)
+ {
+ if (sparseImageMemoryRequirements[memoryReqNdx].formatProperties.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)
+ {
+ metadataAspectIndex = memoryReqNdx;
+ break;
+ }
+ }
+
+ if (aspectIndex == noMatchFound)
+ TCU_THROW(NotSupportedError, "Required image aspect not supported.");
+
+ const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vk, device, destImage);
+
+ deUint32 memoryType = noMatchFound;
+ for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx)
+ {
+ if ((memoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
+ MemoryRequirement::Any.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags))
+ {
+ memoryType = memoryTypeNdx;
+ break;
+ }
+ }
+
+ if (memoryType == noMatchFound)
+ TCU_THROW(NotSupportedError, "No matching memory type found.");
+
+ if (memoryRequirements.size > deviceProperties.limits.sparseAddressSpaceSize)
+ TCU_THROW(NotSupportedError, "Required memory size for sparse resource exceeds device limits.");
+
+ const VkSparseImageMemoryRequirements aspectRequirements = sparseImageMemoryRequirements[aspectIndex];
+ const VkExtent3D imageGranularity = aspectRequirements.formatProperties.imageGranularity;
+
+ std::vector<VkSparseImageMemoryBind> imageResidencyMemoryBinds;
+ std::vector<VkSparseMemoryBind> imageMipTailMemoryBinds;
+
+ for (deUint32 layerNdx = 0; layerNdx < imageCreateInfo.arrayLayers; ++layerNdx)
+ {
+ for (deUint32 mipLevelNdx = 0; mipLevelNdx < aspectRequirements.imageMipTailFirstLod; ++mipLevelNdx)
+ {
+ const VkExtent3D mipExtent = mipLevelExtents(imageCreateInfo.extent, mipLevelNdx);
+ const tcu::UVec3 numSparseBinds = alignedDivide(mipExtent, imageGranularity);
+ const tcu::UVec3 lastBlockExtent = tcu::UVec3(mipExtent.width % imageGranularity.width ? mipExtent.width % imageGranularity.width : imageGranularity.width,
+ mipExtent.height % imageGranularity.height ? mipExtent.height % imageGranularity.height : imageGranularity.height,
+ mipExtent.depth % imageGranularity.depth ? mipExtent.depth % imageGranularity.depth : imageGranularity.depth );
+
+ for (deUint32 z = 0; z < numSparseBinds.z(); ++z)
+ for (deUint32 y = 0; y < numSparseBinds.y(); ++y)
+ for (deUint32 x = 0; x < numSparseBinds.x(); ++x)
+ {
+ const VkMemoryRequirements allocRequirements =
+ {
+ // 28.7.5 alignment shows the block size in bytes
+ memoryRequirements.alignment, // VkDeviceSize size;
+ memoryRequirements.alignment, // VkDeviceSize alignment;
+ memoryRequirements.memoryTypeBits, // uint32_t memoryTypeBits;
+ };
+
+ de::SharedPtr<Allocation> allocation(allocator.allocate(allocRequirements, MemoryRequirement::Any).release());
+ allocations.push_back(allocation);
+
+ VkOffset3D offset;
+ offset.x = x*imageGranularity.width;
+ offset.y = y*imageGranularity.height;
+ offset.z = z*imageGranularity.depth;
+
+ VkExtent3D extent;
+ extent.width = (x == numSparseBinds.x() - 1) ? lastBlockExtent.x() : imageGranularity.width;
+ extent.height = (y == numSparseBinds.y() - 1) ? lastBlockExtent.y() : imageGranularity.height;
+ extent.depth = (z == numSparseBinds.z() - 1) ? lastBlockExtent.z() : imageGranularity.depth;
+
+ const VkSparseImageMemoryBind imageMemoryBind =
+ {
+ {
+ imageAspectFlags, // VkImageAspectFlags aspectMask;
+ mipLevelNdx, // uint32_t mipLevel;
+ layerNdx, // uint32_t arrayLayer;
+ }, // VkImageSubresource subresource;
+ offset, // VkOffset3D offset;
+ extent, // VkExtent3D extent;
+ allocation->getMemory(), // VkDeviceMemory memory;
+ allocation->getOffset(), // VkDeviceSize memoryOffset;
+ 0u, // VkSparseMemoryBindFlags flags;
+ };
+
+ imageResidencyMemoryBinds.push_back(imageMemoryBind);
+ }
+ }
+
+ // Handle MIP tail. There are two cases to consider here:
+ //
+ // 1) VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT is requested by the driver: each layer needs a separate tail.
+ // 2) otherwise: only one tail is needed.
+ if (aspectRequirements.imageMipTailSize > 0)
+ {
+ if (layerNdx == 0 || (aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) == 0)
+ {
+ const VkMemoryRequirements allocRequirements =
+ {
+ aspectRequirements.imageMipTailSize, // VkDeviceSize size;
+ memoryRequirements.alignment, // VkDeviceSize alignment;
+ memoryRequirements.memoryTypeBits, // uint32_t memoryTypeBits;
+ };
+
+ const de::SharedPtr<Allocation> allocation(allocator.allocate(allocRequirements, MemoryRequirement::Any).release());
+
+ const VkSparseMemoryBind imageMipTailMemoryBind =
+ {
+ aspectRequirements.imageMipTailOffset + layerNdx * aspectRequirements.imageMipTailStride, // VkDeviceSize resourceOffset;
+ aspectRequirements.imageMipTailSize, // VkDeviceSize size;
+ allocation->getMemory(), // VkDeviceMemory memory;
+ allocation->getOffset(), // VkDeviceSize memoryOffset;
+ 0u, // VkSparseMemoryBindFlags flags;
+ };
+
+ allocations.push_back(allocation);
+
+ imageMipTailMemoryBinds.push_back(imageMipTailMemoryBind);
+ }
+ }
+
+ // Handle Metadata. Similarly to MIP tail in aspectRequirements, there are two cases to consider here:
+ //
+ // 1) VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT is requested by the driver: each layer needs a separate tail.
+ // 2) otherwise:
+ if (metadataAspectIndex != noMatchFound)
+ {
+ const VkSparseImageMemoryRequirements metadataAspectRequirements = sparseImageMemoryRequirements[metadataAspectIndex];
+
+ if (layerNdx == 0 || (metadataAspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) == 0)
+ {
+ const VkMemoryRequirements metadataAllocRequirements =
+ {
+ metadataAspectRequirements.imageMipTailSize, // VkDeviceSize size;
+ memoryRequirements.alignment, // VkDeviceSize alignment;
+ memoryRequirements.memoryTypeBits, // uint32_t memoryTypeBits;
+ };
+ const de::SharedPtr<Allocation> metadataAllocation(allocator.allocate(metadataAllocRequirements, MemoryRequirement::Any).release());
+
+ const VkSparseMemoryBind metadataMipTailMemoryBind =
+ {
+ metadataAspectRequirements.imageMipTailOffset +
+ layerNdx * metadataAspectRequirements.imageMipTailStride, // VkDeviceSize resourceOffset;
+ metadataAspectRequirements.imageMipTailSize, // VkDeviceSize size;
+ metadataAllocation->getMemory(), // VkDeviceMemory memory;
+ metadataAllocation->getOffset(), // VkDeviceSize memoryOffset;
+ VK_SPARSE_MEMORY_BIND_METADATA_BIT // VkSparseMemoryBindFlags flags;
+ };
+
+ allocations.push_back(metadataAllocation);
+
+ imageMipTailMemoryBinds.push_back(metadataMipTailMemoryBind);
+ }
+ }
+ }
+
+ VkBindSparseInfo bindSparseInfo =
+ {
+ VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, //VkStructureType sType;
+ DE_NULL, //const void* pNext;
+ 0u, //deUint32 waitSemaphoreCount;
+ DE_NULL, //const VkSemaphore* pWaitSemaphores;
+ 0u, //deUint32 bufferBindCount;
+ DE_NULL, //const VkSparseBufferMemoryBindInfo* pBufferBinds;
+ 0u, //deUint32 imageOpaqueBindCount;
+ DE_NULL, //const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
+ 0u, //deUint32 imageBindCount;
+ DE_NULL, //const VkSparseImageMemoryBindInfo* pImageBinds;
+ 1u, //deUint32 signalSemaphoreCount;
+ &signalSemaphore //const VkSemaphore* pSignalSemaphores;
+ };
+
+ VkSparseImageMemoryBindInfo imageResidencyBindInfo;
+ VkSparseImageOpaqueMemoryBindInfo imageMipTailBindInfo;
+
+ if (imageResidencyMemoryBinds.size() > 0)
+ {
+ imageResidencyBindInfo.image = destImage;
+ imageResidencyBindInfo.bindCount = static_cast<deUint32>(imageResidencyMemoryBinds.size());
+ imageResidencyBindInfo.pBinds = &imageResidencyMemoryBinds[0];
+
+ bindSparseInfo.imageBindCount = 1u;
+ bindSparseInfo.pImageBinds = &imageResidencyBindInfo;
+ }
+
+ if (imageMipTailMemoryBinds.size() > 0)
+ {
+ imageMipTailBindInfo.image = destImage;
+ imageMipTailBindInfo.bindCount = static_cast<deUint32>(imageMipTailMemoryBinds.size());
+ imageMipTailBindInfo.pBinds = &imageMipTailMemoryBinds[0];
+
+ bindSparseInfo.imageOpaqueBindCount = 1u;
+ bindSparseInfo.pImageOpaqueBinds = &imageMipTailBindInfo;
+ }
+
+ VK_CHECK(vk.queueBindSparse(queue, 1u, &bindSparseInfo, DE_NULL));
+}
+
+bool checkSparseImageFormatSupport (const VkPhysicalDevice physicalDevice,
+ const InstanceInterface& instance,
+ const VkImageCreateInfo& imageCreateInfo)
+{
+ const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec =
+ getPhysicalDeviceSparseImageFormatProperties(instance, physicalDevice, imageCreateInfo.format, imageCreateInfo.imageType, imageCreateInfo.samples, imageCreateInfo.usage, imageCreateInfo.tiling);
+
+ return (sparseImageFormatPropVec.size() != 0);
+}
+
} // vk