Merge pull request #12812 from SamGondelman/compression

Support ETC2/EAC compressed textures
This commit is contained in:
John Conklin II 2018-04-12 16:04:08 -07:00 committed by GitHub
commit 3d90f93cf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 358 additions and 57 deletions

View file

@ -370,7 +370,36 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
case gpu::COMPRESSED_BC7_SRGBA:
result = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break;
case gpu::COMPRESSED_ETC2_RGB:
result = GL_COMPRESSED_RGB8_ETC2;
break;
case gpu::COMPRESSED_ETC2_SRGB:
result = GL_COMPRESSED_SRGB8_ETC2;
break;
case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
result = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
break;
case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
result = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
break;
case gpu::COMPRESSED_ETC2_RGBA:
result = GL_COMPRESSED_RGBA8_ETC2_EAC;
break;
case gpu::COMPRESSED_ETC2_SRGBA:
result = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
break;
case gpu::COMPRESSED_EAC_RED:
result = GL_COMPRESSED_R11_EAC;
break;
case gpu::COMPRESSED_EAC_RED_SIGNED:
result = GL_COMPRESSED_SIGNED_R11_EAC;
break;
case gpu::COMPRESSED_EAC_XY:
result = GL_COMPRESSED_RG11_EAC;
break;
case gpu::COMPRESSED_EAC_XY_SIGNED:
result = GL_COMPRESSED_SIGNED_RG11_EAC;
break;
default:
qCWarning(gpugllogging) << "Unknown combination of texel format";
}
@ -531,6 +560,36 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
case gpu::COMPRESSED_BC7_SRGBA:
texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break;
case gpu::COMPRESSED_ETC2_RGB:
texel.internalFormat = GL_COMPRESSED_RGB8_ETC2;
break;
case gpu::COMPRESSED_ETC2_SRGB:
texel.internalFormat = GL_COMPRESSED_SRGB8_ETC2;
break;
case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
texel.internalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
break;
case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
texel.internalFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
break;
case gpu::COMPRESSED_ETC2_RGBA:
texel.internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
break;
case gpu::COMPRESSED_ETC2_SRGBA:
texel.internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
break;
case gpu::COMPRESSED_EAC_RED:
texel.internalFormat = GL_COMPRESSED_R11_EAC;
break;
case gpu::COMPRESSED_EAC_RED_SIGNED:
texel.internalFormat = GL_COMPRESSED_SIGNED_R11_EAC;
break;
case gpu::COMPRESSED_EAC_XY:
texel.internalFormat = GL_COMPRESSED_RG11_EAC;
break;
case gpu::COMPRESSED_EAC_XY_SIGNED:
texel.internalFormat = GL_COMPRESSED_SIGNED_RG11_EAC;
break;
default:
qCWarning(gpugllogging) << "Unknown combination of texel format";
}
@ -895,7 +954,36 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
case gpu::COMPRESSED_BC7_SRGBA:
texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break;
case gpu::COMPRESSED_ETC2_RGB:
texel.internalFormat = GL_COMPRESSED_RGB8_ETC2;
break;
case gpu::COMPRESSED_ETC2_SRGB:
texel.internalFormat = GL_COMPRESSED_SRGB8_ETC2;
break;
case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
texel.internalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
break;
case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
texel.internalFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
break;
case gpu::COMPRESSED_ETC2_RGBA:
texel.internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
break;
case gpu::COMPRESSED_ETC2_SRGBA:
texel.internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
break;
case gpu::COMPRESSED_EAC_RED:
texel.internalFormat = GL_COMPRESSED_R11_EAC;
break;
case gpu::COMPRESSED_EAC_RED_SIGNED:
texel.internalFormat = GL_COMPRESSED_SIGNED_R11_EAC;
break;
case gpu::COMPRESSED_EAC_XY:
texel.internalFormat = GL_COMPRESSED_RG11_EAC;
break;
case gpu::COMPRESSED_EAC_XY_SIGNED:
texel.internalFormat = GL_COMPRESSED_SIGNED_RG11_EAC;
break;
default:
qCWarning(gpugllogging) << "Unknown combination of texel format";
}

