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 |