Handle initialising texture levels that might not be ready

* This could happen with a missed call to glGenerateMipmap
This commit is contained in:
baldurk
2015-07-18 20:18:33 +02:00
parent ba225d02b9
commit 70d98240d9
3 changed files with 141 additions and 0 deletions
+76
View File
@@ -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<byte> 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)
+64
View File
@@ -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;
+1
View File
@@ -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);