View file

@ -173,6 +173,8 @@ protected:
void makeProgramBindings(ShaderObject& shaderObject) override;
int makeResourceBufferSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override;
static bool supportedTextureFormat(const gpu::Element& format);
};
} }

View file

@ -19,6 +19,24 @@ using namespace gpu;
using namespace gpu::gl;
using namespace gpu::gl41;
bool GL41Backend::supportedTextureFormat(const gpu::Element& format) {
switch (format.getSemantic()) {
case gpu::Semantic::COMPRESSED_ETC2_RGB:
case gpu::Semantic::COMPRESSED_ETC2_SRGB:
case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
case gpu::Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
case gpu::Semantic::COMPRESSED_ETC2_RGBA:
case gpu::Semantic::COMPRESSED_ETC2_SRGBA:
case gpu::Semantic::COMPRESSED_EAC_RED:
case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED:
case gpu::Semantic::COMPRESSED_EAC_XY:
case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED:
return false;
default:
return true;
}
}
GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texturePointer) {
if (!texturePointer) {
return nullptr;
@ -34,6 +52,11 @@ GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texturePointer) {
return nullptr;
}
// Check whether the texture is in a format we can deal with
if (!supportedTextureFormat(texture.getTexelFormat())) {
return nullptr;
}
GL41Texture* object = Backend::getGPUObject<GL41Texture>(texture);
if (!object) {
switch (texture.getUsageType()) {

View file

@ -206,6 +206,16 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
case GL_COMPRESSED_RGB8_ETC2:
case GL_COMPRESSED_SRGB8_ETC2:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_RGBA8_ETC2_EAC:
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
case GL_COMPRESSED_R11_EAC:
case GL_COMPRESSED_SIGNED_R11_EAC:
case GL_COMPRESSED_RG11_EAC:
case GL_COMPRESSED_SIGNED_RG11_EAC:
glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat,
static_cast<GLsizei>(sourceSize), sourcePointer);
break;
@ -222,6 +232,16 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
case GL_COMPRESSED_RGB8_ETC2:
case GL_COMPRESSED_SRGB8_ETC2:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_RGBA8_ETC2_EAC:
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
case GL_COMPRESSED_R11_EAC:
case GL_COMPRESSED_SIGNED_R11_EAC:
case GL_COMPRESSED_RG11_EAC:
case GL_COMPRESSED_SIGNED_RG11_EAC:
if (glCompressedTextureSubImage2DEXT) {
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat,

View file

@ -20,9 +20,21 @@ using namespace gpu::gl;
using namespace gpu::gles;
bool GLESBackend::supportedTextureFormat(const gpu::Element& format) {
// FIXME distinguish between GLES and GL compressed formats after support
// for the former is added to gpu::Element
return !format.isCompressed();
switch (format.getSemantic()) {
case gpu::Semantic::COMPRESSED_ETC2_RGB:
case gpu::Semantic::COMPRESSED_ETC2_SRGB:
case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
case gpu::Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
case gpu::Semantic::COMPRESSED_ETC2_RGBA:
case gpu::Semantic::COMPRESSED_ETC2_SRGBA:
case gpu::Semantic::COMPRESSED_EAC_RED:
case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED:
case gpu::Semantic::COMPRESSED_EAC_XY:
case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED:
return true;
default:
return !format.isCompressed();
}
}
GLTexture* GLESBackend::syncGPUObject(const TexturePointer& texturePointer) {
@ -231,6 +243,29 @@ GLESFixedAllocationTexture::GLESFixedAllocationTexture(const std::weak_ptr<GLBac
GLESFixedAllocationTexture::~GLESFixedAllocationTexture() {
}
GLsizei getCompressedImageSize(int width, int height, GLenum internalFormat) {
GLsizei blockSize;
switch (internalFormat) {
case GL_COMPRESSED_R11_EAC:
case GL_COMPRESSED_SIGNED_R11_EAC:
case GL_COMPRESSED_RGB8_ETC2:
case GL_COMPRESSED_SRGB8_ETC2:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
blockSize = 8;
break;
case GL_COMPRESSED_RG11_EAC:
case GL_COMPRESSED_SIGNED_RG11_EAC:
case GL_COMPRESSED_RGBA8_ETC2_EAC:
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
default:
blockSize = 16;
}
// See https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glCompressedTexImage2D.xhtml
return (GLsizei)ceil(width / 4.0f) * (GLsizei)ceil(height / 4.0f) * blockSize;
}
void GLESFixedAllocationTexture::allocateStorage() const {
const GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
const auto numMips = _gpuObject.getNumMips();
@ -239,7 +274,12 @@ void GLESFixedAllocationTexture::allocateStorage() const {
for (GLint level = 0; level < numMips; level++) {
Vec3u dimensions = _gpuObject.evalMipDimensions(level);
for (GLenum target : getFaceTargets(_target)) {
glTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, texelFormat.type, nullptr);
if (texelFormat.isCompressed()) {
glCompressedTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0,
getCompressedImageSize(dimensions.x, dimensions.y, texelFormat.internalFormat), nullptr);
} else {
glTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, texelFormat.type, nullptr);
}
}
}

View file

@ -21,13 +21,24 @@ const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA };
const Element Element::COLOR_RGBA_2{ VEC4, NUINT2, RGBA };
const Element Element::COLOR_COMPRESSED_RED{ TILE4x4, COMPRESSED, COMPRESSED_BC4_RED };
const Element Element::COLOR_COMPRESSED_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB };
const Element Element::COLOR_COMPRESSED_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA };
const Element Element::COLOR_COMPRESSED_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_BC3_SRGBA };
const Element Element::COLOR_COMPRESSED_XY { TILE4x4, COMPRESSED, COMPRESSED_BC5_XY };
const Element Element::COLOR_COMPRESSED_SRGBA_HIGH{ TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA };
const Element Element::COLOR_COMPRESSED_HDR_RGB{ TILE4x4, COMPRESSED, COMPRESSED_BC6_RGB };
const Element Element::COLOR_COMPRESSED_BCX_RED { TILE4x4, COMPRESSED, COMPRESSED_BC4_RED };
const Element Element::COLOR_COMPRESSED_BCX_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB };
const Element Element::COLOR_COMPRESSED_BCX_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA };
const Element Element::COLOR_COMPRESSED_BCX_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_BC3_SRGBA };
const Element Element::COLOR_COMPRESSED_BCX_XY { TILE4x4, COMPRESSED, COMPRESSED_BC5_XY };
const Element Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH { TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA };
const Element Element::COLOR_COMPRESSED_BCX_HDR_RGB { TILE4x4, COMPRESSED, COMPRESSED_BC6_RGB };
const Element Element::COLOR_COMPRESSED_ETC2_RGB { TILE4x4, COMPRESSED, COMPRESSED_ETC2_RGB };
const Element Element::COLOR_COMPRESSED_ETC2_SRGB { TILE4x4, COMPRESSED, COMPRESSED_ETC2_SRGB };
const Element Element::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA { TILE4x4, COMPRESSED, COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA };
const Element Element::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA { TILE4x4, COMPRESSED, COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA };
const Element Element::COLOR_COMPRESSED_ETC2_RGBA { TILE4x4, COMPRESSED, COMPRESSED_ETC2_RGBA };
const Element Element::COLOR_COMPRESSED_ETC2_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_ETC2_SRGBA };
const Element Element::COLOR_COMPRESSED_EAC_RED { TILE4x4, COMPRESSED, COMPRESSED_EAC_RED };
const Element Element::COLOR_COMPRESSED_EAC_RED_SIGNED { TILE4x4, COMPRESSED, COMPRESSED_EAC_RED_SIGNED };
const Element Element::COLOR_COMPRESSED_EAC_XY { TILE4x4, COMPRESSED, COMPRESSED_EAC_XY };
const Element Element::COLOR_COMPRESSED_EAC_XY_SIGNED { TILE4x4, COMPRESSED, COMPRESSED_EAC_XY_SIGNED };
const Element Element::VEC2NU8_XY{ VEC2, NUINT8, XY };

