mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-06 06:41:05 +00:00
Handle initial states of views better (don't try and copy data contents)
This commit is contained in:
@@ -243,6 +243,7 @@ private:
|
||||
: curType(eGL_NONE),
|
||||
dimension(0),
|
||||
emulated(false),
|
||||
view(false),
|
||||
width(0),
|
||||
height(0),
|
||||
depth(0),
|
||||
@@ -256,7 +257,7 @@ private:
|
||||
GLResource resource;
|
||||
GLenum curType;
|
||||
GLint dimension;
|
||||
bool emulated;
|
||||
bool emulated, view;
|
||||
GLint width, height, depth, samples;
|
||||
uint32_t creationFlags;
|
||||
GLenum internalFormat;
|
||||
|
||||
+386
-390
@@ -617,241 +617,240 @@ void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, Resourc
|
||||
state->wrap[2] = eGL_CLAMP_TO_EDGE;
|
||||
}
|
||||
|
||||
// we only copy contents for non-views
|
||||
GLuint tex = 0;
|
||||
|
||||
if(!details.view)
|
||||
{
|
||||
GLuint oldtex = 0;
|
||||
gl.glGetIntegerv(binding, (GLint *)&oldtex);
|
||||
|
||||
gl.glGenTextures(1, &tex);
|
||||
gl.glBindTexture(details.curType, tex);
|
||||
|
||||
gl.glBindTexture(details.curType, oldtex);
|
||||
}
|
||||
|
||||
int depth = details.depth;
|
||||
if(details.curType != eGL_TEXTURE_3D)
|
||||
depth = 1;
|
||||
|
||||
int mips =
|
||||
GetNumMips(gl, details.curType, res.name, details.width, details.height, details.depth);
|
||||
|
||||
// create texture of identical format/size to store initial contents
|
||||
if(details.curType == eGL_TEXTURE_2D_MULTISAMPLE)
|
||||
{
|
||||
gl.glTextureStorage2DMultisampleEXT(tex, details.curType, details.samples,
|
||||
details.internalFormat, details.width, details.height,
|
||||
GL_TRUE);
|
||||
mips = 1;
|
||||
}
|
||||
else if(details.curType == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY)
|
||||
{
|
||||
gl.glTextureStorage3DMultisampleEXT(tex, details.curType, details.samples,
|
||||
details.internalFormat, details.width, details.height,
|
||||
details.depth, GL_TRUE);
|
||||
mips = 1;
|
||||
}
|
||||
else if(details.dimension == 1)
|
||||
{
|
||||
gl.glTextureStorage1DEXT(tex, details.curType, mips, details.internalFormat, details.width);
|
||||
}
|
||||
else if(details.dimension == 2)
|
||||
{
|
||||
gl.glTextureStorage2DEXT(tex, details.curType, mips, details.internalFormat, details.width,
|
||||
details.height);
|
||||
}
|
||||
else if(details.dimension == 3)
|
||||
{
|
||||
gl.glTextureStorage3DEXT(tex, details.curType, mips, details.internalFormat, details.width,
|
||||
details.height, details.depth);
|
||||
}
|
||||
|
||||
// we need to set maxlevel appropriately for number of mips to force the texture to be complete.
|
||||
// This can happen if e.g. a texture is initialised just by default with glTexImage for level 0
|
||||
// and
|
||||
// used as a framebuffer attachment, then the implementation is fine with it. Unfortunately
|
||||
// glCopyImageSubData
|
||||
// requires completeness across all mips, a stricter requirement :(.
|
||||
// We set max_level to mips - 1 (so mips=1 means MAX_LEVEL=0). Then restore it to the 'real'
|
||||
// value we fetched above
|
||||
int maxlevel = mips - 1;
|
||||
gl.glTextureParameterivEXT(res.name, details.curType, eGL_TEXTURE_MAX_LEVEL, (GLint *)&maxlevel);
|
||||
|
||||
bool iscomp = IsCompressedFormat(details.internalFormat);
|
||||
|
||||
bool avoidCopySubImage = false;
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips])
|
||||
avoidCopySubImage = true;
|
||||
if(iscomp && details.curType == eGL_TEXTURE_CUBE_MAP &&
|
||||
VendorCheck[VendorCheck_AMD_copy_compressed_cubemaps])
|
||||
avoidCopySubImage = true;
|
||||
|
||||
GLint packParams[8] = {0};
|
||||
GLint unpackParams[8] = {0};
|
||||
GLuint pixelPackBuffer = 0;
|
||||
GLuint pixelUnpackBuffer = 0;
|
||||
if(avoidCopySubImage)
|
||||
{
|
||||
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);
|
||||
|
||||
gl.glGetIntegerv(eGL_PIXEL_PACK_BUFFER_BINDING, (GLint *)&pixelPackBuffer);
|
||||
gl.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, (GLint *)&pixelUnpackBuffer);
|
||||
gl.glBindBuffer(eGL_PIXEL_PACK_BUFFER, 0);
|
||||
gl.glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
// copy over mips
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
int w = RDCMAX(details.width >> i, 1);
|
||||
int h = RDCMAX(details.height >> i, 1);
|
||||
int d = RDCMAX(details.depth >> i, 1);
|
||||
|
||||
if(details.curType == eGL_TEXTURE_CUBE_MAP)
|
||||
d *= 6;
|
||||
else if(details.curType == eGL_TEXTURE_CUBE_MAP_ARRAY ||
|
||||
details.curType == eGL_TEXTURE_1D_ARRAY || details.curType == eGL_TEXTURE_2D_ARRAY)
|
||||
d = details.depth;
|
||||
|
||||
// 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).
|
||||
//
|
||||
// AMD also has issues copying cubemaps
|
||||
if((iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips] && (w < 4 || h < 4)) ||
|
||||
(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_cubemaps] &&
|
||||
details.curType == eGL_TEXTURE_CUBE_MAP))
|
||||
{
|
||||
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,
|
||||
};
|
||||
GLuint oldtex = 0;
|
||||
gl.glGetIntegerv(binding, (GLint *)&oldtex);
|
||||
|
||||
int count = ARRAY_COUNT(targets);
|
||||
gl.glGenTextures(1, &tex);
|
||||
gl.glBindTexture(details.curType, tex);
|
||||
|
||||
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;
|
||||
}
|
||||
gl.glBindTexture(details.curType, oldtex);
|
||||
}
|
||||
else
|
||||
|
||||
int depth = details.depth;
|
||||
if(details.curType != eGL_TEXTURE_3D)
|
||||
depth = 1;
|
||||
|
||||
int mips =
|
||||
GetNumMips(gl, details.curType, res.name, details.width, details.height, details.depth);
|
||||
|
||||
// create texture of identical format/size to store initial contents
|
||||
if(details.curType == eGL_TEXTURE_2D_MULTISAMPLE)
|
||||
{
|
||||
// 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");
|
||||
gl.glTextureStorage2DMultisampleEXT(tex, details.curType, details.samples,
|
||||
details.internalFormat, details.width, details.height,
|
||||
GL_TRUE);
|
||||
mips = 1;
|
||||
}
|
||||
else if(details.curType == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY)
|
||||
{
|
||||
gl.glTextureStorage3DMultisampleEXT(tex, details.curType, details.samples,
|
||||
details.internalFormat, details.width, details.height,
|
||||
details.depth, GL_TRUE);
|
||||
mips = 1;
|
||||
}
|
||||
else if(details.dimension == 1)
|
||||
{
|
||||
gl.glTextureStorage1DEXT(tex, details.curType, mips, details.internalFormat, details.width);
|
||||
}
|
||||
else if(details.dimension == 2)
|
||||
{
|
||||
gl.glTextureStorage2DEXT(tex, details.curType, mips, details.internalFormat, details.width,
|
||||
details.height);
|
||||
}
|
||||
else if(details.dimension == 3)
|
||||
{
|
||||
gl.glTextureStorage3DEXT(tex, details.curType, mips, details.internalFormat, details.width,
|
||||
details.height, details.depth);
|
||||
}
|
||||
|
||||
// we need to set maxlevel appropriately for number of mips to force the texture to be
|
||||
// complete.
|
||||
// This can happen if e.g. a texture is initialised just by default with glTexImage for level
|
||||
// 0 and used as a framebuffer attachment, then the implementation is fine with it.
|
||||
// Unfortunately glCopyImageSubData requires completeness across all mips, a stricter
|
||||
// requirement :(.
|
||||
// We set max_level to mips - 1 (so mips=1 means MAX_LEVEL=0). Then restore it to the 'real'
|
||||
// value we fetched above
|
||||
int maxlevel = mips - 1;
|
||||
gl.glTextureParameterivEXT(res.name, details.curType, eGL_TEXTURE_MAX_LEVEL,
|
||||
(GLint *)&maxlevel);
|
||||
|
||||
bool iscomp = IsCompressedFormat(details.internalFormat);
|
||||
|
||||
bool avoidCopySubImage = false;
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips])
|
||||
avoidCopySubImage = true;
|
||||
if(iscomp && details.curType == eGL_TEXTURE_CUBE_MAP &&
|
||||
VendorCheck[VendorCheck_AMD_copy_compressed_cubemaps])
|
||||
avoidCopySubImage = true;
|
||||
|
||||
GLint packParams[8] = {0};
|
||||
GLint unpackParams[8] = {0};
|
||||
GLuint pixelPackBuffer = 0;
|
||||
GLuint pixelUnpackBuffer = 0;
|
||||
if(avoidCopySubImage)
|
||||
{
|
||||
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);
|
||||
|
||||
gl.glGetIntegerv(eGL_PIXEL_PACK_BUFFER_BINDING, (GLint *)&pixelPackBuffer);
|
||||
gl.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, (GLint *)&pixelUnpackBuffer);
|
||||
gl.glBindBuffer(eGL_PIXEL_PACK_BUFFER, 0);
|
||||
gl.glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
// copy over mips
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
int w = RDCMAX(details.width >> i, 1);
|
||||
int h = RDCMAX(details.height >> i, 1);
|
||||
int d = RDCMAX(details.depth >> i, 1);
|
||||
|
||||
if(details.curType == eGL_TEXTURE_CUBE_MAP)
|
||||
d *= 6;
|
||||
else if(details.curType == eGL_TEXTURE_CUBE_MAP_ARRAY ||
|
||||
details.curType == eGL_TEXTURE_1D_ARRAY || details.curType == eGL_TEXTURE_2D_ARRAY)
|
||||
d = details.depth;
|
||||
|
||||
// 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).
|
||||
// AMD also has issues copying cubemaps
|
||||
if((iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips] && (w < 4 || h < 4)) ||
|
||||
(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_cubemaps] &&
|
||||
details.curType == eGL_TEXTURE_CUBE_MAP))
|
||||
{
|
||||
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(avoidCopySubImage)
|
||||
{
|
||||
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.glBindBuffer(eGL_PIXEL_PACK_BUFFER, pixelPackBuffer);
|
||||
gl.glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, pixelUnpackBuffer);
|
||||
}
|
||||
|
||||
gl.glTextureParameterivEXT(res.name, details.curType, eGL_TEXTURE_MAX_LEVEL,
|
||||
(GLint *)&state->maxLevel);
|
||||
}
|
||||
|
||||
if(avoidCopySubImage)
|
||||
{
|
||||
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.glBindBuffer(eGL_PIXEL_PACK_BUFFER, pixelPackBuffer);
|
||||
gl.glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, pixelUnpackBuffer);
|
||||
}
|
||||
|
||||
gl.glTextureParameterivEXT(res.name, details.curType, eGL_TEXTURE_MAX_LEVEL,
|
||||
(GLint *)&state->maxLevel);
|
||||
|
||||
SetInitialContents(origid, InitialContentData(TextureRes(res.Context, tex), 0, (byte *)state));
|
||||
}
|
||||
else
|
||||
@@ -1024,9 +1023,10 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res)
|
||||
|
||||
SERIALISE_ELEMENT(bool, isCompressed, IsCompressedFormat(details.internalFormat));
|
||||
|
||||
if(details.curType == eGL_TEXTURE_BUFFER)
|
||||
if(details.curType == eGL_TEXTURE_BUFFER || details.view)
|
||||
{
|
||||
// no contents to copy for texture buffer (it's copied under the buffer)
|
||||
// same applies for texture views, their data is copies under the aliased texture
|
||||
}
|
||||
else if(isCompressed)
|
||||
{
|
||||
@@ -1144,6 +1144,8 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res)
|
||||
}
|
||||
else
|
||||
{
|
||||
WrappedOpenGL::TextureData &details = m_GL->m_Textures[GetLiveID(Id)];
|
||||
|
||||
SERIALISE_ELEMENT(GLenum, internalformat, eGL_NONE);
|
||||
|
||||
if(internalformat != eGL_NONE)
|
||||
@@ -1274,7 +1276,7 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res)
|
||||
|
||||
GLuint tex = 0;
|
||||
|
||||
if(textype != eGL_TEXTURE_BUFFER)
|
||||
if(textype != eGL_TEXTURE_BUFFER && !details.view)
|
||||
{
|
||||
GLuint prevtex = 0;
|
||||
gl.glGetIntegerv(TextureBinding(textype), (GLint *)&prevtex);
|
||||
@@ -1289,7 +1291,7 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res)
|
||||
EmulateLuminanceFormat(gl, tex, textype, internalformat, dummy);
|
||||
|
||||
// create texture of identical format/size to store initial contents
|
||||
if(textype == eGL_TEXTURE_BUFFER)
|
||||
if(textype == eGL_TEXTURE_BUFFER || details.view)
|
||||
{
|
||||
// no 'contents' texture to create
|
||||
}
|
||||
@@ -1318,7 +1320,7 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res)
|
||||
gl.glTextureStorage3DEXT(tex, textype, mips, internalformat, width, height, depth);
|
||||
}
|
||||
|
||||
if(textype == eGL_TEXTURE_BUFFER)
|
||||
if(textype == eGL_TEXTURE_BUFFER || details.view)
|
||||
{
|
||||
// no contents to serialise
|
||||
}
|
||||
@@ -1420,7 +1422,7 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res)
|
||||
}
|
||||
}
|
||||
|
||||
if(textype != eGL_TEXTURE_BUFFER)
|
||||
if(textype != eGL_TEXTURE_BUFFER && !details.view)
|
||||
SetInitialContents(Id,
|
||||
InitialContentData(TextureRes(m_GL->GetCtx(), tex), 0, (byte *)state));
|
||||
else
|
||||
@@ -1562,183 +1564,177 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i
|
||||
{
|
||||
GLuint tex = initial.resource.name;
|
||||
|
||||
int mips = GetNumMips(gl, details.curType, tex, details.width, details.height, details.depth);
|
||||
|
||||
// we need to set maxlevel appropriately for number of mips to force the texture to be
|
||||
// complete.
|
||||
// This can happen if e.g. a texture is initialised just by default with glTexImage for level
|
||||
// 0 and
|
||||
// used as a framebuffer attachment, then the implementation is fine with it. Unfortunately
|
||||
// glCopyImageSubData
|
||||
// requires completeness across all mips, a stricter requirement :(.
|
||||
// We set max_level to mips - 1 (so mips=1 means MAX_LEVEL=0). Then below where we set the
|
||||
// texture state, the
|
||||
// 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);
|
||||
|
||||
bool avoidCopySubImage = false;
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips])
|
||||
avoidCopySubImage = true;
|
||||
if(iscomp && details.curType == eGL_TEXTURE_CUBE_MAP &&
|
||||
VendorCheck[VendorCheck_AMD_copy_compressed_cubemaps])
|
||||
avoidCopySubImage = true;
|
||||
|
||||
GLint packParams[8];
|
||||
GLint unpackParams[8];
|
||||
if(avoidCopySubImage)
|
||||
if(initial.resource != GLResource(MakeNullResource) && tex != 0)
|
||||
{
|
||||
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]);
|
||||
int mips = GetNumMips(gl, details.curType, tex, details.width, details.height, details.depth);
|
||||
|
||||
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);
|
||||
// we need to set maxlevel appropriately for number of mips to force the texture to be
|
||||
// complete. This can happen if e.g. a texture is initialised just by default with
|
||||
// glTexImage for level 0 and used as a framebuffer attachment, then the implementation is
|
||||
// fine with it.
|
||||
// Unfortunately glCopyImageSubData requires completeness across all mips, a stricter
|
||||
// requirement :(.
|
||||
// We set max_level to mips - 1 (so mips=1 means MAX_LEVEL=0). Then below where we set the
|
||||
// texture state, the 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);
|
||||
|
||||
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]);
|
||||
bool iscomp = IsCompressedFormat(details.internalFormat);
|
||||
|
||||
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);
|
||||
}
|
||||
bool avoidCopySubImage = false;
|
||||
if(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips])
|
||||
avoidCopySubImage = true;
|
||||
if(iscomp && details.curType == eGL_TEXTURE_CUBE_MAP &&
|
||||
VendorCheck[VendorCheck_AMD_copy_compressed_cubemaps])
|
||||
avoidCopySubImage = true;
|
||||
|
||||
// copy over mips
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
int w = RDCMAX(details.width >> i, 1);
|
||||
int h = RDCMAX(details.height >> i, 1);
|
||||
int d = RDCMAX(details.depth >> i, 1);
|
||||
|
||||
if(details.curType == eGL_TEXTURE_CUBE_MAP)
|
||||
d *= 6;
|
||||
else if(details.curType == eGL_TEXTURE_CUBE_MAP_ARRAY ||
|
||||
details.curType == eGL_TEXTURE_1D_ARRAY || details.curType == eGL_TEXTURE_2D_ARRAY)
|
||||
d = details.depth;
|
||||
|
||||
// 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).
|
||||
//
|
||||
// AMD also has issues copying cubemaps
|
||||
if((iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips] && (w < 4 || h < 4)) ||
|
||||
(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_cubemaps] &&
|
||||
details.curType == eGL_TEXTURE_CUBE_MAP))
|
||||
GLint packParams[8];
|
||||
GLint unpackParams[8];
|
||||
if(avoidCopySubImage)
|
||||
{
|
||||
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,
|
||||
};
|
||||
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]);
|
||||
|
||||
int count = ARRAY_COUNT(targets);
|
||||
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);
|
||||
|
||||
if(details.curType != eGL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
targets[0] = details.curType;
|
||||
count = 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]);
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
|
||||
// copy over mips
|
||||
for(int i = 0; i < mips; i++)
|
||||
{
|
||||
// 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");
|
||||
int w = RDCMAX(details.width >> i, 1);
|
||||
int h = RDCMAX(details.height >> i, 1);
|
||||
int d = RDCMAX(details.depth >> i, 1);
|
||||
|
||||
if(details.curType == eGL_TEXTURE_CUBE_MAP)
|
||||
d *= 6;
|
||||
else if(details.curType == eGL_TEXTURE_CUBE_MAP_ARRAY ||
|
||||
details.curType == eGL_TEXTURE_1D_ARRAY || details.curType == eGL_TEXTURE_2D_ARRAY)
|
||||
d = details.depth;
|
||||
|
||||
// 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).
|
||||
// AMD also has issues copying cubemaps
|
||||
if((iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_tinymips] && (w < 4 || h < 4)) ||
|
||||
(iscomp && VendorCheck[VendorCheck_AMD_copy_compressed_cubemaps] &&
|
||||
details.curType == eGL_TEXTURE_CUBE_MAP))
|
||||
{
|
||||
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(avoidCopySubImage)
|
||||
{
|
||||
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]);
|
||||
if(avoidCopySubImage)
|
||||
{
|
||||
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.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]);
|
||||
}
|
||||
}
|
||||
|
||||
bool ms = (details.curType == eGL_TEXTURE_2D_MULTISAMPLE ||
|
||||
|
||||
@@ -631,6 +631,7 @@ bool WrappedOpenGL::Serialise_glTextureView(GLuint texture, GLenum target, GLuin
|
||||
|
||||
m_Textures[liveTexId].curType = TextureTarget(Target);
|
||||
m_Textures[liveTexId].internalFormat = InternalFormat;
|
||||
m_Textures[liveTexId].view = true;
|
||||
m_Textures[liveTexId].width = m_Textures[liveOrigId].width;
|
||||
m_Textures[liveTexId].height = m_Textures[liveOrigId].height;
|
||||
m_Textures[liveTexId].depth = m_Textures[liveOrigId].depth;
|
||||
@@ -664,16 +665,26 @@ void WrappedOpenGL::glTextureView(GLuint texture, GLenum target, GLuint origtext
|
||||
|
||||
// illegal to re-type textures
|
||||
record->VerifyDataType(target);
|
||||
|
||||
// mark the underlying resource as dirty to avoid tracking dirty across
|
||||
// aliased resources etc.
|
||||
if(m_State == WRITING_IDLE)
|
||||
GetResourceManager()->MarkDirtyResource(origrecord->GetResourceID());
|
||||
else
|
||||
m_MissingTracks.insert(origrecord->GetResourceID());
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
ResourceId texId = GetResourceManager()->GetID(TextureRes(GetCtx(), texture));
|
||||
ResourceId origId = GetResourceManager()->GetID(TextureRes(GetCtx(), origtexture));
|
||||
ResourceId viewedId = GetResourceManager()->GetID(TextureRes(GetCtx(), origtexture));
|
||||
|
||||
m_Textures[texId].internalFormat = internalformat;
|
||||
m_Textures[texId].width = m_Textures[origId].width;
|
||||
m_Textures[texId].height = m_Textures[origId].height;
|
||||
m_Textures[texId].depth = m_Textures[origId].depth;
|
||||
m_Textures[texId].view = true;
|
||||
m_Textures[texId].dimension = m_Textures[viewedId].dimension;
|
||||
m_Textures[texId].width = m_Textures[viewedId].width;
|
||||
m_Textures[texId].height = m_Textures[viewedId].height;
|
||||
m_Textures[texId].depth = m_Textures[viewedId].depth;
|
||||
m_Textures[texId].curType = TextureTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user