mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
[Fix]: fix Complementary
- add a DirectGLES ANGLE fallback control for 8-bit SNORM texture formats - normalize SNORM8 textures to float storage so ANGLE can render Complementary intermediate framebuffers - reuse the normalized upload conversion path for SNORM8 and existing norm16 float fallbacks
This commit is contained in:
@@ -533,17 +533,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
GLint m_prevSkipImages = 0;
|
||||
};
|
||||
|
||||
static Uint GetNorm16ComponentCount(TextureInternalFormat format) {
|
||||
static Uint GetNormFallbackComponentCount(TextureInternalFormat format) {
|
||||
switch (format) {
|
||||
case TextureInternalFormat::R8Snorm:
|
||||
case TextureInternalFormat::R16:
|
||||
case TextureInternalFormat::R16Snorm:
|
||||
return 1;
|
||||
case TextureInternalFormat::RG8Snorm:
|
||||
case TextureInternalFormat::RG16:
|
||||
case TextureInternalFormat::RG16Snorm:
|
||||
return 2;
|
||||
case TextureInternalFormat::RGB8Snorm:
|
||||
case TextureInternalFormat::RGB16:
|
||||
case TextureInternalFormat::RGB16Snorm:
|
||||
return 3;
|
||||
case TextureInternalFormat::RGBA8Snorm:
|
||||
case TextureInternalFormat::RGBA16:
|
||||
case TextureInternalFormat::RGBA16Snorm:
|
||||
return 4;
|
||||
@@ -552,8 +556,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
}
|
||||
|
||||
static Bool IsSnorm16Format(TextureInternalFormat format) {
|
||||
static Bool IsSnormFallbackFormat(TextureInternalFormat format) {
|
||||
switch (format) {
|
||||
case TextureInternalFormat::R8Snorm:
|
||||
case TextureInternalFormat::RG8Snorm:
|
||||
case TextureInternalFormat::RGB8Snorm:
|
||||
case TextureInternalFormat::RGBA8Snorm:
|
||||
case TextureInternalFormat::R16Snorm:
|
||||
case TextureInternalFormat::RG16Snorm:
|
||||
case TextureInternalFormat::RGB16Snorm:
|
||||
@@ -564,13 +572,25 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
}
|
||||
|
||||
static const void* PrepareNorm16FloatFallbackUpload(TextureInternalFormat format,
|
||||
const IntVec3& texelSize,
|
||||
const void* data,
|
||||
SizeT byteSize,
|
||||
GLenum uploadType,
|
||||
Vector<Float>& convertedData) {
|
||||
const Uint componentCount = GetNorm16ComponentCount(format);
|
||||
static Bool IsNorm8FallbackFormat(TextureInternalFormat format) {
|
||||
switch (format) {
|
||||
case TextureInternalFormat::R8Snorm:
|
||||
case TextureInternalFormat::RG8Snorm:
|
||||
case TextureInternalFormat::RGB8Snorm:
|
||||
case TextureInternalFormat::RGBA8Snorm:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const void* PrepareNormFloatFallbackUpload(TextureInternalFormat format,
|
||||
const IntVec3& texelSize,
|
||||
const void* data,
|
||||
SizeT byteSize,
|
||||
GLenum uploadType,
|
||||
Vector<Float>& convertedData) {
|
||||
const Uint componentCount = GetNormFallbackComponentCount(format);
|
||||
if (componentCount == 0 || uploadType != GL_FLOAT || data == nullptr || byteSize == 0) {
|
||||
return data;
|
||||
}
|
||||
@@ -579,14 +599,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
static_cast<SizeT>(std::max(texelSize.y(), 0)) *
|
||||
static_cast<SizeT>(std::max(texelSize.z(), 0));
|
||||
const SizeT componentTotal = texelCount * static_cast<SizeT>(componentCount);
|
||||
const SizeT sourceComponentTotal = byteSize / sizeof(Uint16);
|
||||
const SizeT sourceComponentSize = IsNorm8FallbackFormat(format) ? sizeof(Int8) : sizeof(Uint16);
|
||||
const SizeT sourceComponentTotal = byteSize / sourceComponentSize;
|
||||
if (componentTotal == 0 || sourceComponentTotal == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
convertedData.assign(componentTotal, 0.0f);
|
||||
const SizeT copyComponentTotal = std::min(componentTotal, sourceComponentTotal);
|
||||
if (IsSnorm16Format(format)) {
|
||||
if (IsNorm8FallbackFormat(format)) {
|
||||
const Int8* src = static_cast<const Int8*>(data);
|
||||
constexpr Float invMaxSnorm8 = 1.0f / 127.0f;
|
||||
for (SizeT i = 0; i < copyComponentTotal; ++i) {
|
||||
convertedData[i] = std::max(static_cast<Float>(src[i]) * invMaxSnorm8, -1.0f);
|
||||
}
|
||||
} else if (IsSnormFallbackFormat(format)) {
|
||||
const Int16* src = static_cast<const Int16*>(data);
|
||||
constexpr Float invMaxSnorm16 = 1.0f / 32767.0f;
|
||||
for (SizeT i = 0; i < copyComponentTotal; ++i) {
|
||||
@@ -695,7 +722,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
? textureMipmapObject->MapMipmapData(uploadTarget, level)
|
||||
: nullptr;
|
||||
Vector<Float> convertedUploadData;
|
||||
const void* uploadData = PrepareNorm16FloatFallbackUpload(
|
||||
const void* uploadData = PrepareNormFloatFallbackUpload(
|
||||
textureMipmapObject->GetFormat(), levelTexelSize, pData, levelByteSize, glType,
|
||||
convertedUploadData);
|
||||
|
||||
@@ -785,7 +812,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
? textureMipmapObject->MapMipmapData(uploadTarget, level)
|
||||
: nullptr;
|
||||
Vector<Float> convertedUploadData;
|
||||
const void* uploadData = PrepareNorm16FloatFallbackUpload(
|
||||
const void* uploadData = PrepareNormFloatFallbackUpload(
|
||||
textureMipmapObject->GetFormat(), levelTexelSize, pData, levelByteSize, glType,
|
||||
convertedUploadData);
|
||||
MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p, "
|
||||
@@ -889,7 +916,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
|
||||
const void* mipData = textureMipmapObject->MapMipmapData(uploadTarget, level);
|
||||
Vector<Float> convertedUploadData;
|
||||
const void* uploadData = PrepareNorm16FloatFallbackUpload(
|
||||
const void* uploadData = PrepareNormFloatFallbackUpload(
|
||||
textureMipmapObject->GetFormat(), texelSize, mipData, byteSize, glType,
|
||||
convertedUploadData);
|
||||
switch (stateTextureObject->GetTarget()) {
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (g_GLESCapabilities.GLESRendererString.find("ANGLE") != String::npos) {
|
||||
options |= PixelFormatNormalizeOptionBit::NoRgb16;
|
||||
options |= PixelFormatNormalizeOptionBit::NoSnorm16;
|
||||
options |= PixelFormatNormalizeOptionBit::NoSnorm8;
|
||||
}
|
||||
NormalizePixelFormat(MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat), options,
|
||||
outInternalFormat, outFormat, outType);
|
||||
|
||||
@@ -82,6 +82,34 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
}
|
||||
*outInternalFormat = internalFormat;
|
||||
break;
|
||||
case GL_RGBA8_SNORM:
|
||||
if (options & PixelFormatNormalizeOptionBit::NoSnorm8) {
|
||||
*outInternalFormat = GL_RGBA16F;
|
||||
break;
|
||||
}
|
||||
*outInternalFormat = internalFormat;
|
||||
break;
|
||||
case GL_RGB8_SNORM:
|
||||
if (options & PixelFormatNormalizeOptionBit::NoSnorm8) {
|
||||
*outInternalFormat = GL_RGB16F;
|
||||
break;
|
||||
}
|
||||
*outInternalFormat = internalFormat;
|
||||
break;
|
||||
case GL_RG8_SNORM:
|
||||
if (options & PixelFormatNormalizeOptionBit::NoSnorm8) {
|
||||
*outInternalFormat = GL_RG16F;
|
||||
break;
|
||||
}
|
||||
*outInternalFormat = internalFormat;
|
||||
break;
|
||||
case GL_R8_SNORM:
|
||||
if (options & PixelFormatNormalizeOptionBit::NoSnorm8) {
|
||||
*outInternalFormat = GL_R16F;
|
||||
break;
|
||||
}
|
||||
*outInternalFormat = internalFormat;
|
||||
break;
|
||||
default:
|
||||
*outInternalFormat = internalFormat;
|
||||
break;
|
||||
@@ -296,6 +324,10 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
case GL_RGB8_SNORM:
|
||||
case GL_RG8_SNORM:
|
||||
case GL_R8_SNORM:
|
||||
if (options & PixelFormatNormalizeOptionBit::NoSnorm8) {
|
||||
*outType = GL_FLOAT;
|
||||
break;
|
||||
}
|
||||
*outType = GL_BYTE;
|
||||
break;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace MobileGL {
|
||||
NoNorm16 = 1 << 0,
|
||||
NoSnorm16 = 1 << 1,
|
||||
NoRgb16 = 1 << 2,
|
||||
NoSnorm8 = 1 << 3,
|
||||
None = 0,
|
||||
};
|
||||
namespace MG_Util::TextureFormatProcessor {
|
||||
|
||||
Reference in New Issue
Block a user