View file

@ -194,6 +194,17 @@ enum Semantic : uint8_t {
COMPRESSED_BC6_RGB,
COMPRESSED_BC7_SRGBA,
COMPRESSED_ETC2_RGB,
COMPRESSED_ETC2_SRGB,
COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA,
COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA,
COMPRESSED_ETC2_RGBA,
COMPRESSED_ETC2_SRGBA,
COMPRESSED_EAC_RED,
COMPRESSED_EAC_RED_SIGNED,
COMPRESSED_EAC_XY,
COMPRESSED_EAC_XY_SIGNED,
_LAST_COMPRESSED,
R11G11B10,
@ -249,6 +260,17 @@ static const int SEMANTIC_SIZE_FACTOR[NUM_SEMANTICS] = {
16, //COMPRESSED_BC6_RGB, 1 byte/pixel * 4x4 pixels = 16 bytes
16, //COMPRESSED_BC7_SRGBA, 1 byte/pixel * 4x4 pixels = 16 bytes
8, //COMPRESSED_ETC2_RGB,
8, //COMPRESSED_ETC2_SRGB,
8, //COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA,
8, //COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA,
16, //COMPRESSED_ETC2_RGBA,
16, //COMPRESSED_ETC2_SRGBA,
8, //COMPRESSED_EAC_RED,
8, //COMPRESSED_EAC_RED_SIGNED,
16, //COMPRESSED_EAC_XY,
16, //COMPRESSED_EAC_XY_SIGNED,
1, //_LAST_COMPRESSED,
1, //R11G11B10,
@ -316,13 +338,23 @@ public:
static const Element COLOR_RGBA_2;
static const Element COLOR_R11G11B10;
static const Element COLOR_RGB9E5;
static const Element COLOR_COMPRESSED_RED;
static const Element COLOR_COMPRESSED_SRGB;
static const Element COLOR_COMPRESSED_SRGBA_MASK;
static const Element COLOR_COMPRESSED_SRGBA;
static const Element COLOR_COMPRESSED_XY;
static const Element COLOR_COMPRESSED_SRGBA_HIGH;
static const Element COLOR_COMPRESSED_HDR_RGB;
static const Element COLOR_COMPRESSED_BCX_RED;
static const Element COLOR_COMPRESSED_BCX_SRGB;
static const Element COLOR_COMPRESSED_BCX_SRGBA_MASK;
static const Element COLOR_COMPRESSED_BCX_SRGBA;
static const Element COLOR_COMPRESSED_BCX_XY;
static const Element COLOR_COMPRESSED_BCX_SRGBA_HIGH;
static const Element COLOR_COMPRESSED_BCX_HDR_RGB;
static const Element COLOR_COMPRESSED_ETC2_RGB;
static const Element COLOR_COMPRESSED_ETC2_SRGB;
static const Element COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA;
static const Element COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA;
static const Element COLOR_COMPRESSED_ETC2_RGBA;
static const Element COLOR_COMPRESSED_ETC2_SRGBA;
static const Element COLOR_COMPRESSED_EAC_RED;
static const Element COLOR_COMPRESSED_EAC_RED_SIGNED;
static const Element COLOR_COMPRESSED_EAC_XY;
static const Element COLOR_COMPRESSED_EAC_XY_SIGNED;
static const Element VEC2NU8_XY;
static const Element VEC4F_COLOR_RGBA;
static const Element VEC2F_UV;

View file

@ -574,20 +574,40 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat::R8, ktx::GLBaseInternalFormat::RED);
} else if (texelFormat == Format::VEC2NU8_XY && mipFormat == Format::VEC2NU8_XY) {
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RG, ktx::GLInternalFormat::RG8, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGB && mipFormat == Format::COLOR_COMPRESSED_SRGB) {
} else if (texelFormat == Format::COLOR_COMPRESSED_BCX_SRGB && mipFormat == Format::COLOR_COMPRESSED_BCX_SRGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA_MASK && mipFormat == Format::COLOR_COMPRESSED_SRGBA_MASK) {
} else if (texelFormat == Format::COLOR_COMPRESSED_BCX_SRGBA_MASK && mipFormat == Format::COLOR_COMPRESSED_BCX_SRGBA_MASK) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA && mipFormat == Format::COLOR_COMPRESSED_SRGBA) {
} else if (texelFormat == Format::COLOR_COMPRESSED_BCX_SRGBA && mipFormat == Format::COLOR_COMPRESSED_BCX_SRGBA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_RED && mipFormat == Format::COLOR_COMPRESSED_RED) {
} else if (texelFormat == Format::COLOR_COMPRESSED_BCX_RED && mipFormat == Format::COLOR_COMPRESSED_BCX_RED) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RED_RGTC1, ktx::GLBaseInternalFormat::RED);
} else if (texelFormat == Format::COLOR_COMPRESSED_XY && mipFormat == Format::COLOR_COMPRESSED_XY) {
} else if (texelFormat == Format::COLOR_COMPRESSED_BCX_XY && mipFormat == Format::COLOR_COMPRESSED_BCX_XY) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RG_RGTC2, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA_HIGH && mipFormat == Format::COLOR_COMPRESSED_SRGBA_HIGH) {
} else if (texelFormat == Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH && mipFormat == Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_HDR_RGB && mipFormat == Format::COLOR_COMPRESSED_HDR_RGB) {
} else if (texelFormat == Format::COLOR_COMPRESSED_BCX_HDR_RGB && mipFormat == Format::COLOR_COMPRESSED_BCX_HDR_RGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_RGB && mipFormat == Format::COLOR_COMPRESSED_ETC2_RGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGB8_ETC2, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_SRGB && mipFormat == Format::COLOR_COMPRESSED_ETC2_SRGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB8_ETC2, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA && mipFormat == Format::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA && mipFormat == Format::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_RGBA && mipFormat == Format::COLOR_COMPRESSED_ETC2_RGBA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGBA8_ETC2_EAC, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_SRGBA && mipFormat == Format::COLOR_COMPRESSED_ETC2_SRGBA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_EAC_RED && mipFormat == Format::COLOR_COMPRESSED_EAC_RED) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_R11_EAC, ktx::GLBaseInternalFormat::RED);
} else if (texelFormat == Format::COLOR_COMPRESSED_EAC_RED_SIGNED && mipFormat == Format::COLOR_COMPRESSED_EAC_RED_SIGNED) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SIGNED_R11_EAC, ktx::GLBaseInternalFormat::RED);
} else if (texelFormat == Format::COLOR_COMPRESSED_EAC_XY && mipFormat == Format::COLOR_COMPRESSED_EAC_XY) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RG11_EAC, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_COMPRESSED_EAC_XY_SIGNED && mipFormat == Format::COLOR_COMPRESSED_EAC_XY_SIGNED) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SIGNED_RG11_EAC, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_RGB9E5 && mipFormat == Format::COLOR_RGB9E5) {
header.setUncompressed(ktx::GLType::UNSIGNED_INT_5_9_9_9_REV, 1, ktx::GLFormat::RGB, ktx::GLInternalFormat::RGB9_E5, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_R11G11B10 && mipFormat == Format::COLOR_R11G11B10) {
@ -642,31 +662,45 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E
texelFormat = Format::COLOR_RGB9E5;
} else if (header.isCompressed()) {
if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT) {
mipFormat = Format::COLOR_COMPRESSED_SRGB;
texelFormat = Format::COLOR_COMPRESSED_SRGB;
texelFormat = Format::COLOR_COMPRESSED_BCX_SRGB;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) {
mipFormat = Format::COLOR_COMPRESSED_SRGBA_MASK;
texelFormat = Format::COLOR_COMPRESSED_SRGBA_MASK;
texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_MASK;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
mipFormat = Format::COLOR_COMPRESSED_SRGBA;
texelFormat = Format::COLOR_COMPRESSED_SRGBA;
texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RED_RGTC1) {
mipFormat = Format::COLOR_COMPRESSED_RED;
texelFormat = Format::COLOR_COMPRESSED_RED;
texelFormat = Format::COLOR_COMPRESSED_BCX_RED;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG_RGTC2) {
mipFormat = Format::COLOR_COMPRESSED_XY;
texelFormat = Format::COLOR_COMPRESSED_XY;
texelFormat = Format::COLOR_COMPRESSED_BCX_XY;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) {
mipFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH;
texelFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH;
texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) {
mipFormat = Format::COLOR_COMPRESSED_HDR_RGB;
texelFormat = Format::COLOR_COMPRESSED_HDR_RGB;
texelFormat = Format::COLOR_COMPRESSED_BCX_HDR_RGB;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB8_ETC2) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_RGB;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_ETC2) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGB;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGBA8_ETC2_EAC) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_RGBA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGBA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_R11_EAC) {
texelFormat = Format::COLOR_COMPRESSED_EAC_RED;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SIGNED_R11_EAC) {
texelFormat = Format::COLOR_COMPRESSED_EAC_RED_SIGNED;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG11_EAC) {
texelFormat = Format::COLOR_COMPRESSED_EAC_XY;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SIGNED_RG11_EAC) {
texelFormat = Format::COLOR_COMPRESSED_EAC_XY_SIGNED;
} else {
return false;
}
mipFormat = texelFormat;
} else {
return false;
}
return true;
}
}

