From 70d98240d92387fd145aed25d50bd80b8ca1769d Mon Sep 17 00:00:00 2001 From: baldurk Date: Sat, 18 Jul 2015 20:18:33 +0200 Subject: [PATCH] Handle initialising texture levels that might not be ready * This could happen with a missed call to glGenerateMipmap --- renderdoc/driver/gl/gl_manager.cpp | 76 ++++++++++++++++++++++++++++ renderdoc/driver/gl/gl_resources.cpp | 64 +++++++++++++++++++++++ renderdoc/driver/gl/gl_resources.h | 1 + 3 files changed, 141 insertions(+) diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index fae7ca2b6..969c02ba1 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -1108,6 +1108,82 @@ bool GLResourceManager::Serialise_InitialState(GLResource res) SERIALISE_ELEMENT(int, mips, 0); SERIALISE_ELEMENT(bool, isCompressed, false); + // if number of mips isn't sufficient, make sure to initialise + // the lower levels - this could happen if e.g. a texture is + // init'd with glTexImage(level = 0), then after we stop tracking + // it glGenerateMipmap is called + { + GLuint live = GetLiveResource(Id).name; + + GLsizei w = (GLsizei)width; + GLsizei h = (GLsizei)height; + GLsizei d = (GLsizei)depth; + + int liveMips = GetNumMips(gl, textype, live, width, height, depth); + + GLenum targets[] = { + eGL_TEXTURE_CUBE_MAP_POSITIVE_X, + eGL_TEXTURE_CUBE_MAP_NEGATIVE_X, + eGL_TEXTURE_CUBE_MAP_POSITIVE_Y, + eGL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + eGL_TEXTURE_CUBE_MAP_POSITIVE_Z, + eGL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + }; + + int count = ARRAY_COUNT(targets); + + if(textype != eGL_TEXTURE_CUBE_MAP) + { + targets[0] = textype; + count = 1; + } + + for(int m = 1; m < mips; m++) + { + w = RDCMAX(1, w >> 1); + h = RDCMAX(1, h >> 1); + d = RDCMAX(1, d >> 1); + + if(textype == eGL_TEXTURE_CUBE_MAP_ARRAY || + textype == eGL_TEXTURE_1D_ARRAY || + textype == eGL_TEXTURE_2D_ARRAY) + d = (GLsizei)depth; + + if(m >= liveMips) + { + for(int t=0; t < count; t++) + { + if(isCompressed) + { + GLsizei compSize = (GLsizei)GetCompressedByteSize(w, h, d, internalformat, m); + + vector dummy; + dummy.resize(compSize); + + if(dim == 1) + gl.glCompressedTextureImage1DEXT(live, targets[t], m, internalformat, w, 0, compSize, &dummy[0]); + else if(dim == 2) + gl.glCompressedTextureImage2DEXT(live, targets[t], m, internalformat, w, h, 0, compSize, &dummy[0]); + else if(dim == 3) + gl.glCompressedTextureImage3DEXT(live, targets[t], m, internalformat, w, h, d, 0, compSize, &dummy[0]); + } + else + { + if(dim == 1) + gl.glTextureImage1DEXT(live, targets[t], m, internalformat, (GLsizei)w, 0, + GetBaseFormat(internalformat), GetDataType(internalformat), NULL); + else if(dim == 2) + gl.glTextureImage2DEXT(live, targets[t], m, internalformat, (GLsizei)w, (GLsizei)h, 0, + GetBaseFormat(internalformat), GetDataType(internalformat), NULL); + else if(dim == 3) + gl.glTextureImage3DEXT(live, targets[t], m, internalformat, (GLsizei)w, (GLsizei)h, (GLsizei)d, 0, + GetBaseFormat(internalformat), GetDataType(internalformat), NULL); + } + } + } + } + } + GLuint tex = 0; if(textype != eGL_TEXTURE_BUFFER) diff --git a/renderdoc/driver/gl/gl_resources.cpp b/renderdoc/driver/gl/gl_resources.cpp index b744d2e8a..7153ebd56 100644 --- a/renderdoc/driver/gl/gl_resources.cpp +++ b/renderdoc/driver/gl/gl_resources.cpp @@ -25,6 +25,70 @@ #include "gl_hookset.h" #include "gl_resources.h" +size_t GetCompressedByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum internalformat, int mip) +{ + if(!IsCompressedFormat(internalformat)) + { + RDCERR("Not compressed format"); + return GetByteSize(w, h, d, GetBaseFormat(internalformat), GetDataType(internalformat)); + } + + switch(internalformat) + { + // BC1 + case eGL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case eGL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case eGL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + return (AlignUp4(w) * AlignUp4(h) * d) / 2; + // BC2 + case eGL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + return (AlignUp4(w) * AlignUp4(h) * d); + // BC3 + case eGL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + return (AlignUp4(w) * AlignUp4(h) * d); + // BC4 + case eGL_COMPRESSED_RED_RGTC1: + case eGL_COMPRESSED_SIGNED_RED_RGTC1: + return (AlignUp4(w) * AlignUp4(h) * d) / 2; + // BC5 + case eGL_COMPRESSED_RG_RGTC2: + case eGL_COMPRESSED_SIGNED_RG_RGTC2: + return (AlignUp4(w) * AlignUp4(h) * d); + // BC6 + case eGL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: + case eGL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: + return (AlignUp4(w) * AlignUp4(h) * d); + // BC7 + case eGL_COMPRESSED_RGBA_BPTC_UNORM_ARB: + case eGL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: + return (AlignUp4(w) * AlignUp4(h) * d); + // ETC2 + case eGL_COMPRESSED_RGB8_ETC2: + case eGL_COMPRESSED_SRGB8_ETC2: + case eGL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case eGL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + return (AlignUp4(w) * AlignUp4(h) * d) / 2; + // EAC + case eGL_COMPRESSED_RGBA8_ETC2_EAC: + case eGL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + return (AlignUp4(w) * AlignUp4(h) * d); + case eGL_COMPRESSED_R11_EAC: + case eGL_COMPRESSED_SIGNED_R11_EAC: + return (AlignUp4(w) * AlignUp4(h) * d) / 2; + case eGL_COMPRESSED_RG11_EAC: + case eGL_COMPRESSED_SIGNED_RG11_EAC: + return (AlignUp4(w) * AlignUp4(h) * d); + default: + break; + } + + RDCERR("Unrecognised compressed format"); + return GetByteSize(w, h, d, GetBaseFormat(internalformat), GetDataType(internalformat)); +} + size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type) { size_t elemSize = 0; diff --git a/renderdoc/driver/gl/gl_resources.h b/renderdoc/driver/gl/gl_resources.h index c5c975def..1fe271b32 100644 --- a/renderdoc/driver/gl/gl_resources.h +++ b/renderdoc/driver/gl/gl_resources.h @@ -31,6 +31,7 @@ struct GLHookSet; +size_t GetCompressedByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum internalformat, int mip); size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type); GLenum GetBaseFormat(GLenum internalFormat); GLenum GetDataType(GLenum internalFormat);