mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-26 23:55:46 +00:00
Add vendor check to avoid glCopyImageSubData on <4x4 compressed mips
This commit is contained in:
@@ -180,6 +180,41 @@ void DoVendorChecks(const GLHookSet &gl, GLWindowingData context)
|
||||
}
|
||||
}
|
||||
|
||||
// AMD throws an error if we try to copy the mips that are smaller than 4x4,
|
||||
if(gl.glGetError && gl.glGenTextures && gl.glBindTexture && gl.glCopyImageSubData &&
|
||||
gl.glTexStorage2D && gl.glTexParameteri && gl.glDeleteTextures)
|
||||
{
|
||||
GLuint texs[2];
|
||||
gl.glGenTextures(2, texs);
|
||||
|
||||
gl.glBindTexture(eGL_TEXTURE_2D, texs[0]);
|
||||
gl.glTexStorage2D(eGL_TEXTURE_2D, 1, eGL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 1, 1);
|
||||
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAX_LEVEL, 1);
|
||||
|
||||
gl.glBindTexture(eGL_TEXTURE_2D, texs[1]);
|
||||
gl.glTexStorage2D(eGL_TEXTURE_2D, 1, eGL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 1, 1);
|
||||
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAX_LEVEL, 1);
|
||||
|
||||
// clear all error flags.
|
||||
GLenum err = gl.glGetError();
|
||||
while(err != eGL_NONE) err = gl.glGetError();
|
||||
|
||||
gl.glCopyImageSubData(texs[0], eGL_TEXTURE_2D, 0, 0, 0, 0, texs[1], eGL_TEXTURE_2D, 0, 0, 0, 0, 1, 1, 1);
|
||||
|
||||
err = gl.glGetError();
|
||||
|
||||
if(err != eGL_NONE)
|
||||
{
|
||||
// if we got an error trying to query that, we should enable this hack
|
||||
VendorCheck[VendorCheck_AMD_copy_compressed_tinymips] = true;
|
||||
|
||||
RDCWARN("Using hack to avoid glCopyImageSubData on lowest mips of compressed texture");
|
||||
}
|
||||
|
||||
gl.glBindTexture(eGL_TEXTURE_2D, 0);
|
||||
gl.glDeleteTextures(2, texs);
|
||||
}
|
||||
|
||||
// only do this when we have a proper context e.g. on windows where an old
|
||||
// context is first created. Check to see if FBOs or VAOs are shared between
|
||||
// contexts.
|
||||
|
||||
@@ -111,6 +111,7 @@ enum VendorCheckEnum
|
||||
VendorCheck_EXT_fbo_shared,
|
||||
VendorCheck_EXT_vao_shared,
|
||||
VendorCheck_AMD_polygon_mode_query,
|
||||
VendorCheck_AMD_copy_compressed_tinymips,
|
||||
VendorCheck_Count,
|
||||
};
|
||||
extern bool VendorCheck[VendorCheck_Count];
|
||||
|
||||
@@ -272,6 +272,49 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
|
||||
int maxlevel = mips-1;
|
||||
gl.glTextureParameterivEXT(res.name, details.curType, eGL_TEXTURE_MAX_LEVEL, (GLint *)&maxlevel);
|
||||
|
||||
bool iscomp = IsCompressedFormat(details.internalFormat);
|
||||
|
||||
GLint packParams[8];
|
||||
GLint unpackParams[8];
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips])
|
||||
{
|
||||
gl.glGetIntegerv(eGL_PACK_SWAP_BYTES, &packParams[0]);
|
||||
gl.glGetIntegerv(eGL_PACK_LSB_FIRST, &packParams[1]);
|
||||
gl.glGetIntegerv(eGL_PACK_ROW_LENGTH, &packParams[2]);
|
||||
gl.glGetIntegerv(eGL_PACK_IMAGE_HEIGHT, &packParams[3]);
|
||||
gl.glGetIntegerv(eGL_PACK_SKIP_PIXELS, &packParams[4]);
|
||||
gl.glGetIntegerv(eGL_PACK_SKIP_ROWS, &packParams[5]);
|
||||
gl.glGetIntegerv(eGL_PACK_SKIP_IMAGES, &packParams[6]);
|
||||
gl.glGetIntegerv(eGL_PACK_ALIGNMENT, &packParams[7]);
|
||||
|
||||
gl.glPixelStorei(eGL_PACK_SWAP_BYTES, 0);
|
||||
gl.glPixelStorei(eGL_PACK_LSB_FIRST, 0);
|
||||
gl.glPixelStorei(eGL_PACK_ROW_LENGTH, 0);
|
||||
gl.glPixelStorei(eGL_PACK_IMAGE_HEIGHT, 0);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_PIXELS, 0);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_ROWS, 0);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_IMAGES, 0);
|
||||
gl.glPixelStorei(eGL_PACK_ALIGNMENT, 1);
|
||||
|
||||
gl.glGetIntegerv(eGL_UNPACK_SWAP_BYTES, &unpackParams[0]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_LSB_FIRST, &unpackParams[1]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &unpackParams[2]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_IMAGE_HEIGHT, &unpackParams[3]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_SKIP_PIXELS, &unpackParams[4]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_SKIP_ROWS, &unpackParams[5]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_SKIP_IMAGES, &unpackParams[6]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &unpackParams[7]);
|
||||
|
||||
gl.glPixelStorei(eGL_UNPACK_SWAP_BYTES, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_LSB_FIRST, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_ROW_LENGTH, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_IMAGE_HEIGHT, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_PIXELS, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_ROWS, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_IMAGES, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_ALIGNMENT, 1);
|
||||
}
|
||||
|
||||
// copy over mips
|
||||
for(int i=0; i < mips; i++)
|
||||
{
|
||||
@@ -286,15 +329,89 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
|
||||
details.curType == eGL_TEXTURE_2D_ARRAY)
|
||||
d = details.depth;
|
||||
|
||||
// it seems like everything explodes if I do glCopyImageSubData on a D32F_S8 texture - in-program the overlay
|
||||
// gets corrupted as one UBO seems to not provide data anymore until it's "refreshed". It seems like a driver bug,
|
||||
// nvidia specific.
|
||||
// In most cases a program isn't going to rely on the contents of a depth-stencil buffer (shadow maps that it might
|
||||
// require would be depth-only formatted).
|
||||
if(details.internalFormat == eGL_DEPTH32F_STENCIL8 && VendorCheck[VendorCheck_NV_avoid_D32S8_copy])
|
||||
RDCDEBUG("Not fetching initial contents of D32F_S8 texture");
|
||||
// AMD throws an error copying mips that are smaller than the block size in one dimension, so do copy via
|
||||
// CPU instead (will be slow, potentially we could optimise this if there's a different GPU-side image copy
|
||||
// routine that works on these dimensions. Hopefully there'll only be a couple of such mips).
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips] && (w < 4 || h < 4))
|
||||
{
|
||||
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(details.curType != eGL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
targets[0] = details.curType;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
for(int trg=0; trg < count; trg++)
|
||||
{
|
||||
GLint compSize;
|
||||
gl.glGetTextureLevelParameterivEXT(res.name, targets[trg], i, eGL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize);
|
||||
|
||||
size_t size = compSize;
|
||||
|
||||
// sometimes cubemaps return the compressed image size for the whole texture, but we read it
|
||||
// face by face
|
||||
if(VendorCheck[VendorCheck_EXT_compressed_cube_size] && details.curType == eGL_TEXTURE_CUBE_MAP)
|
||||
size /= 6;
|
||||
|
||||
byte *buf = new byte[size];
|
||||
|
||||
// read to CPU
|
||||
gl.glGetCompressedTextureImageEXT(res.name, targets[trg], i, buf);
|
||||
|
||||
// write to GPU
|
||||
if(details.dimension == 1)
|
||||
gl.glCompressedTextureSubImage1DEXT(tex, targets[trg], i, 0, w, details.internalFormat, (GLsizei)size, buf);
|
||||
else if(details.dimension == 2)
|
||||
gl.glCompressedTextureSubImage2DEXT(tex, targets[trg], i, 0, 0, w, h, details.internalFormat, (GLsizei)size, buf);
|
||||
else if(details.dimension == 3)
|
||||
gl.glCompressedTextureSubImage3DEXT(tex, targets[trg], i, 0, 0, 0, w, h, d, details.internalFormat, (GLsizei)size, buf);
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
}
|
||||
else
|
||||
gl.glCopyImageSubData(res.name, details.curType, i, 0, 0, 0, tex, details.curType, i, 0, 0, 0, w, h, d);
|
||||
{
|
||||
// it seems like everything explodes if I do glCopyImageSubData on a D32F_S8 texture - in-program the overlay
|
||||
// gets corrupted as one UBO seems to not provide data anymore until it's "refreshed". It seems like a driver bug,
|
||||
// nvidia specific.
|
||||
// In most cases a program isn't going to rely on the contents of a depth-stencil buffer (shadow maps that it might
|
||||
// require would be depth-only formatted).
|
||||
if(details.internalFormat == eGL_DEPTH32F_STENCIL8 && VendorCheck[VendorCheck_NV_avoid_D32S8_copy])
|
||||
RDCDEBUG("Not fetching initial contents of D32F_S8 texture");
|
||||
else
|
||||
gl.glCopyImageSubData(res.name, details.curType, i, 0, 0, 0, tex, details.curType, i, 0, 0, 0, w, h, d);
|
||||
}
|
||||
}
|
||||
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips])
|
||||
{
|
||||
gl.glPixelStorei(eGL_PACK_SWAP_BYTES, packParams[0]);
|
||||
gl.glPixelStorei(eGL_PACK_LSB_FIRST, packParams[1]);
|
||||
gl.glPixelStorei(eGL_PACK_ROW_LENGTH, packParams[2]);
|
||||
gl.glPixelStorei(eGL_PACK_IMAGE_HEIGHT, packParams[3]);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_PIXELS, packParams[4]);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_ROWS, packParams[5]);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_IMAGES, packParams[6]);
|
||||
gl.glPixelStorei(eGL_PACK_ALIGNMENT, packParams[7]);
|
||||
|
||||
gl.glPixelStorei(eGL_UNPACK_SWAP_BYTES, unpackParams[0]);
|
||||
gl.glPixelStorei(eGL_UNPACK_LSB_FIRST, unpackParams[1]);
|
||||
gl.glPixelStorei(eGL_UNPACK_ROW_LENGTH, unpackParams[2]);
|
||||
gl.glPixelStorei(eGL_UNPACK_IMAGE_HEIGHT, unpackParams[3]);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_PIXELS, unpackParams[4]);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_ROWS, unpackParams[5]);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_IMAGES, unpackParams[6]);
|
||||
gl.glPixelStorei(eGL_UNPACK_ALIGNMENT, unpackParams[7]);
|
||||
}
|
||||
|
||||
gl.glTextureParameterivEXT(res.name, details.curType, eGL_TEXTURE_MAX_LEVEL, (GLint *)&state->maxLevel);
|
||||
@@ -965,7 +1082,50 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i
|
||||
// correct MAX_LEVEL is set to whatever the program had.
|
||||
int maxlevel = mips-1;
|
||||
gl.glTextureParameterivEXT(live.name, details.curType, eGL_TEXTURE_MAX_LEVEL, (GLint *)&maxlevel);
|
||||
|
||||
bool iscomp = IsCompressedFormat(details.internalFormat);
|
||||
|
||||
GLint packParams[8];
|
||||
GLint unpackParams[8];
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips])
|
||||
{
|
||||
gl.glGetIntegerv(eGL_PACK_SWAP_BYTES, &packParams[0]);
|
||||
gl.glGetIntegerv(eGL_PACK_LSB_FIRST, &packParams[1]);
|
||||
gl.glGetIntegerv(eGL_PACK_ROW_LENGTH, &packParams[2]);
|
||||
gl.glGetIntegerv(eGL_PACK_IMAGE_HEIGHT, &packParams[3]);
|
||||
gl.glGetIntegerv(eGL_PACK_SKIP_PIXELS, &packParams[4]);
|
||||
gl.glGetIntegerv(eGL_PACK_SKIP_ROWS, &packParams[5]);
|
||||
gl.glGetIntegerv(eGL_PACK_SKIP_IMAGES, &packParams[6]);
|
||||
gl.glGetIntegerv(eGL_PACK_ALIGNMENT, &packParams[7]);
|
||||
|
||||
gl.glPixelStorei(eGL_PACK_SWAP_BYTES, 0);
|
||||
gl.glPixelStorei(eGL_PACK_LSB_FIRST, 0);
|
||||
gl.glPixelStorei(eGL_PACK_ROW_LENGTH, 0);
|
||||
gl.glPixelStorei(eGL_PACK_IMAGE_HEIGHT, 0);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_PIXELS, 0);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_ROWS, 0);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_IMAGES, 0);
|
||||
gl.glPixelStorei(eGL_PACK_ALIGNMENT, 1);
|
||||
|
||||
gl.glGetIntegerv(eGL_UNPACK_SWAP_BYTES, &unpackParams[0]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_LSB_FIRST, &unpackParams[1]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &unpackParams[2]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_IMAGE_HEIGHT, &unpackParams[3]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_SKIP_PIXELS, &unpackParams[4]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_SKIP_ROWS, &unpackParams[5]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_SKIP_IMAGES, &unpackParams[6]);
|
||||
gl.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &unpackParams[7]);
|
||||
|
||||
gl.glPixelStorei(eGL_UNPACK_SWAP_BYTES, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_LSB_FIRST, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_ROW_LENGTH, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_IMAGE_HEIGHT, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_PIXELS, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_ROWS, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_IMAGES, 0);
|
||||
gl.glPixelStorei(eGL_UNPACK_ALIGNMENT, 1);
|
||||
}
|
||||
|
||||
// copy over mips
|
||||
for(int i=0; i < mips; i++)
|
||||
{
|
||||
@@ -980,15 +1140,89 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i
|
||||
details.curType == eGL_TEXTURE_2D_ARRAY)
|
||||
d = details.depth;
|
||||
|
||||
// it seems like everything explodes if I do glCopyImageSubData on a D32F_S8 texture - on replay loads of things
|
||||
// get heavily corrupted - probably the same as the problems we get in-program, but magnified. It seems like a driver bug,
|
||||
// nvidia specific.
|
||||
// In most cases a program isn't going to rely on the contents of a depth-stencil buffer (shadow maps that it might
|
||||
// require would be depth-only formatted).
|
||||
if(details.internalFormat == eGL_DEPTH32F_STENCIL8 && VendorCheck[VendorCheck_NV_avoid_D32S8_copy])
|
||||
RDCDEBUG("Not fetching initial contents of D32F_S8 texture");
|
||||
// AMD throws an error copying mips that are smaller than the block size in one dimension, so do copy via
|
||||
// CPU instead (will be slow, potentially we could optimise this if there's a different GPU-side image copy
|
||||
// routine that works on these dimensions. Hopefully there'll only be a couple of such mips).
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips] && (w < 4 || h < 4))
|
||||
{
|
||||
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(details.curType != eGL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
targets[0] = details.curType;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
for(int trg=0; trg < count; trg++)
|
||||
{
|
||||
GLint compSize;
|
||||
gl.glGetTextureLevelParameterivEXT(tex, targets[trg], i, eGL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize);
|
||||
|
||||
size_t size = compSize;
|
||||
|
||||
// sometimes cubemaps return the compressed image size for the whole texture, but we read it
|
||||
// face by face
|
||||
if(VendorCheck[VendorCheck_EXT_compressed_cube_size] && details.curType == eGL_TEXTURE_CUBE_MAP)
|
||||
size /= 6;
|
||||
|
||||
byte *buf = new byte[size];
|
||||
|
||||
// read to CPU
|
||||
gl.glGetCompressedTextureImageEXT(tex, targets[trg], i, buf);
|
||||
|
||||
// write to GPU
|
||||
if(details.dimension == 1)
|
||||
gl.glCompressedTextureSubImage1DEXT(live.name, targets[trg], i, 0, w, details.internalFormat, (GLsizei)size, buf);
|
||||
else if(details.dimension == 2)
|
||||
gl.glCompressedTextureSubImage2DEXT(live.name, targets[trg], i, 0, 0, w, h, details.internalFormat, (GLsizei)size, buf);
|
||||
else if(details.dimension == 3)
|
||||
gl.glCompressedTextureSubImage3DEXT(live.name, targets[trg], i, 0, 0, 0, w, h, d, details.internalFormat, (GLsizei)size, buf);
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
}
|
||||
else
|
||||
gl.glCopyImageSubData(tex, details.curType, i, 0, 0, 0, live.name, details.curType, i, 0, 0, 0, w, h, d);
|
||||
{
|
||||
// it seems like everything explodes if I do glCopyImageSubData on a D32F_S8 texture - on replay loads of things
|
||||
// get heavily corrupted - probably the same as the problems we get in-program, but magnified. It seems like a driver bug,
|
||||
// nvidia specific.
|
||||
// In most cases a program isn't going to rely on the contents of a depth-stencil buffer (shadow maps that it might
|
||||
// require would be depth-only formatted).
|
||||
if(details.internalFormat == eGL_DEPTH32F_STENCIL8 && VendorCheck[VendorCheck_NV_avoid_D32S8_copy])
|
||||
RDCDEBUG("Not fetching initial contents of D32F_S8 texture");
|
||||
else
|
||||
gl.glCopyImageSubData(tex, details.curType, i, 0, 0, 0, live.name, details.curType, i, 0, 0, 0, w, h, d);
|
||||
}
|
||||
}
|
||||
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips])
|
||||
{
|
||||
gl.glPixelStorei(eGL_PACK_SWAP_BYTES, packParams[0]);
|
||||
gl.glPixelStorei(eGL_PACK_LSB_FIRST, packParams[1]);
|
||||
gl.glPixelStorei(eGL_PACK_ROW_LENGTH, packParams[2]);
|
||||
gl.glPixelStorei(eGL_PACK_IMAGE_HEIGHT, packParams[3]);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_PIXELS, packParams[4]);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_ROWS, packParams[5]);
|
||||
gl.glPixelStorei(eGL_PACK_SKIP_IMAGES, packParams[6]);
|
||||
gl.glPixelStorei(eGL_PACK_ALIGNMENT, packParams[7]);
|
||||
|
||||
gl.glPixelStorei(eGL_UNPACK_SWAP_BYTES, unpackParams[0]);
|
||||
gl.glPixelStorei(eGL_UNPACK_LSB_FIRST, unpackParams[1]);
|
||||
gl.glPixelStorei(eGL_UNPACK_ROW_LENGTH, unpackParams[2]);
|
||||
gl.glPixelStorei(eGL_UNPACK_IMAGE_HEIGHT, unpackParams[3]);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_PIXELS, unpackParams[4]);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_ROWS, unpackParams[5]);
|
||||
gl.glPixelStorei(eGL_UNPACK_SKIP_IMAGES, unpackParams[6]);
|
||||
gl.glPixelStorei(eGL_UNPACK_ALIGNMENT, unpackParams[7]);
|
||||
}
|
||||
|
||||
TextureStateInitialData *state = (TextureStateInitialData *)initial.blob;
|
||||
|
||||
Reference in New Issue
Block a user