diff --git a/renderdoc/driver/gl/egl_hooks.cpp b/renderdoc/driver/gl/egl_hooks.cpp index b1cacc5f1..b985aa385 100644 --- a/renderdoc/driver/gl/egl_hooks.cpp +++ b/renderdoc/driver/gl/egl_hooks.cpp @@ -223,6 +223,7 @@ HOOK_EXPORT EGLBoolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSu // see gl_emulated.cpp GL.EmulateUnsupportedFunctions(); GL.EmulateRequiredExtensions(); + GL.DriverForEmulation(&eglhook.driver); } GLWindowingData data; diff --git a/renderdoc/driver/gl/gl_dispatch_table.h b/renderdoc/driver/gl/gl_dispatch_table.h index a38ec97bf..b1151982e 100644 --- a/renderdoc/driver/gl/gl_dispatch_table.h +++ b/renderdoc/driver/gl/gl_dispatch_table.h @@ -27,6 +27,8 @@ #include "gl_common.h" +class WrappedOpenGL; + typedef std::function PlatformGetProcAddr; // We need to disable clang-format since this struct is programmatically parsed @@ -42,6 +44,7 @@ struct GLDispatchTable // presence. void EmulateUnsupportedFunctions(); void EmulateRequiredExtensions(); + void DriverForEmulation(WrappedOpenGL *driver); // first we list all the core functions. 1.1 functions are separate under 'dllexport' for // different handling on windows. Extensions come after. diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index eef10ce63..a845f9e1a 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -255,48 +255,6 @@ private: // map with key being mip level, value being stored data typedef std::map> CompressedDataStore; - struct TextureData - { - TextureData() - : curType(eGL_NONE), - dimension(0), - emulated(false), - view(false), - width(0), - height(0), - depth(0), - samples(0), - creationFlags(TextureCategory::NoFlags), - internalFormat(eGL_NONE), - renderbufferReadTex(0) - { - renderbufferFBOs[0] = renderbufferFBOs[1] = 0; - } - GLResource resource; - GLenum curType; - GLint dimension; - bool emulated, view; - GLint width, height, depth, samples; - TextureCategory creationFlags; - GLenum internalFormat; - - // since renderbuffers cannot be read from, we have to create a texture of identical - // size/format, - // and define FBOs for blitting to it - the renderbuffer is attached to the first FBO and the - // texture is - // bound to the second. - GLuint renderbufferReadTex; - GLuint renderbufferFBOs[2]; - - // since compressed textures cannot be read back on GLES we have to store them during the - // uploading - CompressedDataStore compressedData; - - void GetCompressedImageDataGLES(int mip, GLenum target, size_t size, byte *buf); - }; - - std::map m_Textures; - struct ShaderData { ShaderData() : type(eGL_NONE), prog(0), version(0) {} @@ -654,6 +612,50 @@ public: void StartFrameCapture(void *dev, void *wnd); bool EndFrameCapture(void *dev, void *wnd); + struct TextureData + { + TextureData() + : curType(eGL_NONE), + dimension(0), + emulated(false), + view(false), + width(0), + height(0), + depth(0), + samples(0), + creationFlags(TextureCategory::NoFlags), + internalFormat(eGL_NONE), + mipsValid(0), + renderbufferReadTex(0) + { + renderbufferFBOs[0] = renderbufferFBOs[1] = 0; + } + GLResource resource; + GLenum curType; + GLint dimension; + bool emulated, view; + GLint width, height, depth, samples; + TextureCategory creationFlags; + GLenum internalFormat; + GLuint mipsValid; + + // since renderbuffers cannot be read from, we have to create a texture of identical + // size/format, + // and define FBOs for blitting to it - the renderbuffer is attached to the first FBO and the + // texture is + // bound to the second. + GLuint renderbufferReadTex; + GLuint renderbufferFBOs[2]; + + // since compressed textures cannot be read back on GLES we have to store them during the + // uploading + CompressedDataStore compressedData; + + void GetCompressedImageDataGLES(int mip, GLenum target, size_t size, byte *buf); + }; + + std::map m_Textures; + IMPLEMENT_FUNCTION_SERIALISED(void, glBindTexture, GLenum target, GLuint texture); IMPLEMENT_FUNCTION_SERIALISED(void, glBindTextures, GLuint first, GLsizei count, const GLuint *textures); diff --git a/renderdoc/driver/gl/gl_initstate.cpp b/renderdoc/driver/gl/gl_initstate.cpp index 5f52b148b..bd34d4292 100644 --- a/renderdoc/driver/gl/gl_initstate.cpp +++ b/renderdoc/driver/gl/gl_initstate.cpp @@ -586,6 +586,28 @@ void GLResourceManager::CreateTextureImage(GLuint tex, GLenum internalFormat, GL d = RDCMAX(1, d >> 1); } } + + if(IsCaptureMode(m_State)) + { + // register this texture and set up its texture details, so it's available for emulation + // readback. + GLResource res = TextureRes(m_Driver->GetCtx(), tex); + ResourceId id = RegisterResource(res); + + WrappedOpenGL::TextureData &details = m_Driver->m_Textures[id]; + + details.resource = res; + details.curType = textype; + details.dimension = dim; + details.emulated = details.view = false; + details.width = width; + details.height = height; + details.depth = depth; + details.samples = samples; + details.creationFlags = TextureCategory::NoFlags; + details.internalFormat = internalFormat; + details.mipsValid = (1 << mips) - 1; + } } void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, ResourceId origid, diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 5a49e0a68..c1f850b2d 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -123,6 +123,12 @@ bool GLResourceManager::SerialisableResource(ResourceId id, GLResourceRecord *re bool GLResourceManager::ResourceTypeRelease(GLResource res) { + if(HasCurrentResource(res)) + { + MarkCleanResource(res); + UnregisterResource(res); + } + m_Driver->QueueResourceRelease(res); return true; } diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 0ddf8f30c..1f973e8b6 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -3283,6 +3283,8 @@ ReplayStatus CreateReplayDevice(RDCFile *rdc, GLPlatform &platform, IReplayDrive WrappedOpenGL *gldriver = new WrappedOpenGL(platform); gldriver->SetDriverType(rdc->GetDriver()); + GL.DriverForEmulation(gldriver); + RDCLOG("Created %s replay device.", ToStr(rdc->GetDriver()).c_str()); GLReplay *replay = gldriver->GetReplay(); diff --git a/renderdoc/driver/gl/glx_hooks.cpp b/renderdoc/driver/gl/glx_hooks.cpp index e5c8dee86..36d836d6a 100644 --- a/renderdoc/driver/gl/glx_hooks.cpp +++ b/renderdoc/driver/gl/glx_hooks.cpp @@ -291,6 +291,7 @@ HOOK_EXPORT Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext c // see gl_emulated.cpp GL.EmulateUnsupportedFunctions(); GL.EmulateRequiredExtensions(); + GL.DriverForEmulation(&glxhook.driver); } GLWindowingData data; @@ -332,6 +333,7 @@ HOOK_EXPORT Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawab // see gl_emulated.cpp GL.EmulateUnsupportedFunctions(); GL.EmulateRequiredExtensions(); + GL.DriverForEmulation(&glxhook.driver); } GLWindowingData data; diff --git a/renderdoc/driver/gl/wgl_hooks.cpp b/renderdoc/driver/gl/wgl_hooks.cpp index c787ca839..14f7e6df0 100644 --- a/renderdoc/driver/gl/wgl_hooks.cpp +++ b/renderdoc/driver/gl/wgl_hooks.cpp @@ -361,6 +361,7 @@ static BOOL WINAPI wglMakeCurrent_hooked(HDC dc, HGLRC rc) // see gl_emulated.cpp GL.EmulateUnsupportedFunctions(); GL.EmulateRequiredExtensions(); + GL.DriverForEmulation(&wglhook.driver); } GLWindowingData data; diff --git a/renderdoc/driver/gl/wrappers/gl_emulated.cpp b/renderdoc/driver/gl/wrappers/gl_emulated.cpp index 4ce2192fc..9cb2f8ff6 100644 --- a/renderdoc/driver/gl/wrappers/gl_emulated.cpp +++ b/renderdoc/driver/gl/wrappers/gl_emulated.cpp @@ -28,11 +28,13 @@ #include "driver/gl/gl_common.h" #include "driver/gl/gl_dispatch_table.h" +#include "driver/gl/gl_driver.h" #include "driver/gl/gl_resources.h" namespace glEmulate { PFNGLGETINTERNALFORMATIVPROC glGetInternalformativ_real = NULL; +WrappedOpenGL *driver = NULL; typedef GLenum (*BindingLookupFunc)(GLenum target); @@ -1198,6 +1200,16 @@ void APIENTRY _glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLev } else if(!layered) { + GLenum status = GL.glCheckFramebufferStatus(eGL_DRAW_FRAMEBUFFER); + + if(status != eGL_FRAMEBUFFER_COMPLETE) + RDCERR("glCopyImageSubData emulation draw FBO is %s", ToStr(status).c_str()); + + status = GL.glCheckFramebufferStatus(eGL_READ_FRAMEBUFFER); + + if(status != eGL_FRAMEBUFFER_COMPLETE) + RDCERR("glCopyImageSubData emulation read FBO is %s", ToStr(status).c_str()); + SafeBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY, dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST); } @@ -1218,6 +1230,19 @@ void APIENTRY _glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLev GL.glFramebufferTexture2D(eGL_DRAW_FRAMEBUFFER, attach, textargets[dstZ + slice], dstName, dstLevel); + if(slice == 0) + { + GLenum status = GL.glCheckFramebufferStatus(eGL_DRAW_FRAMEBUFFER); + + if(status != eGL_FRAMEBUFFER_COMPLETE) + RDCERR("glCopyImageSubData emulation draw FBO is %s for slice 0", ToStr(status).c_str()); + + status = GL.glCheckFramebufferStatus(eGL_READ_FRAMEBUFFER); + + if(status != eGL_FRAMEBUFFER_COMPLETE) + RDCERR("glCopyImageSubData emulation read FBO is %s for slice 0", ToStr(status).c_str()); + } + SafeBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY, dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST); } @@ -1229,6 +1254,19 @@ void APIENTRY _glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLev GL.glFramebufferTextureLayer(eGL_READ_FRAMEBUFFER, attach, srcName, srcLevel, srcZ + slice); GL.glFramebufferTextureLayer(eGL_DRAW_FRAMEBUFFER, attach, dstName, dstLevel, dstZ + slice); + if(slice == 0) + { + GLenum status = GL.glCheckFramebufferStatus(eGL_DRAW_FRAMEBUFFER); + + if(status != eGL_FRAMEBUFFER_COMPLETE) + RDCERR("glCopyImageSubData emulation draw FBO is %s for slice 0", ToStr(status).c_str()); + + status = GL.glCheckFramebufferStatus(eGL_READ_FRAMEBUFFER); + + if(status != eGL_FRAMEBUFFER_COMPLETE) + RDCERR("glCopyImageSubData emulation read FBO is %s for slice 0", ToStr(status).c_str()); + } + SafeBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY, dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST); } @@ -1348,6 +1386,48 @@ void APIENTRY _glClearBufferData(GLenum target, GLenum internalformat, GLenum fo #pragma region GLES Compatibility +void APIENTRY _glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) +{ + if(driver == NULL) + { + RDCERR("No driver available, can't emulate glGetTexLevelParameteriv"); + return; + } + + GLint boundTexture = 0; + GL.glGetIntegerv(TextureBinding(target), (GLint *)&boundTexture); + + ResourceId id = driver->GetResourceManager()->GetID(TextureRes(driver->GetCtx(), boundTexture)); + + WrappedOpenGL::TextureData &details = driver->m_Textures[id]; + + bool hasmip = (details.mipsValid & (1 << level)) != 0; + + if(details.mipsValid == 0) + RDCWARN("No mips valid! Uninitialised texture?"); + + switch(pname) + { + case eGL_TEXTURE_WIDTH: *params = hasmip ? RDCMAX(1, details.width >> level) : 0; return; + case eGL_TEXTURE_HEIGHT: *params = hasmip ? RDCMAX(1, details.height >> level) : 0; return; + case eGL_TEXTURE_DEPTH: *params = hasmip ? RDCMAX(1, details.depth >> level) : 0; return; + case eGL_TEXTURE_INTERNAL_FORMAT: *params = details.internalFormat; return; + default: + // since this is internal emulation, we only handle the parameters we expect to need + break; + } + + RDCERR("Unhandled parameter %s", ToStr(pname).c_str()); +} + +void APIENTRY _glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params) +{ + // just call and upcast + GLint param = 0; + _glGetTexLevelParameteriv(target, level, pname, ¶m); + *params = (GLfloat)param; +} + void APIENTRY _glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void *pixels) { if((format == eGL_DEPTH_COMPONENT && !HasExt[NV_read_depth]) || @@ -1728,6 +1808,12 @@ void GLDispatchTable::EmulateRequiredExtensions() EMULATE_FUNC(glGetBufferSubData); EMULATE_FUNC(glGetTexImage); + if(GLCoreVersion < 31) + { + EMULATE_FUNC(glGetTexLevelParameteriv); + EMULATE_FUNC(glGetTexLevelParameterfv); + } + if(GLCoreVersion < 32) { EMULATE_FUNC(glDrawElementsBaseVertex); @@ -1838,3 +1924,8 @@ void GLDispatchTable::EmulateRequiredExtensions() EMULATE_FUNC(glVertexArrayVertexBindingDivisorEXT); } } + +void GLDispatchTable::DriverForEmulation(WrappedOpenGL *driver) +{ + glEmulate::driver = driver; +} diff --git a/renderdoc/driver/gl/wrappers/gl_framebuffer_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_framebuffer_funcs.cpp index c98b2bff6..d93f4ec2f 100644 --- a/renderdoc/driver/gl/wrappers/gl_framebuffer_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_framebuffer_funcs.cpp @@ -2168,6 +2168,7 @@ bool WrappedOpenGL::Serialise_glNamedRenderbufferStorageEXT(SerialiserType &ser, texDetails.samples = 1; texDetails.curType = eGL_RENDERBUFFER; texDetails.internalFormat = internalformat; + texDetails.mipsValid = 1; GL.glNamedRenderbufferStorageEXT(renderbuffer.name, internalformat, width, height); @@ -2236,6 +2237,7 @@ void WrappedOpenGL::glNamedRenderbufferStorageEXT(GLuint renderbuffer, GLenum in m_Textures[rb].curType = eGL_RENDERBUFFER; m_Textures[rb].dimension = 2; m_Textures[rb].internalFormat = internalformat; + m_Textures[rb].mipsValid = 1; } } @@ -2270,6 +2272,7 @@ void WrappedOpenGL::glRenderbufferStorage(GLenum target, GLenum internalformat, m_Textures[rb].curType = eGL_RENDERBUFFER; m_Textures[rb].dimension = 2; m_Textures[rb].internalFormat = internalformat; + m_Textures[rb].mipsValid = 1; } } @@ -2299,6 +2302,7 @@ bool WrappedOpenGL::Serialise_glNamedRenderbufferStorageMultisampleEXT(Serialise texDetails.samples = samples; texDetails.curType = eGL_RENDERBUFFER; texDetails.internalFormat = internalformat; + texDetails.mipsValid = 1; GL.glNamedRenderbufferStorageMultisampleEXT(renderbuffer.name, samples, internalformat, width, height); @@ -2367,6 +2371,7 @@ void WrappedOpenGL::glNamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer m_Textures[rb].curType = eGL_RENDERBUFFER; m_Textures[rb].dimension = 2; m_Textures[rb].internalFormat = internalformat; + m_Textures[rb].mipsValid = 1; } } @@ -2403,6 +2408,7 @@ void WrappedOpenGL::glRenderbufferStorageMultisample(GLenum target, GLsizei samp m_Textures[rb].curType = eGL_RENDERBUFFER; m_Textures[rb].dimension = 2; m_Textures[rb].internalFormat = internalformat; + m_Textures[rb].mipsValid = 1; } } diff --git a/renderdoc/driver/gl/wrappers/gl_interop_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_interop_funcs.cpp index 7d4d54730..5fb2b8be1 100644 --- a/renderdoc/driver/gl/wrappers/gl_interop_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_interop_funcs.cpp @@ -143,6 +143,7 @@ HANDLE WrappedOpenGL::wglDXRegisterObjectNV(HANDLE hDevice, void *dxObject, GLui m_Textures[texId].dimension = 3; m_Textures[texId].internalFormat = MakeGLFormat(fmt); + m_Textures[texId].mipsValid = (1 << mips) - 1; } return wrapped; @@ -335,6 +336,7 @@ bool WrappedOpenGL::Serialise_wglDXRegisterObjectNV(SerialiserType &ser, GLResou m_Textures[liveId].dimension = 3; m_Textures[liveId].internalFormat = internalFormat; + m_Textures[liveId].mipsValid = (1 << mips) - 1; } AddResourceInitChunk(Resource); diff --git a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp index 7c3a5910f..ddf11f0c1 100644 --- a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp @@ -652,6 +652,7 @@ bool WrappedOpenGL::Serialise_glTextureView(SerialiserType &ser, GLuint textureH m_Textures[liveTexId].width = m_Textures[liveOrigId].width; m_Textures[liveTexId].height = m_Textures[liveOrigId].height; m_Textures[liveTexId].depth = m_Textures[liveOrigId].depth; + m_Textures[liveTexId].mipsValid = (1 << numlevels) - 1; AddResourceInitChunk(texture); DerivedResource(origtexture, GetResourceManager()->GetOriginalID(liveTexId)); @@ -711,6 +712,7 @@ void WrappedOpenGL::glTextureView(GLuint texture, GLenum target, GLuint origtext m_Textures[texId].height = m_Textures[viewedId].height; m_Textures[texId].depth = m_Textures[viewedId].depth; m_Textures[texId].curType = TextureTarget(target); + m_Textures[texId].mipsValid = (1 << numlevels) - 1; } } @@ -2073,9 +2075,11 @@ bool WrappedOpenGL::Serialise_glTextureImage1DEXT(SerialiserType &ser, GLuint te bool emulated = EmulateLuminanceFormat(texture.name, target, intFmt, format); internalformat = intFmt; + ResourceId liveId = GetResourceManager()->GetID(texture); + m_Textures[liveId].mipsValid |= 1 << level; + if(level == 0) // assume level 0 will always get a glTexImage call { - ResourceId liveId = GetResourceManager()->GetID(texture); m_Textures[liveId].width = width; m_Textures[liveId].height = 1; m_Textures[liveId].depth = 1; @@ -2167,6 +2171,8 @@ void WrappedOpenGL::Common_glTextureImage1DEXT(ResourceId texId, GLenum target, } } + m_Textures[texId].mipsValid |= 1 << level; + if(level == 0) { m_Textures[texId].width = width; @@ -2282,9 +2288,11 @@ bool WrappedOpenGL::Serialise_glTextureImage2DEXT(SerialiserType &ser, GLuint te bool emulated = EmulateLuminanceFormat(texture.name, target, intFmt, format); internalformat = intFmt; + ResourceId liveId = GetResourceManager()->GetID(texture); + m_Textures[liveId].mipsValid |= 1 << level; + if(level == 0) // assume level 0 will always get a glTexImage call { - ResourceId liveId = GetResourceManager()->GetID(texture); m_Textures[liveId].width = width; m_Textures[liveId].height = height; m_Textures[liveId].depth = 1; @@ -2400,6 +2408,8 @@ void WrappedOpenGL::Common_glTextureImage2DEXT(ResourceId texId, GLenum target, } } + m_Textures[texId].mipsValid |= 1 << level; + if(level == 0) { m_Textures[texId].width = width; @@ -2519,9 +2529,11 @@ bool WrappedOpenGL::Serialise_glTextureImage3DEXT(SerialiserType &ser, GLuint te bool emulated = EmulateLuminanceFormat(texture.name, target, intFmt, format); internalformat = intFmt; + ResourceId liveId = GetResourceManager()->GetID(texture); + m_Textures[liveId].mipsValid |= 1 << level; + if(level == 0) // assume level 0 will always get a glTexImage call { - ResourceId liveId = GetResourceManager()->GetID(texture); m_Textures[liveId].width = width; m_Textures[liveId].height = height; m_Textures[liveId].depth = depth; @@ -2617,6 +2629,8 @@ void WrappedOpenGL::Common_glTextureImage3DEXT(ResourceId texId, GLenum target, } } + m_Textures[texId].mipsValid |= 1 << level; + if(level == 0) { m_Textures[texId].width = width; @@ -2741,9 +2755,11 @@ bool WrappedOpenGL::Serialise_glCompressedTextureImage1DEXT(SerialiserType &ser, databuf = &m_ScratchBuf[0]; } + ResourceId liveId = GetResourceManager()->GetID(texture); + m_Textures[liveId].mipsValid |= 1 << level; + if(level == 0) // assume level 0 will always get a glTexImage call { - ResourceId liveId = GetResourceManager()->GetID(texture); m_Textures[liveId].width = width; m_Textures[liveId].height = 1; m_Textures[liveId].depth = 1; @@ -2836,6 +2852,8 @@ void WrappedOpenGL::Common_glCompressedTextureImage1DEXT(ResourceId texId, GLenu } } + m_Textures[texId].mipsValid |= 1 << level; + if(level == 0) { m_Textures[texId].width = width; @@ -3061,9 +3079,11 @@ bool WrappedOpenGL::Serialise_glCompressedTextureImage2DEXT(SerialiserType &ser, databuf = &m_ScratchBuf[0]; } + ResourceId liveId = GetResourceManager()->GetID(texture); + m_Textures[liveId].mipsValid |= 1 << level; + if(level == 0) // assume level 0 will always get a glTexImage call { - ResourceId liveId = GetResourceManager()->GetID(texture); m_Textures[liveId].width = width; m_Textures[liveId].height = height; m_Textures[liveId].depth = 1; @@ -3182,6 +3202,8 @@ void WrappedOpenGL::Common_glCompressedTextureImage2DEXT(ResourceId texId, GLenu } } + m_Textures[texId].mipsValid |= 1 << level; + if(level == 0) { m_Textures[texId].width = width; @@ -3314,9 +3336,11 @@ bool WrappedOpenGL::Serialise_glCompressedTextureImage3DEXT(SerialiserType &ser, databuf = &m_ScratchBuf[0]; } + ResourceId liveId = GetResourceManager()->GetID(texture); + m_Textures[liveId].mipsValid |= 1 << level; + if(level == 0) // assume level 0 will always get a glTexImage call { - ResourceId liveId = GetResourceManager()->GetID(texture); m_Textures[liveId].width = width; m_Textures[liveId].height = height; m_Textures[liveId].depth = depth; @@ -3415,6 +3439,8 @@ void WrappedOpenGL::Common_glCompressedTextureImage3DEXT(ResourceId texId, GLenu } } + m_Textures[texId].mipsValid |= 1 << level; + if(level == 0) { m_Textures[texId].width = width; @@ -3516,9 +3542,11 @@ bool WrappedOpenGL::Serialise_glCopyTextureImage1DEXT(SerialiserType &ser, GLuin if(IsReplayingAndReading()) { + ResourceId liveId = GetResourceManager()->GetID(texture); + m_Textures[liveId].mipsValid |= 1 << level; + if(level == 0) // assume level 0 will always get a glTexImage call { - ResourceId liveId = GetResourceManager()->GetID(texture); m_Textures[liveId].width = width; m_Textures[liveId].height = 1; m_Textures[liveId].depth = 1; @@ -3586,10 +3614,11 @@ void WrappedOpenGL::Common_glCopyTextureImage1DEXT(GLResourceRecord *record, GLe GetResourceManager()->MarkResourceFrameReferenced(record->GetResourceID(), eFrameRef_Read); } + ResourceId texId = record->GetResourceID(); + m_Textures[texId].mipsValid |= 1 << level; + if(level == 0) { - ResourceId texId = record->GetResourceID(); - m_Textures[texId].width = width; m_Textures[texId].height = 1; m_Textures[texId].depth = 1; @@ -3665,9 +3694,11 @@ bool WrappedOpenGL::Serialise_glCopyTextureImage2DEXT(SerialiserType &ser, GLuin if(IsReplayingAndReading()) { + ResourceId liveId = GetResourceManager()->GetID(texture); + m_Textures[liveId].mipsValid |= 1 << level; + if(level == 0) // assume level 0 will always get a glTexImage call { - ResourceId liveId = GetResourceManager()->GetID(texture); m_Textures[liveId].width = width; m_Textures[liveId].height = height; m_Textures[liveId].depth = 1; @@ -3736,10 +3767,11 @@ void WrappedOpenGL::Common_glCopyTextureImage2DEXT(GLResourceRecord *record, GLe GetResourceManager()->MarkResourceFrameReferenced(record->GetResourceID(), eFrameRef_Read); } + ResourceId texId = record->GetResourceID(); + m_Textures[texId].mipsValid |= 1 << level; + if(level == 0) { - ResourceId texId = record->GetResourceID(); - m_Textures[texId].width = width; m_Textures[texId].height = height; m_Textures[texId].depth = 1; @@ -3827,6 +3859,7 @@ bool WrappedOpenGL::Serialise_glTextureStorage1DEXT(SerialiserType &ser, GLuint m_Textures[liveId].dimension = 1; m_Textures[liveId].internalFormat = internalformat; m_Textures[liveId].emulated = emulated; + m_Textures[liveId].mipsValid = (1 << levels) - 1; if(target != eGL_NONE) GL.glTextureStorage1DEXT(texture.name, target, levels, internalformat, width); @@ -3876,6 +3909,7 @@ void WrappedOpenGL::Common_glTextureStorage1DEXT(ResourceId texId, GLenum target TextureTarget(GetResourceManager()->GetResourceRecord(texId)->datatype); m_Textures[texId].dimension = 1; m_Textures[texId].internalFormat = internalformat; + m_Textures[texId].mipsValid = (1 << levels) - 1; } } @@ -3952,6 +3986,7 @@ bool WrappedOpenGL::Serialise_glTextureStorage2DEXT(SerialiserType &ser, GLuint m_Textures[liveId].dimension = 2; m_Textures[liveId].internalFormat = internalformat; m_Textures[liveId].emulated = emulated; + m_Textures[liveId].mipsValid = (1 << levels) - 1; if(target != eGL_NONE) GL.glTextureStorage2DEXT(texture.name, target, levels, internalformat, width, height); @@ -4001,6 +4036,7 @@ void WrappedOpenGL::Common_glTextureStorage2DEXT(ResourceId texId, GLenum target TextureTarget(GetResourceManager()->GetResourceRecord(texId)->datatype); m_Textures[texId].dimension = 2; m_Textures[texId].internalFormat = internalformat; + m_Textures[texId].mipsValid = (1 << levels) - 1; } } @@ -4081,6 +4117,7 @@ bool WrappedOpenGL::Serialise_glTextureStorage3DEXT(SerialiserType &ser, GLuint m_Textures[liveId].dimension = 3; m_Textures[liveId].internalFormat = internalformat; m_Textures[liveId].emulated = emulated; + m_Textures[liveId].mipsValid = (1 << levels) - 1; if(target != eGL_NONE) GL.glTextureStorage3DEXT(texture.name, target, levels, internalformat, width, height, depth); @@ -4131,6 +4168,7 @@ void WrappedOpenGL::Common_glTextureStorage3DEXT(ResourceId texId, GLenum target TextureTarget(GetResourceManager()->GetResourceRecord(texId)->datatype); m_Textures[texId].dimension = 3; m_Textures[texId].internalFormat = internalformat; + m_Textures[texId].mipsValid = (1 << levels) - 1; } } @@ -4214,6 +4252,7 @@ bool WrappedOpenGL::Serialise_glTextureStorage2DMultisampleEXT(SerialiserType &s m_Textures[liveId].dimension = 2; m_Textures[liveId].internalFormat = internalformat; m_Textures[liveId].emulated = emulated; + m_Textures[liveId].mipsValid = 1; if(target != eGL_NONE) GL.glTextureStorage2DMultisampleEXT(texture.name, target, samples, internalformat, width, @@ -4268,6 +4307,7 @@ void WrappedOpenGL::Common_glTextureStorage2DMultisampleEXT(ResourceId texId, GL TextureTarget(GetResourceManager()->GetResourceRecord(texId)->datatype); m_Textures[texId].dimension = 2; m_Textures[texId].internalFormat = internalformat; + m_Textures[texId].mipsValid = 1; } } @@ -4385,6 +4425,7 @@ bool WrappedOpenGL::Serialise_glTextureStorage3DMultisampleEXT(SerialiserType &s m_Textures[liveId].dimension = 2; m_Textures[liveId].internalFormat = internalformat; m_Textures[liveId].emulated = emulated; + m_Textures[liveId].mipsValid = 1; if(target != eGL_NONE) GL.glTextureStorage3DMultisampleEXT(texture.name, target, samples, internalformat, width, @@ -4441,6 +4482,7 @@ void WrappedOpenGL::Common_glTextureStorage3DMultisampleEXT(ResourceId texId, GL TextureTarget(GetResourceManager()->GetResourceRecord(texId)->datatype); m_Textures[texId].dimension = 3; m_Textures[texId].internalFormat = internalformat; + m_Textures[texId].mipsValid = 1; } } @@ -5839,6 +5881,7 @@ bool WrappedOpenGL::Serialise_glTextureBufferRangeEXT(SerialiserType &ser, GLuin if(target != eGL_NONE) m_Textures[liveId].curType = TextureTarget(target); m_Textures[liveId].internalFormat = internalformat; + m_Textures[liveId].mipsValid = 1; } if(target != eGL_NONE) @@ -5939,6 +5982,7 @@ void WrappedOpenGL::Common_glTextureBufferRangeEXT(ResourceId texId, GLenum targ TextureTarget(GetResourceManager()->GetResourceRecord(texId)->datatype); m_Textures[texId].dimension = 1; m_Textures[texId].internalFormat = internalformat; + m_Textures[texId].mipsValid = 1; } } @@ -6015,6 +6059,7 @@ bool WrappedOpenGL::Serialise_glTextureBufferEXT(SerialiserType &ser, GLuint tex if(target != eGL_NONE) m_Textures[liveId].curType = TextureTarget(target); m_Textures[liveId].internalFormat = internalformat; + m_Textures[liveId].mipsValid = 1; } if(target != eGL_NONE) @@ -6123,6 +6168,7 @@ void WrappedOpenGL::Common_glTextureBufferEXT(ResourceId texId, GLenum target, TextureTarget(GetResourceManager()->GetResourceRecord(texId)->datatype); m_Textures[texId].dimension = 1; m_Textures[texId].internalFormat = internalformat; + m_Textures[texId].mipsValid = 1; } }