mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 13:48:30 +09:00
[Fix, Test] (MG_Util, MG_Backend/DirectGLES, MG_Backend/DirectVulkan, MG_Test): a packed texel whose client type already spells its storage word must cross glGetTexImage unencoded, or the RGB9_E5 shared exponent gets canonicalized
This commit is contained in:
@@ -259,6 +259,25 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
// The one client (format, type) pair whose word is bit-identical to the packed internal
|
||||
// word, if any. Everything else has to go through the decode/encode conversion.
|
||||
Bool IsRawPackedPixelPair(PackedInternalKind kind, TextureInputFormat format,
|
||||
TexturePixelDataType type) {
|
||||
switch (kind) {
|
||||
case PackedInternalKind::UNorm2101010Rev:
|
||||
return format == TextureInputFormat::RGBA && type == TexturePixelDataType::UnsignedInt2101010Rev;
|
||||
case PackedInternalKind::UInt2101010Rev:
|
||||
return format == TextureInputFormat::RGBAInteger &&
|
||||
type == TexturePixelDataType::UnsignedInt2101010Rev;
|
||||
case PackedInternalKind::FloatR11G11B10:
|
||||
return format == TextureInputFormat::RGB && type == TexturePixelDataType::UnsignedInt101111Rev;
|
||||
case PackedInternalKind::FloatRGB9E5:
|
||||
return format == TextureInputFormat::RGB && type == TexturePixelDataType::UnsignedInt5999Rev;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 EncodePackedInternalWordFloat(PackedInternalKind kind, const Float rgba[4]) {
|
||||
switch (kind) {
|
||||
case PackedInternalKind::UNorm2101010Rev: {
|
||||
@@ -431,10 +450,7 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||
return false;
|
||||
}
|
||||
// The client word already equals the packed internal word (memcpy fast path).
|
||||
if (hasPackedInternal && type == TexturePixelDataType::UnsignedInt2101010Rev &&
|
||||
(format == TextureInputFormat::RGBA || format == TextureInputFormat::RGBAInteger) &&
|
||||
(packedInternal.kind == PackedInternalKind::UNorm2101010Rev ||
|
||||
packedInternal.kind == PackedInternalKind::UInt2101010Rev)) {
|
||||
if (hasPackedInternal && IsRawPackedPixelPair(packedInternal.kind, format, type)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -458,11 +474,7 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||
// GL_RGB, which the state layer already enforces.
|
||||
if (mapping.isInteger || mapping.channelCount != 3) return false;
|
||||
// The client word already equals the packed internal word.
|
||||
if (hasPackedInternal &&
|
||||
((packedInternal.kind == PackedInternalKind::FloatRGB9E5 &&
|
||||
type == TexturePixelDataType::UnsignedInt5999Rev) ||
|
||||
(packedInternal.kind == PackedInternalKind::FloatR11G11B10 &&
|
||||
type == TexturePixelDataType::UnsignedInt101111Rev))) {
|
||||
if (hasPackedInternal && IsRawPackedPixelPair(packedInternal.kind, format, type)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -765,6 +777,15 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Bool IsRawPackedPixelTransfer(TextureInternalFormat internalFormat, TextureInputFormat clientFormat,
|
||||
TexturePixelDataType clientType) {
|
||||
InternalPackedLayout packedInternal{};
|
||||
if (!GetInternalPackedLayout(internalFormat, packedInternal)) {
|
||||
return false;
|
||||
}
|
||||
return IsRawPackedPixelPair(packedInternal.kind, clientFormat, clientType);
|
||||
}
|
||||
|
||||
// assume 8 bit per channel
|
||||
// swizzle.size() == channel count
|
||||
void ProcessColorSwizzle(void* data, SizeT pixelCount, const Vector<TextureSwizzleParam>& swizzle) {
|
||||
|
||||
@@ -23,6 +23,21 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||
IntVec3 dimension, Bool isBitmap, SizeT& outSize);
|
||||
void ProcessColorSwizzle(void* data, SizeT pixelCount, const Vector<TextureSwizzleParam>& swizzle);
|
||||
|
||||
// True when a packed internal format's 32-bit storage word IS the client (format, type) word,
|
||||
// so the transfer has to move the words verbatim in both directions.
|
||||
//
|
||||
// Decoding such a texel to float and re-encoding it is NOT a no-op: RGB9_E5 stores a shared
|
||||
// exponent with redundant encodings, and the spec's encode algorithm (GL 4.6 8.5.2) always
|
||||
// emits the canonical one - 0xf8fc0000 and 0xe7e00000 are the same value 8064, but only the
|
||||
// latter is canonical. glTexImage followed by glGetTexImage must hand back the bits the
|
||||
// application uploaded, which is what GL CTS KHR-GL43.copy_image compares
|
||||
// ("CopyImageSubData modified contents of source image").
|
||||
//
|
||||
// Only the pairs whose bit layouts are identical qualify; a genuinely different client format
|
||||
// or type still needs the decode/encode conversion.
|
||||
Bool IsRawPackedPixelTransfer(TextureInternalFormat internalFormat, TextureInputFormat clientFormat,
|
||||
TexturePixelDataType clientType);
|
||||
|
||||
// Decodes the canonical shadow-mip storage of `internalFormat` into wide RGBA texels for CPU
|
||||
// readback (GetTexImage of non-renderable formats). Non-integer formats fill outWide with
|
||||
// 4 Floats per texel; integer formats fill it with 4 Uint32/Int32 per texel and set
|
||||
|
||||
Reference in New Issue
Block a user