[Fix, Test] (Util): widen a three-channel 16-bit texture to its same-width four-channel sibling

This commit is contained in:
2026-08-22 12:41:18 -04:00
parent 60808b6cf2
commit 88be35c9ba
2 changed files with 27 additions and 5 deletions
+12 -4
View File
@@ -4033,6 +4033,8 @@ TEST_F(TextureTest, ThreeChannelWideningRetargetsInternalFormatAndTransferPairTo
const Flags<PixelFormatNormalizeOptionBit> widenNoSnorm16 =
PixelFormatNormalizeOptionBit::NoThreeChannelRenderTarget |
PixelFormatNormalizeOptionBit::NoSnorm16RenderTarget;
const Flags<PixelFormatNormalizeOptionBit> widenNoNorm16 =
PixelFormatNormalizeOptionBit::NoThreeChannelRenderTarget | PixelFormatNormalizeOptionBit::NoNorm16;
const Case cases[] = {
// Complementary's colortex1 and colortex2. The transfer pair used to stay three-channel
@@ -4047,10 +4049,16 @@ TEST_F(TextureTest, ThreeChannelWideningRetargetsInternalFormatAndTransferPairTo
// cannot render to the encoding gets the 32-bit float rather than the half.
{GL_RGB16_SNORM, widen, GL_RGBA16_SNORM, GL_RGBA, GL_SHORT},
{GL_RGB16_SNORM, widenNoSnorm16, GL_RGBA32F, GL_RGBA, GL_FLOAT},
// 16-bit UNORM and the legacy 10/12-bit formats stored as RGB16.
{GL_RGB16, widen, GL_RGBA32F, GL_RGBA, GL_FLOAT},
{GL_RGB10, widen, GL_RGBA32F, GL_RGBA, GL_FLOAT},
{GL_RGB12, widen, GL_RGBA32F, GL_RGBA, GL_FLOAT},
// 16-bit UNORM and the legacy 10/12-bit formats stored as RGB16. The same-width sibling
// whenever the driver has EXT_texture_norm16 - which is what keeps the whole 48-bit
// ARB_texture_view class on one ES view class, so a GL_RGB16 texture can be viewed as
// GL_RGB16UI - and the 32-bit float only when it does not.
{GL_RGB16, widen, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT},
{GL_RGB10, widen, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT},
{GL_RGB12, widen, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT},
{GL_RGB16, widenNoNorm16, GL_RGBA32F, GL_RGBA, GL_FLOAT},
{GL_RGB10, widenNoNorm16, GL_RGBA32F, GL_RGBA, GL_FLOAT},
{GL_RGB12, widenNoNorm16, GL_RGBA32F, GL_RGBA, GL_FLOAT},
// sRGB and the integer formats: the base format has to move to the four-channel one of the
// right class, GL_RGBA_INTEGER included.
{GL_SRGB8, widen, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE},
@@ -134,7 +134,21 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
case GL_RGB16:
case GL_RGB10:
case GL_RGB12:
return {GL_RGBA32F, GL_RGBA, GL_FLOAT};
// Same reasoning as GL_RGB16_SNORM above, and the same shape: keep the
// unsigned-normalized encoding whenever the driver has it, because
// GL_RGBA16 is the SAME-WIDTH four-channel sibling and GL_RGBA32F is not.
// That matters beyond storage size. ARB_texture_view puts all five 48-bit
// formats in one view class, so a GL_RGB16 texture viewed as GL_RGB16UI has
// to alias storage the ES driver also considers compatible; against a
// GL_RGBA32F carrier the view is a different class and glTextureView is
// refused outright (KHR-GL4x.texture_view.view_classes). Against GL_RGBA16
// the whole class lands on ES's 64-bit class and every channel reinterprets
// bit-exactly. EXT_texture_norm16 - the absence of which is what NoNorm16
// means - is also what makes GL_RGBA16 colour-renderable, so the two
// questions have one answer.
return (options & PixelFormatNormalizeOptionBit::NoNorm16)
? ThreeChannelWidening{GL_RGBA32F, GL_RGBA, GL_FLOAT}
: ThreeChannelWidening{GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT};
// Floating point.
case GL_RGB16F:
return {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT};