Support VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
... to support AHARDWAREBUFFER_FORMAT_YCbCr_P010 sampling for
client composition (SurfaceFlinger composition using OpenGL)
which occurs when camera produces HDR P010 buffers.
Bug: b/219756793
Test: launch Cuttlefish and run Camera2Video sample app
Test: dEQP-VK.ycbcr.format.*
Change-Id: I5e2567a88df134b71ce75b554c5994a755173e87
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/63748
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Presubmit-Ready: Jason Macnak <natsu@google.com>
Tested-by: Jason Macnak <natsu@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Commit-Queue: Jason Macnak <natsu@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 510d062..d091ea5 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -1733,48 +1733,95 @@
Pointer<Byte> bufferV = *Pointer<Pointer<Byte>>(mipmap + 2 * sizeof(Mipmap) + OFFSET(Mipmap, buffer));
// Luminance
- Int c0 = Int(bufferY[index[0]]);
- Int c1 = Int(bufferY[index[1]]);
- Int c2 = Int(bufferY[index[2]]);
- Int c3 = Int(bufferY[index[3]]);
- c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
- UShort4 Y = As<UShort4>(Unpack(As<Byte4>(c0)));
-
- UShort4 Cb, Cr;
+ UShort4 Y;
+ {
+ switch(state.textureFormat)
+ {
+ case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+ case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ {
+ Int c0 = Int(bufferY[index[0]]);
+ Int c1 = Int(bufferY[index[1]]);
+ Int c2 = Int(bufferY[index[2]]);
+ Int c3 = Int(bufferY[index[3]]);
+ c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
+ Y = As<UShort4>(Unpack(As<Byte4>(c0)));
+ }
+ break;
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+ {
+ Y = Insert(Y, Pointer<UShort>(bufferY)[index[0]], 0); // TODO: Insert(UShort4, UShort)
+ Y = Insert(Y, Pointer<UShort>(bufferY)[index[1]], 1);
+ Y = Insert(Y, Pointer<UShort>(bufferY)[index[2]], 2);
+ Y = Insert(Y, Pointer<UShort>(bufferY)[index[3]], 3);
+ // Top 10 bits of each 16 bits:
+ Y = (Y & UShort4(0xFFC0u)) >> 6;
+ // Scale from 10 bits to 16 bits:
+ Y = Y << 6;
+ }
+ break;
+ default:
+ UNSUPPORTED("state.textureFormat %d", (int)state.textureFormat);
+ break;
+ }
+ }
// Chroma
+ UShort4 Cb, Cr;
{
computeIndices(index, uuuu, vvvv, wwww, layerIndex, offset, sample, mipmap + sizeof(Mipmap));
UShort4 U, V;
- if(state.textureFormat == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM)
+ switch(state.textureFormat)
{
- c0 = Int(bufferU[index[0]]);
- c1 = Int(bufferU[index[1]]);
- c2 = Int(bufferU[index[2]]);
- c3 = Int(bufferU[index[3]]);
- c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
- U = As<UShort4>(Unpack(As<Byte4>(c0)));
+ case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+ {
+ Int c0 = Int(bufferU[index[0]]);
+ Int c1 = Int(bufferU[index[1]]);
+ Int c2 = Int(bufferU[index[2]]);
+ Int c3 = Int(bufferU[index[3]]);
+ c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
+ U = As<UShort4>(Unpack(As<Byte4>(c0)));
- c0 = Int(bufferV[index[0]]);
- c1 = Int(bufferV[index[1]]);
- c2 = Int(bufferV[index[2]]);
- c3 = Int(bufferV[index[3]]);
- c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
- V = As<UShort4>(Unpack(As<Byte4>(c0)));
- }
- else if(state.textureFormat == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM)
- {
- Short4 UV;
- UV = Insert(UV, Pointer<Short>(bufferU)[index[0]], 0); // TODO: Insert(UShort4, UShort)
- UV = Insert(UV, Pointer<Short>(bufferU)[index[1]], 1);
- UV = Insert(UV, Pointer<Short>(bufferU)[index[2]], 2);
- UV = Insert(UV, Pointer<Short>(bufferU)[index[3]], 3);
- U = (UV & Short4(0x00FFu)) | (UV << 8);
- V = (UV & Short4(0xFF00u)) | As<Short4>(As<UShort4>(UV) >> 8);
- }
- else
+ c0 = Int(bufferV[index[0]]);
+ c1 = Int(bufferV[index[1]]);
+ c2 = Int(bufferV[index[2]]);
+ c3 = Int(bufferV[index[3]]);
+ c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
+ V = As<UShort4>(Unpack(As<Byte4>(c0)));
+ }
+ break;
+ case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ {
+ Short4 UV;
+ UV = Insert(UV, Pointer<Short>(bufferU)[index[0]], 0); // TODO: Insert(UShort4, UShort)
+ UV = Insert(UV, Pointer<Short>(bufferU)[index[1]], 1);
+ UV = Insert(UV, Pointer<Short>(bufferU)[index[2]], 2);
+ UV = Insert(UV, Pointer<Short>(bufferU)[index[3]], 3);
+ U = (UV & Short4(0x00FFu)) | (UV << 8);
+ V = (UV & Short4(0xFF00u)) | As<Short4>(As<UShort4>(UV) >> 8);
+ }
+ break;
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+ {
+ UInt4 UV;
+ UV = Insert(UV, Pointer<UInt>(bufferU)[index[0]], 0);
+ UV = Insert(UV, Pointer<UInt>(bufferU)[index[1]], 1);
+ UV = Insert(UV, Pointer<UInt>(bufferU)[index[2]], 2);
+ UV = Insert(UV, Pointer<UInt>(bufferU)[index[3]], 3);
+ // Top 10 bits of first 16 bits:
+ U = UShort4((UV & UInt4(0x0000FFC0u)) >> 6); // TODO: UnpackLower(UInt4)
+ // Top 10 bits of second 16 bits:
+ V = UShort4((UV & UInt4(0xFFC00000u)) >> 22); // TODO: UnpackUpper(UInt4)
+ // Scale from 10 bits to 16 bits:
+ U = U << 6;
+ V = V << 6;
+ }
+ break;
+ default:
UNSUPPORTED("state.textureFormat %d", (int)state.textureFormat);
+ break;
+ }
if(!state.swappedChroma)
{
@@ -2574,6 +2621,7 @@
{
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
return sw::float4(0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF);
default:
break;
diff --git a/src/Reactor/Reactor.cpp b/src/Reactor/Reactor.cpp
index 2f2b336..41268a9 100644
--- a/src/Reactor/Reactor.cpp
+++ b/src/Reactor/Reactor.cpp
@@ -2138,6 +2138,11 @@
return RValue<UShort4>(Nucleus::createNot(val.value()));
}
+RValue<UShort4> Insert(RValue<UShort4> val, RValue<UShort> element, int i)
+{
+ return RValue<UShort4>(Nucleus::createInsertElement(val.value(), element.value(), i));
+}
+
Short8::Short8(short c)
{
int64_t constantVector[8] = { c, c, c, c, c, c, c, c };
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index 70ab92c..453684e 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -1050,6 +1050,7 @@
// RValue<UShort4> operator--(UShort4 &val, int); // Post-decrement
// const UShort4 &operator--(UShort4 &val); // Pre-decrement
+RValue<UShort4> Insert(RValue<UShort4> val, RValue<UShort> element, int i);
RValue<UShort4> Max(RValue<UShort4> x, RValue<UShort4> y);
RValue<UShort4> Min(RValue<UShort4> x, RValue<UShort4> y);
RValue<UShort4> AddSat(RValue<UShort4> x, RValue<UShort4> y);
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index dc38d8e..8fe7e31 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -786,9 +786,15 @@
position += Bytes.size();
}
- uint64_t tell() const override { return position; }
+ uint64_t tell() const override
+ {
+ return position;
+ }
- void seek(uint64_t Off) override { position = Off; }
+ void seek(uint64_t Off) override
+ {
+ position = Off;
+ }
std::vector<EntryPoint> loadImageAndGetEntryPoints(const std::vector<const char *> &functionNames)
{
@@ -2839,11 +2845,6 @@
return RValue<UShort>(Nucleus::createExtractElement(val.value(), UShort::type(), i));
}
-RValue<UShort4> Insert(RValue<UShort4> val, RValue<UShort> element, int i)
-{
- return RValue<UShort4>(Nucleus::createInsertElement(val.value(), element.value(), i));
-}
-
RValue<UShort4> operator<<(RValue<UShort4> lhs, unsigned char rhs)
{
RR_DEBUG_INFO_UPDATE_LOC();
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
index 7e57476..3efbafd 100644
--- a/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
+++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
@@ -53,6 +53,8 @@
return AHARDWAREBUFFER_FORMAT_S8_UINT;
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+ return AHARDWAREBUFFER_FORMAT_YCbCr_P010;
default:
UNSUPPORTED("AHardwareBufferExternalMemory::VkFormat %d", int(format));
return 0;
@@ -380,6 +382,8 @@
case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
case AHARDWAREBUFFER_FORMAT_YV12:
return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
+ case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
+ return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
default:
UNSUPPORTED("AHardwareBufferExternalMemory::AHardwareBuffer_Format %d", int(ahbFormat));
return VK_FORMAT_UNDEFINED;
@@ -401,7 +405,8 @@
// YUV formats are not listed in the AHardwareBuffer Format Equivalence table in the Vulkan spec.
// Clients must use VkExternalFormatANDROID.
- if(pFormat->format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM)
+ if(pFormat->format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM ||
+ pFormat->format == VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16)
{
pFormat->format = VK_FORMAT_UNDEFINED;
}
@@ -472,6 +477,7 @@
{
case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
case AHARDWAREBUFFER_FORMAT_YV12:
+ case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
switch(aspect)
{
case VK_IMAGE_ASPECT_PLANE_0_BIT:
@@ -500,6 +506,7 @@
{
case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
case AHARDWAREBUFFER_FORMAT_YV12:
+ case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
switch(aspect)
{
case VK_IMAGE_ASPECT_PLANE_0_BIT:
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp
index f36e351..d551bd1 100644
--- a/src/Vulkan/VkFormat.cpp
+++ b/src/Vulkan/VkFormat.cpp
@@ -47,6 +47,7 @@
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
return true;
default:
// sRGB encoded formats are also unsigned normalized.
@@ -157,6 +158,7 @@
aspects = VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT;
break;
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
aspects = VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT;
break;
default:
@@ -219,6 +221,8 @@
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
return VK_FORMAT_R8_UNORM;
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+ return VK_FORMAT_R10X6_UNORM_PACK16;
default:
UNSUPPORTED("format %d", int(format));
break;
@@ -234,6 +238,8 @@
case VK_FORMAT_R8G8_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
return VK_FORMAT_R8G8_UNORM;
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+ return VK_FORMAT_R10X6G10X6_UNORM_2PACK16;
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
default:
@@ -456,6 +462,7 @@
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
return false;
case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_R16G16_SFLOAT:
@@ -487,6 +494,7 @@
{
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
return true;
default:
return false;
@@ -1225,6 +1233,7 @@
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
case VK_FORMAT_BC6H_UFLOAT_BLOCK:
@@ -1490,6 +1499,7 @@
// expects chroma components to be in range [-0.5, 0.5]
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
return false;
case VK_FORMAT_R8_SNORM:
case VK_FORMAT_R8_USCALED:
@@ -1565,6 +1575,7 @@
case VK_FORMAT_R8G8_UINT:
case VK_FORMAT_R8G8_SINT:
case VK_FORMAT_R8G8_SRGB:
+ case VK_FORMAT_R10X6_UNORM_PACK16:
return 2;
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_R8G8B8A8_SNORM:
@@ -1599,6 +1610,7 @@
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
case VK_FORMAT_A2B10G10R10_UINT_PACK32:
case VK_FORMAT_A2B10G10R10_SINT_PACK32:
+ case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
return 4;
case VK_FORMAT_R16_UNORM:
case VK_FORMAT_R16_SNORM:
@@ -1738,6 +1750,9 @@
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
// TODO: ASSERT to ensure this is only called per-aspect?
return 1; // Y plane only
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+ // TODO: ASSERT to ensure this is only called per-aspect?
+ return 2; // Y plane only
default:
UNSUPPORTED("Format: %d", int(format));
}
@@ -1815,6 +1830,7 @@
return 16 * ((width + 11) / 12);
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
return sw::align<16>(width); // Y plane only // TODO: ASSERT to ensure this is only called per-aspect?
default:
return bytes() * width;
@@ -1886,6 +1902,7 @@
return pitchB(width, border) * ((height + 11) / 12); // Pitch computed per 12 rows
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
// "Images in this format must be defined with a width and height that is a multiple of two."
return pitchB(width, border) * (height + height / 2); // U and V planes are 1/4 size of Y plane.
default:
@@ -2305,6 +2322,7 @@
case VK_FORMAT_R16G16B16A16_SFLOAT:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
case VK_FORMAT_A2B10G10R10_UINT_PACK32:
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
@@ -2369,6 +2387,7 @@
case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
case VK_FORMAT_A2B10G10R10_UINT_PACK32:
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
@@ -2459,6 +2478,7 @@
case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
case VK_FORMAT_A2B10G10R10_UINT_PACK32:
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
@@ -2547,6 +2567,7 @@
case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
return component < 3;
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 55b6e55..b99ca22 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -838,6 +838,7 @@
{
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
ASSERT(mipLevelExtent.width % 2 == 0 && mipLevelExtent.height % 2 == 0); // Vulkan 1.1: "Images in this format must be defined with a width and height that is a multiple of two."
// Vulkan 1.1 Table 31. Plane Format Compatibility Table:
// Half-resolution U and V planes.
@@ -944,6 +945,7 @@
}
// Fall through to 2PLANE case:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
if(aspect == VK_IMAGE_ASPECT_PLANE_1_BIT)
{
return getStorageSize(VK_IMAGE_ASPECT_PLANE_0_BIT);
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 0c04adf..64b8055 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -1504,6 +1504,7 @@
// YCbCr formats:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
pFormatProperties->optimalTilingFeatures |=
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |