Handle repeated re-specifying of buffer textures by marking dirty

* Also added handling for dirty buffer textures - there are no contents to
  copy, those are handled with the buffer, so instead we just grab the few
  parameters that are valid to re-specify the buffer texture.
This commit is contained in:
baldurk
2014-12-26 12:25:41 +00:00
parent aec7af04e4
commit 4647eee9f2
2 changed files with 502 additions and 353 deletions
+396 -353
View File
@@ -118,6 +118,9 @@ struct TextureStateInitialData
GLenum wrap[3];
float border[4];
float lodBias;
ResourceId texBuffer;
uint32_t texBufOffs;
uint32_t texBufSize;
};
template<>
@@ -139,6 +142,9 @@ void Serialiser::Serialise(const char *name, TextureStateInitialData &el)
Serialise<3>("wrap", el.wrap);
Serialise<4>("border", el.border);
Serialise("lodBias", el.lodBias);
Serialise("texBuffer", el.texBuffer);
Serialise("texBufOffs", el.texBufOffs);
Serialise("texBufSize", el.texBufSize);
}
bool GLResourceManager::SerialisableResource(ResourceId id, GLResourceRecord *record)
@@ -186,57 +192,10 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
WrappedOpenGL::TextureData &details = m_GL->m_Textures[Id];
GLenum binding = TextureBinding(details.curType);
GLuint tex = 0;
{
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;
GLint isComp = 0;
GLenum queryType = details.curType;
if(queryType == eGL_TEXTURE_CUBE_MAP)
queryType = eGL_TEXTURE_CUBE_MAP_POSITIVE_X;
gl.glGetTextureLevelParameterivEXT(res.name, queryType, 0, eGL_TEXTURE_COMPRESSED, &isComp);
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);
}
TextureStateInitialData *state = (TextureStateInitialData *)Serialiser::AllocAlignedBuffer(sizeof(TextureStateInitialData));
RDCEraseMem(state, sizeof(TextureStateInitialData));
if(details.curType != eGL_TEXTURE_BUFFER)
{
bool ms = (details.curType == eGL_TEXTURE_2D_MULTISAMPLE || details.curType == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY);
@@ -268,161 +227,222 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
gl.glGetTextureParameterfvEXT(res.name, details.curType, eGL_TEXTURE_BORDER_COLOR, &state->border[0]);
gl.glGetTextureParameterfvEXT(res.name, details.curType, eGL_TEXTURE_LOD_BIAS, &state->lodBias);
}
}
// 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);
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]);
GLuint tex = 0;
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++)
{
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).
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,
};
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;
GLint isComp = 0;
GLenum queryType = details.curType;
if(queryType == eGL_TEXTURE_CUBE_MAP)
queryType = eGL_TEXTURE_CUBE_MAP_POSITIVE_X;
gl.glGetTextureLevelParameterivEXT(res.name, queryType, 0, eGL_TEXTURE_COMPRESSED, &isComp);
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);
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++)
{
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).
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]);
}
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.glTextureParameterivEXT(res.name, details.curType, eGL_TEXTURE_MAX_LEVEL, (GLint *)&state->maxLevel);
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);
SetInitialContents(Id, InitialContentData(TextureRes(res.Context, tex), 0, (byte *)state));
SetInitialContents(Id, InitialContentData(TextureRes(res.Context, tex), 0, (byte *)state));
}
else
{
// record texbuffer only state
GLuint bufName = 0;
gl.glGetTextureLevelParameterivEXT(res.name, details.curType, 0, eGL_TEXTURE_BUFFER_DATA_STORE_BINDING, (GLint *)&bufName);
state->texBuffer = GetID(BufferRes(res.Context, bufName));
gl.glGetTextureLevelParameterivEXT(res.name, details.curType, 0, eGL_TEXTURE_BUFFER_OFFSET, (GLint *)&state->texBufOffs);
gl.glGetTextureLevelParameterivEXT(res.name, details.curType, 0, eGL_TEXTURE_BUFFER_SIZE, (GLint *)&state->texBufSize);
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, (byte *)state));
}
}
else if(res.Namespace == eResFramebuffer)
{
@@ -502,7 +522,7 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
VAOInitialData *data = (VAOInitialData *)Serialiser::AllocAlignedBuffer(sizeof(VAOInitialData));
RDCEraseMem(data, sizeof(VAOInitialData));
for(GLuint i=0; i < 16; i++)
{
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *)&data->VertexAttribs[i].enabled);
@@ -682,7 +702,11 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
SERIALISE_ELEMENT(bool, isCompressed, isComp != 0);
if(isCompressed)
if(details.curType == eGL_TEXTURE_BUFFER)
{
// no contents to copy for texture buffer (it's copied under the buffer)
}
else if(isCompressed)
{
for(int i=0; i < mips; i++)
{
@@ -842,6 +866,7 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
GLuint tex = 0;
if(textype != eGL_TEXTURE_BUFFER)
{
GLuint prevtex = 0;
gl.glGetIntegerv(TextureBinding(textype), (GLint *)&prevtex);
@@ -853,7 +878,11 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
}
// create texture of identical format/size to store initial contents
if(textype == eGL_TEXTURE_2D_MULTISAMPLE)
if(textype == eGL_TEXTURE_BUFFER)
{
// no 'contents' texture to create
}
else if(textype == eGL_TEXTURE_2D_MULTISAMPLE)
{
gl.glTextureStorage2DMultisampleEXT(tex, textype, samples, internalformat, width, height, GL_TRUE);
mips = 1;
@@ -876,7 +905,11 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
gl.glTextureStorage3DEXT(tex, textype, mips, internalformat, width, height, depth);
}
if(isCompressed)
if(textype == eGL_TEXTURE_BUFFER)
{
// no contents to serialise
}
else if(isCompressed)
{
for(int i=0; i < mips; i++)
{
@@ -979,7 +1012,10 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
}
}
SetInitialContents(Id, InitialContentData(TextureRes(m_GL->GetCtx(), tex), 0, (byte *)state));
if(textype != eGL_TEXTURE_BUFFER)
SetInitialContents(Id, InitialContentData(TextureRes(m_GL->GetCtx(), tex), 0, (byte *)state));
else
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, (byte *)state));
gl.glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, pub);
@@ -1042,7 +1078,7 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
VAOInitialData *initialdata = (VAOInitialData *)GetInitialContents(Id).blob;
memcpy(&data, initialdata, sizeof(data));
}
for(GLuint i=0; i < 16; i++)
{
m_pSerialiser->Serialise("VertexAttrib[]", data.VertexAttribs[i]);
@@ -1091,169 +1127,170 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i
ResourceId Id = GetID(live);
WrappedOpenGL::TextureData &details = m_GL->m_Textures[Id];
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);
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++)
{
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).
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
{
// 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;
if(details.curType != eGL_TEXTURE_BUFFER)
{
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);
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++)
{
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).
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
{
// 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]);
}
bool ms = (details.curType == eGL_TEXTURE_2D_MULTISAMPLE || details.curType == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY);
if(state->depthMode == eGL_DEPTH_COMPONENT || state->depthMode == eGL_STENCIL_INDEX)
gl.glTextureParameterivEXT(live.name, details.curType, eGL_DEPTH_STENCIL_TEXTURE_MODE, (GLint *)&state->depthMode);
if(details.curType == eGL_TEXTURE_CUBE_MAP || details.curType == eGL_TEXTURE_CUBE_MAP_ARRAY)
gl.glTextureParameterivEXT(live.name, details.curType, eGL_TEXTURE_CUBE_MAP_SEAMLESS, (GLint *)&state->seamless);
@@ -1277,6 +1314,12 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i
gl.glTextureParameterfvEXT(live.name, details.curType, eGL_TEXTURE_LOD_BIAS, &state->lodBias);
}
}
else
{
// restore texbuffer only state
gl.glTextureBufferRangeEXT(live.name, eGL_TEXTURE_BUFFER, details.internalFormat,
GetLiveResource(state->texBuffer).name, state->texBufOffs, state->texBufSize);
}
}
else if(live.Namespace == eResProgram)
{
@@ -5171,6 +5171,13 @@ void WrappedOpenGL::glTextureBufferRangeEXT(GLuint texture, GLenum target, GLenu
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), texture));
RDCASSERT(record);
if(record->datatype == TextureBinding(target) && m_Textures[record->GetResourceID()].internalFormat == internalformat && m_State == WRITING_IDLE)
{
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(BufferRes(GetCtx(), buffer));
return;
}
SCOPED_SERIALISE_CONTEXT(TEXBUFFER_RANGE);
Serialise_glTextureBufferRangeEXT(texture, target, internalformat, buffer, offset, size);
@@ -5184,6 +5191,19 @@ void WrappedOpenGL::glTextureBufferRangeEXT(GLuint texture, GLenum target, GLenu
record->AddParent(GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer)));
}
}
{
GLuint texture = 0;
m_Real.glGetIntegerv(TextureBinding(target), (GLint *)&texture);
ResourceId texId = GetResourceManager()->GetID(TextureRes(GetCtx(), texture));
m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1));
m_Textures[texId].height = 1;
m_Textures[texId].depth = 1;
m_Textures[texId].curType = TextureTarget(target);
m_Textures[texId].dimension = 1;
m_Textures[texId].internalFormat = internalformat;
}
}
void WrappedOpenGL::glTexBufferRange(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
@@ -5194,6 +5214,13 @@ void WrappedOpenGL::glTexBufferRange(GLenum target, GLenum internalformat, GLuin
{
GLResourceRecord *record = GetCtxData().GetActiveTexRecord();
RDCASSERT(record);
if(record->datatype == TextureBinding(target) && m_Textures[record->GetResourceID()].internalFormat == internalformat && m_State == WRITING_IDLE)
{
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(BufferRes(GetCtx(), buffer));
return;
}
SCOPED_SERIALISE_CONTEXT(TEXBUFFER_RANGE);
Serialise_glTextureBufferRangeEXT(record->Resource.name,
@@ -5209,6 +5236,19 @@ void WrappedOpenGL::glTexBufferRange(GLenum target, GLenum internalformat, GLuin
record->AddParent(GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer)));
}
}
{
GLuint texture = 0;
m_Real.glGetIntegerv(TextureBinding(target), (GLint *)&texture);
ResourceId texId = GetResourceManager()->GetID(TextureRes(GetCtx(), texture));
m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1));
m_Textures[texId].height = 1;
m_Textures[texId].depth = 1;
m_Textures[texId].curType = TextureTarget(target);
m_Textures[texId].dimension = 1;
m_Textures[texId].internalFormat = internalformat;
}
}
bool WrappedOpenGL::Serialise_glTextureBufferEXT(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer)
@@ -5250,6 +5290,13 @@ void WrappedOpenGL::glTextureBufferEXT(GLuint texture, GLenum target, GLenum int
{
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), texture));
RDCASSERT(record);
if(record->datatype == TextureBinding(target) && m_Textures[record->GetResourceID()].internalFormat == internalformat && m_State == WRITING_IDLE)
{
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(BufferRes(GetCtx(), buffer));
return;
}
SCOPED_SERIALISE_CONTEXT(TEXBUFFER);
Serialise_glTextureBufferEXT(texture, target, internalformat, buffer);
@@ -5266,6 +5313,21 @@ void WrappedOpenGL::glTextureBufferEXT(GLuint texture, GLenum target, GLenum int
record->AddParent(GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer)));
}
}
{
GLuint texture = 0;
m_Real.glGetIntegerv(TextureBinding(target), (GLint *)&texture);
ResourceId texId = GetResourceManager()->GetID(TextureRes(GetCtx(), texture));
uint32_t size = 1;
m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, (GLint *)&size);
m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1));
m_Textures[texId].height = 1;
m_Textures[texId].depth = 1;
m_Textures[texId].curType = TextureTarget(target);
m_Textures[texId].dimension = 1;
m_Textures[texId].internalFormat = internalformat;
}
}
void WrappedOpenGL::glTexBuffer(GLenum target, GLenum internalformat, GLuint buffer)
@@ -5276,6 +5338,13 @@ void WrappedOpenGL::glTexBuffer(GLenum target, GLenum internalformat, GLuint buf
{
GLResourceRecord *record = GetCtxData().GetActiveTexRecord();
RDCASSERT(record);
if(record->datatype == TextureBinding(target) && m_Textures[record->GetResourceID()].internalFormat == internalformat && m_State == WRITING_IDLE)
{
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(BufferRes(GetCtx(), buffer));
return;
}
SCOPED_SERIALISE_CONTEXT(TEXBUFFER);
Serialise_glTextureBufferEXT(record->Resource.name,
@@ -5293,6 +5362,21 @@ void WrappedOpenGL::glTexBuffer(GLenum target, GLenum internalformat, GLuint buf
record->AddParent(GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer)));
}
}
{
GLuint texture = 0;
m_Real.glGetIntegerv(TextureBinding(target), (GLint *)&texture);
ResourceId texId = GetResourceManager()->GetID(TextureRes(GetCtx(), texture));
uint32_t size = 1;
m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, (GLint *)&size);
m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1));
m_Textures[texId].height = 1;
m_Textures[texId].depth = 1;
m_Textures[texId].curType = TextureTarget(target);
m_Textures[texId].dimension = 1;
m_Textures[texId].internalFormat = internalformat;
}
}
void WrappedOpenGL::glMultiTexBufferEXT(GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer)
@@ -5303,6 +5387,13 @@ void WrappedOpenGL::glMultiTexBufferEXT(GLenum texunit, GLenum target, GLenum in
{
GLResourceRecord *record = GetCtxData().m_TextureRecord[texunit-eGL_TEXTURE0];
RDCASSERT(record);
if(record->datatype == TextureBinding(target) && m_Textures[record->GetResourceID()].internalFormat == internalformat && m_State == WRITING_IDLE)
{
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(BufferRes(GetCtx(), buffer));
return;
}
SCOPED_SERIALISE_CONTEXT(TEXBUFFER);
Serialise_glTextureBufferEXT(record->Resource.name,
@@ -5320,6 +5411,21 @@ void WrappedOpenGL::glMultiTexBufferEXT(GLenum texunit, GLenum target, GLenum in
record->AddParent(GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer)));
}
}
{
GLuint texture = 0;
m_Real.glGetIntegerv(TextureBinding(target), (GLint *)&texture);
ResourceId texId = GetResourceManager()->GetID(TextureRes(GetCtx(), texture));
uint32_t size = 1;
m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, (GLint *)&size);
m_Textures[texId].width = uint32_t(size)/uint32_t(GetByteSize(1, 1, 1, GetBaseFormat(internalformat), GetDataType(internalformat), 1));
m_Textures[texId].height = 1;
m_Textures[texId].depth = 1;
m_Textures[texId].curType = TextureTarget(target);
m_Textures[texId].dimension = 1;
m_Textures[texId].internalFormat = internalformat;
}
}
#pragma endregion