View file

@ -87,6 +87,17 @@ namespace gpu {
{ Semantic::COMPRESSED_BC6_RGB, "compressed_bc6_rgb" },
{ Semantic::COMPRESSED_BC7_SRGBA, "compressed_bc7_srgba" },
{ Semantic::COMPRESSED_ETC2_RGB, "compressed_etc2_rgb" },
{ Semantic::COMPRESSED_ETC2_SRGB, "compressed_etc2_srgb" },
{ Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA, "compressed_etc2_rgb_punchthrough_alpha" },
{ Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA, "compressed_etc2_srgb_punchthrough_alpha" },
{ Semantic::COMPRESSED_ETC2_RGBA, "compressed_etc2_rgba" },
{ Semantic::COMPRESSED_ETC2_SRGBA, "compressed_etc2_srgba" },
{ Semantic::COMPRESSED_EAC_RED, "compressed_eac_red" },
{ Semantic::COMPRESSED_EAC_RED_SIGNED, "compressed_eac_red_signed" },
{ Semantic::COMPRESSED_EAC_XY, "compressed_eac_xy" },
{ Semantic::COMPRESSED_EAC_XY_SIGNED, "compressed_eac_xy_signed" },
{ Semantic::_LAST_COMPRESSED, "_last_compressed" },
{ Semantic::R11G11B10, "r11g11b10" },

View file

@ -466,7 +466,8 @@ void generateHDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
nvtt::CompressionOptions compressionOptions;
compressionOptions.setQuality(nvtt::Quality_Production);
if (mipFormat == gpu::Element::COLOR_COMPRESSED_HDR_RGB) {
// TODO: gles: generate ETC mips instead?
if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB) {
compressionOptions.setFormat(nvtt::Format_BC6);
} else if (mipFormat == gpu::Element::COLOR_RGB9E5) {
compressionOptions.setFormat(nvtt::Format_RGB);
@ -583,20 +584,21 @@ void generateLDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
nvtt::CompressionOptions compressionOptions;
compressionOptions.setQuality(nvtt::Quality_Production);
// TODO: gles: generate ETC mips instead?
auto mipFormat = texture->getStoredMipFormat();
if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGB) {
if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGB) {
compressionOptions.setFormat(nvtt::Format_BC1);
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA_MASK) {
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA_MASK) {
alphaMode = nvtt::AlphaMode_Transparency;
compressionOptions.setFormat(nvtt::Format_BC1a);
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA) {
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA) {
alphaMode = nvtt::AlphaMode_Transparency;
compressionOptions.setFormat(nvtt::Format_BC3);
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_RED) {
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_RED) {
compressionOptions.setFormat(nvtt::Format_BC4);
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_XY) {
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_XY) {
compressionOptions.setFormat(nvtt::Format_BC5);
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA_HIGH) {
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH) {
alphaMode = nvtt::AlphaMode_Transparency;
compressionOptions.setFormat(nvtt::Format_BC7);
} else if (mipFormat == gpu::Element::COLOR_RGBA_32) {
@ -736,13 +738,21 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
gpu::Element formatMip;
gpu::Element formatGPU;
if (isColorTexturesCompressionEnabled()) {
#ifndef USE_GLES
if (validAlpha) {
// NOTE: This disables BC1a compression because it was producing odd artifacts on text textures
// for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts).
formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA;
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_SRGBA;
} else {
formatGPU = gpu::Element::COLOR_COMPRESSED_SRGB;
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_SRGB;
}
#else
if (validAlpha) {
formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGBA;
} else {
formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGB;
}
#endif
formatMip = formatGPU;
} else {
#ifdef USE_GLES
@ -869,8 +879,12 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr
gpu::Element formatMip = gpu::Element::VEC2NU8_XY;
gpu::Element formatGPU = gpu::Element::VEC2NU8_XY;
if (isNormalTexturesCompressionEnabled()) {
formatMip = gpu::Element::COLOR_COMPRESSED_XY;
formatGPU = gpu::Element::COLOR_COMPRESSED_XY;
#ifndef USE_GLES
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY;
#else
formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_XY;
#endif
formatMip = formatGPU;
}
theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR));
@ -903,8 +917,12 @@ gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& sr
gpu::Element formatMip;
gpu::Element formatGPU;
if (isGrayscaleTexturesCompressionEnabled()) {
formatMip = gpu::Element::COLOR_COMPRESSED_RED;
formatGPU = gpu::Element::COLOR_COMPRESSED_RED;
#ifndef USE_GLES
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED;
#else
formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_RED;
#endif
formatMip = formatGPU;
} else {
formatMip = gpu::Element::COLOR_R_8;
formatGPU = gpu::Element::COLOR_R_8;
@ -1271,8 +1289,9 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcI
gpu::Element formatMip;
gpu::Element formatGPU;
if (isCubeTexturesCompressionEnabled()) {
formatMip = gpu::Element::COLOR_COMPRESSED_HDR_RGB;
formatGPU = gpu::Element::COLOR_COMPRESSED_HDR_RGB;
// TODO: gles: pick HDR ETC format
formatMip = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
} else {
formatMip = HDR_FORMAT;
formatGPU = HDR_FORMAT;

View file

@ -358,6 +358,17 @@ namespace khronos {
case InternalFormat::COMPRESSED_RG_RGTC2: // BC5
case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: // BC6
case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7
// ETC2 / EAC
case InternalFormat::COMPRESSED_RGB8_ETC2:
case InternalFormat::COMPRESSED_SRGB8_ETC2:
case InternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case InternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case InternalFormat::COMPRESSED_RGBA8_ETC2_EAC:
case InternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
case InternalFormat::COMPRESSED_R11_EAC:
case InternalFormat::COMPRESSED_SIGNED_R11_EAC:
case InternalFormat::COMPRESSED_RG11_EAC:
case InternalFormat::COMPRESSED_SIGNED_RG11_EAC:
return evalAlignedCompressedBlockCount<4>(value);
default:
@ -370,12 +381,22 @@ namespace khronos {
case InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT:
case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
case InternalFormat::COMPRESSED_RED_RGTC1:
case InternalFormat::COMPRESSED_RGB8_ETC2:
case InternalFormat::COMPRESSED_SRGB8_ETC2:
case InternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case InternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case InternalFormat::COMPRESSED_R11_EAC:
case InternalFormat::COMPRESSED_SIGNED_R11_EAC:
return 8;
case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
case InternalFormat::COMPRESSED_RG_RGTC2:
case InternalFormat::COMPRESSED_RGBA8_ETC2_EAC:
case InternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
case InternalFormat::COMPRESSED_RG11_EAC:
case InternalFormat::COMPRESSED_SIGNED_RG11_EAC:
return 16;
default: