diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index d13e6a043..945776092 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -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) { diff --git a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp index 760a28dc0..fec0f45dd 100644 --- a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp @@ -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