diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp index 6e918b2de1..a865a11135 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp @@ -645,6 +645,18 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::COMPRESSED_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; break; + case gpu::COMPRESSED_BC3_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + case gpu::COMPRESSED_BC3_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + break; + case gpu::COMPRESSED_BC7_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; + break; + case gpu::COMPRESSED_BC7_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; + break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp index 19891d3370..30d2bc8377 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp @@ -120,11 +120,12 @@ void GLTexture::copyMipFaceFromTexture(uint16_t sourceMip, uint16_t targetMip, u } auto size = _gpuObject.evalMipDimensions(sourceMip); auto mipData = _gpuObject.accessStoredMipFace(sourceMip, face); + auto mipSize = _gpuObject.getStoredMipFaceSize(sourceMip, face); if (mipData) { GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), _gpuObject.getStoredMipFormat()); - copyMipFaceLinesFromTexture(targetMip, face, size, 0, texelFormat.format, texelFormat.type, mipData->readData()); + copyMipFaceLinesFromTexture(targetMip, face, size, 0, texelFormat.format, texelFormat.internalFormat, texelFormat.type, mipSize, mipData->readData()); } else { - qCDebug(gpugllogging) << "Missing mipData level=" << sourceMip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); + qCDebug(gpugllogging) << "Missing mipData level=" << sourceMip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); } } @@ -203,9 +204,11 @@ TransferJob::TransferJob(const GLTexture& parent, uint16_t sourceMip, uint16_t t auto transferDimensions = _parent._gpuObject.evalMipDimensions(sourceMip); GLenum format; + GLenum internalFormat; GLenum type; GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_parent._gpuObject.getTexelFormat(), _parent._gpuObject.getStoredMipFormat()); format = texelFormat.format; + internalFormat = texelFormat.internalFormat; type = texelFormat.type; auto mipSize = _parent._gpuObject.getStoredMipFaceSize(sourceMip, face); @@ -236,7 +239,7 @@ TransferJob::TransferJob(const GLTexture& parent, uint16_t sourceMip, uint16_t t Backend::updateTextureTransferPendingSize(0, _transferSize); _transferLambda = [=] { - _parent.copyMipFaceLinesFromTexture(targetMip, face, transferDimensions, lineOffset, format, type, _buffer.data()); + _parent.copyMipFaceLinesFromTexture(targetMip, face, transferDimensions, lineOffset, format, internalFormat, type, _buffer.size(), _buffer.data()); std::vector emptyVector; _buffer.swap(emptyVector); }; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.h b/libraries/gpu-gl/src/gpu/gl/GLTexture.h index 960575827f..f12ac12df3 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.h +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.h @@ -163,7 +163,7 @@ public: protected: virtual Size size() const = 0; virtual void generateMips() const = 0; - virtual void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const = 0; + virtual void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const = 0; virtual void copyMipFaceFromTexture(uint16_t sourceMip, uint16_t targetMip, uint8_t face) const final; GLTexture(const std::weak_ptr& backend, const Texture& texture, GLuint id); diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index 545279627a..3f530e28b8 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -50,7 +50,7 @@ public: protected: GL41Texture(const std::weak_ptr& backend, const Texture& texture); void generateMips() const override; - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const override; + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override; virtual void syncSampler() const; void withPreservedTexture(std::function f) const; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index e2e1b164cf..2501f8b06b 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -92,9 +92,15 @@ void GL41Texture::generateMips() const { (void)CHECK_GL_ERROR(); } -void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const { +void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { if (GL_TEXTURE_2D == _target) { - glTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + if (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT == internalFormat) { + qCDebug(gpugllogging) << "Compressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); + qCDebug(gpugllogging) << "Compressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer; + glCompressedTexImage2D(_target, mip, internalFormat, size.x, size.y, 0, sourceSize, sourcePointer); + } else { + glTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + } } else if (GL_TEXTURE_CUBE_MAP == _target) { auto target = GLTexture::CUBE_FACE_LAYOUT[face]; glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index d80a70cfd1..c1bbfdd162 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -48,7 +48,7 @@ public: protected: GL45Texture(const std::weak_ptr& backend, const Texture& texture); void generateMips() const override; - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const override; + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override; virtual void syncSampler() const; }; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 73974addff..c530af535a 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -117,9 +117,18 @@ void GL45Texture::generateMips() const { (void)CHECK_GL_ERROR(); } -void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const { +void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { if (GL_TEXTURE_2D == _target) { - glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + if (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT == internalFormat) { + qCDebug(gpugllogging) << "Compressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); + qCDebug(gpugllogging) << "Compressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer << "4.5"; + glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + } + else { + qCDebug(gpugllogging) << "Uncompressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); + qCDebug(gpugllogging) << "Uncompressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer << "4.5"; + glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + } } else if (GL_TEXTURE_CUBE_MAP == _target) { // DSA ARB does not work on AMD, so use EXT // unless EXT is not available on the driver diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index de202911e3..cdf5c8345c 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -19,6 +19,8 @@ const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA }; const Element Element::COLOR_BGRA_32{ VEC4, NUINT8, BGRA }; const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA }; +const Element Element::COLOR_COMPRESSED_SRGBA{ VEC4, NUINT8, COMPRESSED_BC3_SRGBA }; + const Element Element::COLOR_R11G11B10{ SCALAR, FLOAT, R11G11B10 }; const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA }; const Element Element::VEC2F_UV{ VEC2, FLOAT, UV }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 97fe76eebc..2b42683d56 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -236,6 +236,7 @@ public: static const Element COLOR_BGRA_32; static const Element COLOR_SBGRA_32; static const Element COLOR_R11G11B10; + static const Element COLOR_COMPRESSED_SRGBA; static const Element VEC4F_COLOR_RGBA; static const Element VEC2F_UV; static const Element VEC2F_XY; diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 1e65972114..6c92886864 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -434,7 +434,7 @@ void Texture::assignStoredMip(uint16 level, storage::StoragePointer& storage) { // THen check that the mem texture passed make sense with its format Size expectedSize = evalStoredMipSize(level, getStoredMipFormat()); auto size = storage->size(); - if (storage->size() == expectedSize) { + if (storage->size() <= expectedSize) { _storage->assignMipData(level, storage); _stamp++; } else if (size > expectedSize) { @@ -461,7 +461,7 @@ void Texture::assignStoredMipFace(uint16 level, uint8 face, storage::StoragePoin // THen check that the mem texture passed make sense with its format Size expectedSize = evalStoredMipFaceSize(level, getStoredMipFormat()); auto size = storage->size(); - if (size == expectedSize) { + if (size <= expectedSize) { _storage->assignMipFaceData(level, face, storage); _stamp++; } else if (size > expectedSize) { diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 28de0c70eb..d61788c7db 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -260,6 +260,9 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RGBA, ktx::GLInternalFormat_Uncompressed::SRGB8_ALPHA8, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_R_8 && mipFormat == Format::COLOR_R_8) { header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat_Uncompressed::R8, ktx::GLBaseInternalFormat::RED); + } else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA && mipFormat == Format::COLOR_COMPRESSED_SRGBA) { + return false; + header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA); } else { return false; } @@ -295,6 +298,13 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E } else { return false; } + } else if (header.getGLFormat() == ktx::GLFormat::COMPRESSED_FORMAT && header.getGLType() == ktx::GLType::COMPRESSED_TYPE) { + if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { + mipFormat = Format::COLOR_COMPRESSED_SRGBA; + texelFormat = Format::COLOR_COMPRESSED_SRGBA; + } else { + return false; + } } else { return false; } diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index f1a8e4e13b..3a71d80e12 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -27,6 +27,9 @@ using namespace gpu; // FIXME: Declare this to enable compression //#define COMPRESS_TEXTURES +#define CPU_MIPMAPS 1 +#define DEBUG_NVTT 1 + static const glm::uvec2 SPARSE_PAGE_SIZE(128); static const glm::uvec2 MAX_TEXTURE_SIZE(4096); bool DEV_DECIMATE_TEXTURES = false; @@ -219,6 +222,10 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, const QImage& image, bool isLinear, bool doCompress) { +#ifdef COMPRESS_TEXTURES +#else + doCompress = false; +#endif if (image.hasAlphaChannel()) { gpu::Semantic gpuSemantic; @@ -226,14 +233,14 @@ void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element if (isLinear) { mipSemantic = gpu::BGRA; if (doCompress) { - gpuSemantic = gpu::COMPRESSED_BC3_RGBA; + gpuSemantic = gpu::COMPRESSED_RGBA; } else { gpuSemantic = gpu::RGBA; } } else { mipSemantic = gpu::SBGRA; if (doCompress) { - gpuSemantic = gpu::COMPRESSED_BC3_SRGBA; + gpuSemantic = gpu::COMPRESSED_SRGBA; } else { gpuSemantic = gpu::SRGBA; } @@ -263,9 +270,6 @@ void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element } } -#define CPU_MIPMAPS 1 -#define DEBUG_NVTT 0 - void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateMips"); @@ -276,6 +280,8 @@ void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; #endif // DEBUG_NVTT + texture->assignStoredMip(0, image.byteCount(), image.constBits()); + auto numMips = texture->getNumMips(); for (uint16 level = 1; level < numMips; ++level) { QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); @@ -305,6 +311,8 @@ void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateFaceMips"); + + auto numMips = texture->getNumMips(); for (uint16 level = 1; level < numMips; ++level) { QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); @@ -390,6 +398,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { return; /**/ + #if DEBUG_NVTT QDebug debug = qDebug(); QDebug* debugPtr = &debug; @@ -409,7 +418,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { nvtt::InputFormat inputFormat = nvtt::InputFormat_BGRA_8UB; nvtt::AlphaMode alphaMode = image.hasAlphaChannel() ? nvtt::AlphaMode_Transparency : nvtt::AlphaMode_None; nvtt::WrapMode wrapMode = nvtt::WrapMode_Repeat; - nvtt::Format compressionFormat = image.hasAlphaChannel() ? nvtt::Format_RGBA : nvtt::Format_RGB; + nvtt::Format compressionFormat = nvtt::Format_BC3; float inputGamma = 1.0f; float outputGamma = 2.2f; @@ -436,7 +445,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat(compressionFormat); - compressionOptions.setQuality(nvtt::Quality_Production); + compressionOptions.setQuality(nvtt::Quality_Fastest); nvtt::Compressor compressor; compressor.process(inputOptions, compressionOptions, outputOptions); @@ -457,6 +466,8 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag gpu::Element formatGPU; gpu::Element formatMip; defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); + formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; + formatMip = gpu::Element::COLOR_COMPRESSED_SRGBA; if (isStrict) { theTexture = (gpu::Texture::createStrict(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -484,11 +495,11 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag } gpu::Texture* TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, false, true, true); } gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, false, true); } gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index f09986991a..23d60bd801 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -101,8 +101,6 @@ namespace ktx { UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B, UNSIGNED_INT_5_9_9_9_REV = 0x8C3E, FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD, - - NUM_GLTYPES = 25, }; enum class GLFormat : uint32_t { @@ -130,8 +128,6 @@ namespace ktx { RGBA_INTEGER = 0x8D99, BGR_INTEGER = 0x8D9A, BGRA_INTEGER = 0x8D9B, - - NUM_GLFORMATS = 20, }; enum class GLInternalFormat_Uncompressed : uint32_t { @@ -232,8 +228,6 @@ namespace ktx { STENCIL_INDEX4 = 0x8D47, STENCIL_INDEX8 = 0x8D48, STENCIL_INDEX16 = 0x8D49, - - NUM_UNCOMPRESSED_GLINTERNALFORMATS = 74, }; enum class GLInternalFormat_Compressed : uint32_t { @@ -267,8 +261,6 @@ namespace ktx { COMPRESSED_SIGNED_R11_EAC = 0x9271, COMPRESSED_RG11_EAC = 0x9272, COMPRESSED_SIGNED_RG11_EAC = 0x9273, - - NUM_COMPRESSED_GLINTERNALFORMATS = 24, }; enum class GLBaseInternalFormat : uint32_t { @@ -280,8 +272,6 @@ namespace ktx { RGB = 0x1907, RGBA = 0x1908, STENCIL_INDEX = 0x1901, - - NUM_GLBASEINTERNALFORMATS = 7, }; enum CubeMapFace {