mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 13:48:30 +09:00
[Fix, Test] (TextureFormatProcessor): store the desktop-only low-bit formats without a driver requantization
This commit is contained in:
@@ -3197,11 +3197,19 @@ TEST_F(TextureTest, NormalizeLegacySizedFormatsMapToCanonicalShadowLayouts) {
|
|||||||
GLenum type;
|
GLenum type;
|
||||||
};
|
};
|
||||||
const Case cases[] = {
|
const Case cases[] = {
|
||||||
// Legacy <=8-bit-per-channel formats store as UNorm8 component arrays.
|
// Legacy <=8-bit-per-channel DESKTOP-ONLY formats store as UNorm8 component arrays, in the
|
||||||
{GL_R3_G3_B2, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE},
|
// 8-bit-per-channel ES format that layout already is. Storing them in the narrower
|
||||||
{GL_RGB4, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE},
|
// GL_RGB565/GL_RGBA4 they nominally fit in made the driver requantize the shadow bytes on
|
||||||
{GL_RGB5, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE},
|
// every upload, which is not lossless: 5-bit 2 -> UNorm8 16 -> 16/255*31 = 1.945, which a
|
||||||
{GL_RGBA2, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE},
|
// truncating driver reads back as 1 (KHR-GL43.copy_image rgb4->rgb4, 12/12 failing on Mali).
|
||||||
|
{GL_R3_G3_B2, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
|
||||||
|
{GL_RGB4, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
|
||||||
|
{GL_RGB5, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
|
||||||
|
{GL_RGBA2, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
|
||||||
|
// The two that are ES formats in their own right keep their native storage: an application
|
||||||
|
// that asks for GL_RGBA4 or GL_RGB5_A1 is asking for the smaller image, and the same
|
||||||
|
// normalization also picks the storage for glRenderbufferStorage, where those two are
|
||||||
|
// ordinary ES render targets rather than a desktop-compatibility shim.
|
||||||
{GL_RGBA4, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE},
|
{GL_RGBA4, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE},
|
||||||
{GL_RGB5_A1, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE},
|
{GL_RGB5_A1, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE},
|
||||||
// 10/12-bit channels store as UNorm16 component arrays.
|
// 10/12-bit channels store as UNorm16 component arrays.
|
||||||
|
|||||||
@@ -270,10 +270,30 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
|||||||
// per-channel precision (extra precision stays inside the CTS comparison epsilon, which is
|
// per-channel precision (extra precision stays inside the CTS comparison epsilon, which is
|
||||||
// derived from the requested format's bit widths). The upload (format, type) below matches
|
// derived from the requested format's bit widths). The upload (format, type) below matches
|
||||||
// the canonical shadow layout in PixelStoreProcessor (UNorm8 / UNorm16 component arrays).
|
// the canonical shadow layout in PixelStoreProcessor (UNorm8 / UNorm16 component arrays).
|
||||||
|
//
|
||||||
|
// The <=8-bit ones land on the 8-bit-per-channel storage that layout ALREADY is, rather
|
||||||
|
// than on the narrower GL_RGB565/GL_RGBA4 they nominally fit in. Storing them narrower
|
||||||
|
// made the driver requantize the UNorm8 shadow bytes on every upload, and that step is
|
||||||
|
// exact only by luck: 5-bit value 2 encodes as UNorm8 16, and 16/255*31 = 1.945 sits
|
||||||
|
// astride the 5-bit boundary, so a driver that truncates hands back 1 (all twelve
|
||||||
|
// KHR-GL43.copy_image.functional rgb4->rgb4 cases fail on Mali, at verify()'s FIRST
|
||||||
|
// check - a plain glTexImage/glGetTexImage round trip with no copy involved). The
|
||||||
|
// 8-bit store removes the requantization entirely; the client word round-trips
|
||||||
|
// exactly, because encoding an n-bit field to UNorm8 with rounding and back is the
|
||||||
|
// identity for every n <= 8. It is also what DirectVulkan has always done with them
|
||||||
|
// (VkTextureManager::ResolveTextureFormatInfo resolves all six legacy low-bit formats
|
||||||
|
// to R8G8B8A8_UNORM), so the two backends now agree here.
|
||||||
|
//
|
||||||
|
// Only the DESKTOP-ONLY formats move. GL_RGBA4 and GL_RGB5_A1 are ES formats an
|
||||||
|
// application can legitimately ask for - the same normalization picks the storage for
|
||||||
|
// glRenderbufferStorage - so widening them would be a memory decision, not a
|
||||||
|
// correctness one. Nothing about the REPORTED precision moves either way:
|
||||||
|
// GL_TEXTURE_*_SIZE and glGetInternalformativ answer from TextureMetrics, keyed on the
|
||||||
|
// requested format, not on the ES storage.
|
||||||
case GL_R3_G3_B2:
|
case GL_R3_G3_B2:
|
||||||
case GL_RGB4:
|
case GL_RGB4:
|
||||||
case GL_RGB5:
|
case GL_RGB5:
|
||||||
*outInternalFormat = GL_RGB565;
|
*outInternalFormat = GL_RGB8;
|
||||||
break;
|
break;
|
||||||
case GL_RGB10:
|
case GL_RGB10:
|
||||||
case GL_RGB12:
|
case GL_RGB12:
|
||||||
@@ -283,7 +303,7 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
|||||||
: GL_RGB16;
|
: GL_RGB16;
|
||||||
break;
|
break;
|
||||||
case GL_RGBA2:
|
case GL_RGBA2:
|
||||||
*outInternalFormat = GL_RGBA4;
|
*outInternalFormat = GL_RGBA8;
|
||||||
break;
|
break;
|
||||||
case GL_RGBA12:
|
case GL_RGBA12:
|
||||||
*outInternalFormat =
|
*outInternalFormat =
|
||||||
|
|||||||
Reference in New Issue
Block a user