From 652f3529a32fa8fa774cd6ece106dde257d0301b Mon Sep 17 00:00:00 2001 From: baldurk Date: Sun, 14 Dec 2014 10:32:57 +0000 Subject: [PATCH] Track if a context is core or not, re-check vendor checks on core * When a compatibility context is created (via the old CreateContext, or via an appropriate CreateContextAttribs call), we can still do the vendor checks but we want to make sure we perform them again if we ever create a core profile context. Note that actually *using* a compatibility context isn't supported at the moment, but this won't explicitly break that. --- renderdoc/driver/gl/gl_common.cpp | 1 + renderdoc/driver/gl/gl_common.h | 1 + renderdoc/driver/gl/gl_driver.cpp | 102 ++++++++++++------------ renderdoc/driver/gl/gl_driver.h | 4 +- renderdoc/driver/gl/gl_replay_linux.cpp | 8 +- renderdoc/driver/gl/gl_replay_win32.cpp | 8 +- renderdoc/hooks/gl_linux_hooks.cpp | 20 ++++- renderdoc/hooks/gl_win32_hooks.cpp | 13 ++- 8 files changed, 98 insertions(+), 59 deletions(-) diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index b5565929c..46bda1f4e 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -47,6 +47,7 @@ bool ExtensionSupported[ExtensionSupported_Count]; bool VendorCheck[VendorCheck_Count]; int GLCoreVersion = 0; +bool GLIsCore = false; // simple wrapper for OS functions to make/delete a context GLWindowingData MakeContext(GLWindowingData share); diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 93d3e02b1..ffbabb786 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -90,6 +90,7 @@ GLenum MakeGLFormat(WrappedOpenGL &gl, GLenum target, ResourceFormat fmt); GLuint GetBoundVertexBuffer(const GLHookSet &gl, GLuint idx); extern int GLCoreVersion; +extern bool GLIsCore; // extensions we know we want to check for are precached, indexd by this enum enum ExtensionCheckEnum diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 4a8f0fec6..be73d2217 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -671,29 +671,32 @@ void *WrappedOpenGL::SwitchToContext(void *ctx) void WrappedOpenGL::DeleteContext(void *contextHandle) { - ContextData &font = m_ContextData[contextHandle]; + ContextData &ctxdata = m_ContextData[contextHandle]; - if(font.built && font.ready) + if(ctxdata.built && ctxdata.ready) { - if(font.Program) - m_Real.glDeleteProgram(font.Program); - if(font.GeneralUBO) - m_Real.glDeleteBuffers(1, &font.GeneralUBO); - if(font.GlyphUBO) - m_Real.glDeleteBuffers(1, &font.GlyphUBO); - if(font.StringUBO) - m_Real.glDeleteBuffers(1, &font.StringUBO); - if(font.GlyphTexture) - m_Real.glDeleteTextures(1, &font.GlyphTexture); + if(ctxdata.Program) + m_Real.glDeleteProgram(ctxdata.Program); + if(ctxdata.GeneralUBO) + m_Real.glDeleteBuffers(1, &ctxdata.GeneralUBO); + if(ctxdata.GlyphUBO) + m_Real.glDeleteBuffers(1, &ctxdata.GlyphUBO); + if(ctxdata.StringUBO) + m_Real.glDeleteBuffers(1, &ctxdata.StringUBO); + if(ctxdata.GlyphTexture) + m_Real.glDeleteTextures(1, &ctxdata.GlyphTexture); } m_ContextData.erase(contextHandle); } -void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams) +void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams, bool core) { // TODO: support multiple GL contexts more explicitly m_InitParams = initParams; + + ContextData &ctxdata = m_ContextData[winData.ctx]; + ctxdata.isCore = core; } void WrappedOpenGL::ActivateContext(GLWindowingData winData) @@ -712,11 +715,11 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) m_ContextRecord->AddChunk(scope.Get()); } - ContextData &font = m_ContextData[winData.ctx]; + ContextData &ctxdata = m_ContextData[winData.ctx]; - if(!font.built) + if(!ctxdata.built) { - font.built = true; + ctxdata.built = true; const GLHookSet &gl = m_Real; @@ -734,9 +737,10 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) int ver = mj*10 + mn; - if(ver > GLCoreVersion) + if(ver > GLCoreVersion || (!GLIsCore && ctxdata.isCore)) { GLCoreVersion = ver; + GLIsCore = ctxdata.isCore; DoVendorChecks(gl, winData); } } @@ -747,14 +751,14 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) gl.glCreateShader && gl.glShaderSource && gl.glCompileShader && gl.glGetShaderiv && gl.glGetShaderInfoLog && gl.glDeleteShader && gl.glCreateProgram && gl.glAttachShader && gl.glLinkProgram && gl.glGetProgramiv && gl.glGetProgramInfoLog) { - gl.glGenTextures(1, &font.GlyphTexture); - gl.glTextureStorage2DEXT(font.GlyphTexture, eGL_TEXTURE_2D, 1, eGL_R8, FONT_TEX_WIDTH, FONT_TEX_HEIGHT); + gl.glGenTextures(1, &ctxdata.GlyphTexture); + gl.glTextureStorage2DEXT(ctxdata.GlyphTexture, eGL_TEXTURE_2D, 1, eGL_R8, FONT_TEX_WIDTH, FONT_TEX_HEIGHT); GLuint curvao = 0; gl.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&curvao); - gl.glGenVertexArrays(1, &font.DummyVAO); - gl.glBindVertexArray(font.DummyVAO); + gl.glGenVertexArrays(1, &ctxdata.DummyVAO); + gl.glBindVertexArray(ctxdata.DummyVAO); string ttfstring = GetEmbeddedResource(sourcecodepro_ttf); byte *ttfdata = (byte *)ttfstring.c_str(); @@ -770,8 +774,8 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) stbtt_bakedchar chardata[numChars]; int ret = stbtt_BakeFontBitmap(ttfdata, 0, pixelHeight, buf, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, firstChar, numChars, chardata); - font.CharSize = pixelHeight; - font.CharAspect = chardata->xadvance / pixelHeight; + ctxdata.CharSize = pixelHeight; + ctxdata.CharAspect = chardata->xadvance / pixelHeight; stbtt_fontinfo f = {0}; stbtt_InitFont(&f, ttfdata, 0); @@ -781,7 +785,7 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) float maxheight = float(ascent)*stbtt_ScaleForPixelHeight(&f, pixelHeight); - gl.glTextureSubImage2DEXT(font.GlyphTexture, eGL_TEXTURE_2D, 0, 0, 0, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, + gl.glTextureSubImage2DEXT(ctxdata.GlyphTexture, eGL_TEXTURE_2D, 0, 0, 0, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, eGL_RED, eGL_UNSIGNED_BYTE, (void *)buf); delete[] buf; @@ -799,14 +803,14 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) glyphData[(i+1)*2 + 1] = Vec4f(b->x0, b->y0, b->x1, b->y1); } - gl.glGenBuffers(1, &font.GlyphUBO); - gl.glNamedBufferStorageEXT(font.GlyphUBO, sizeof(glyphData), glyphData, 0); + gl.glGenBuffers(1, &ctxdata.GlyphUBO); + gl.glNamedBufferStorageEXT(ctxdata.GlyphUBO, sizeof(glyphData), glyphData, 0); - gl.glGenBuffers(1, &font.GeneralUBO); - gl.glNamedBufferStorageEXT(font.GeneralUBO, sizeof(FontUniforms), NULL, GL_MAP_WRITE_BIT); + gl.glGenBuffers(1, &ctxdata.GeneralUBO); + gl.glNamedBufferStorageEXT(ctxdata.GeneralUBO, sizeof(FontUniforms), NULL, GL_MAP_WRITE_BIT); - gl.glGenBuffers(1, &font.StringUBO); - gl.glNamedBufferStorageEXT(font.StringUBO, sizeof(uint32_t)*4*FONT_MAX_CHARS, NULL, GL_MAP_WRITE_BIT); + gl.glGenBuffers(1, &ctxdata.StringUBO); + gl.glNamedBufferStorageEXT(ctxdata.StringUBO, sizeof(uint32_t)*4*FONT_MAX_CHARS, NULL, GL_MAP_WRITE_BIT); string textvs = GetEmbeddedResource(debuguniforms_h); textvs += GetEmbeddedResource(text_vert); @@ -840,24 +844,24 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) RDCERR("Shader error: %s", buffer); } - font.Program = gl.glCreateProgram(); + ctxdata.Program = gl.glCreateProgram(); - gl.glAttachShader(font.Program, vs); - gl.glAttachShader(font.Program, fs); + gl.glAttachShader(ctxdata.Program, vs); + gl.glAttachShader(ctxdata.Program, fs); - gl.glLinkProgram(font.Program); + gl.glLinkProgram(ctxdata.Program); - gl.glGetProgramiv(font.Program, eGL_LINK_STATUS, &status); + gl.glGetProgramiv(ctxdata.Program, eGL_LINK_STATUS, &status); if(status == 0) { - gl.glGetProgramInfoLog(font.Program, 1024, NULL, buffer); + gl.glGetProgramInfoLog(ctxdata.Program, 1024, NULL, buffer); RDCERR("Link error: %s", buffer); } gl.glDeleteShader(vs); gl.glDeleteShader(fs); - font.ready = true; + ctxdata.ready = true; gl.glBindVertexArray(curvao); } @@ -996,11 +1000,11 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) RDCASSERT(strlen(text) < (size_t)FONT_MAX_CHARS); - ContextData &font = m_ContextData[GetCtx()]; + ContextData &ctxdata = m_ContextData[GetCtx()]; - if(!font.built || !font.ready) return; + if(!ctxdata.built || !ctxdata.ready) return; - gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, font.GeneralUBO); + gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.GeneralUBO); FontUniforms *ubo = (FontUniforms *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, sizeof(FontUniforms), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); ubo->TextPosition.x = x; @@ -1009,8 +1013,8 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) ubo->FontScreenAspect.x = 1.0f/float(m_InitParams.width); ubo->FontScreenAspect.y = 1.0f/float(m_InitParams.height); - ubo->TextSize = font.CharSize; - ubo->FontScreenAspect.x *= font.CharAspect; + ubo->TextSize = ctxdata.CharSize; + ubo->FontScreenAspect.x *= ctxdata.CharAspect; ubo->CharacterSize.x = 1.0f/float(FONT_TEX_WIDTH); ubo->CharacterSize.y = 1.0f/float(FONT_TEX_HEIGHT); @@ -1019,7 +1023,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) size_t len = strlen(text); - gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, font.StringUBO); + gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.StringUBO); uint32_t *texs = (uint32_t *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, len*4*sizeof(uint32_t), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); for(size_t i=0; i < len; i++) @@ -1053,19 +1057,19 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL); // bind UBOs - gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, font.GeneralUBO); - gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 1, font.GlyphUBO); - gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 2, font.StringUBO); + gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.GeneralUBO); + gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 1, ctxdata.GlyphUBO); + gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 2, ctxdata.StringUBO); // bind empty VAO just for valid rendering - gl.glBindVertexArray(font.DummyVAO); + gl.glBindVertexArray(ctxdata.DummyVAO); // bind textures gl.glActiveTexture(eGL_TEXTURE0); - gl.glBindTexture(eGL_TEXTURE_2D, font.GlyphTexture); + gl.glBindTexture(eGL_TEXTURE_2D, ctxdata.GlyphTexture); // bind program - gl.glUseProgram(font.Program); + gl.glUseProgram(ctxdata.Program); // draw string gl.glDrawArraysInstanced(eGL_TRIANGLE_STRIP, 0, 4, (GLsizei)len); diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 2278f3aa4..3e4e7d932 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -286,6 +286,8 @@ class WrappedOpenGL bool built; bool ready; + bool isCore; + GLuint Program; GLuint GeneralUBO, StringUBO, GlyphUBO; GLuint GlyphTexture; @@ -352,7 +354,7 @@ class WrappedOpenGL vector &GetFrameRecord() { return m_FrameRecord; } FetchAPIEvent GetEvent(uint32_t eventID); - void CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams); + void CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams, bool core); void DeleteContext(void *contextHandle); void ActivateContext(GLWindowingData winData); void WindowSize(void *windowHandle, uint32_t w, uint32_t h); diff --git a/renderdoc/driver/gl/gl_replay_linux.cpp b/renderdoc/driver/gl/gl_replay_linux.cpp index b7885ce0a..990b25044 100644 --- a/renderdoc/driver/gl/gl_replay_linux.cpp +++ b/renderdoc/driver/gl/gl_replay_linux.cpp @@ -119,7 +119,9 @@ uint64_t GLReplay::MakeOutputWindow(void *wn, bool depth) attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB; attribs[i++] = 3; attribs[i++] = GLX_CONTEXT_FLAGS_ARB; - attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB|GLX_CONTEXT_DEBUG_BIT_ARB; + attribs[i++] = GLX_CONTEXT_DEBUG_BIT_ARB; + attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB; + attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; GLXContext ctx = glXCreateContextAttribsProc(dpy, fbcfg[0], m_ReplayCtx.ctx, true, attribs); @@ -249,7 +251,9 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB; attribs[i++] = 3; attribs[i++] = GLX_CONTEXT_FLAGS_ARB; - attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB|GLX_CONTEXT_DEBUG_BIT_ARB; + attribs[i++] = GLX_CONTEXT_DEBUG_BIT_ARB; + attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB; + attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; Display *dpy = XOpenDisplay(NULL); diff --git a/renderdoc/driver/gl/gl_replay_win32.cpp b/renderdoc/driver/gl/gl_replay_win32.cpp index 17a7ed8e0..892ada280 100644 --- a/renderdoc/driver/gl/gl_replay_win32.cpp +++ b/renderdoc/driver/gl/gl_replay_win32.cpp @@ -159,7 +159,9 @@ uint64_t GLReplay::MakeOutputWindow(void *wn, bool depth) attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB; attribs[i++] = 3; attribs[i++] = WGL_CONTEXT_FLAGS_ARB; - attribs[i++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB|WGL_CONTEXT_DEBUG_BIT_ARB; + attribs[i++] = WGL_CONTEXT_DEBUG_BIT_ARB; + attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB; + attribs[i++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; HGLRC rc = createContextAttribs(DC, m_ReplayCtx.ctx, attribs); if(rc == NULL) @@ -375,7 +377,9 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB; attribs[i++] = 3; attribs[i++] = WGL_CONTEXT_FLAGS_ARB; - attribs[i++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB|WGL_CONTEXT_DEBUG_BIT_ARB; + attribs[i++] = WGL_CONTEXT_DEBUG_BIT_ARB; + attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB; + attribs[i++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; rc = createContextAttribs(dc, NULL, attribs); if(rc == NULL) diff --git a/renderdoc/hooks/gl_linux_hooks.cpp b/renderdoc/hooks/gl_linux_hooks.cpp index 94495d76e..db7e8e737 100644 --- a/renderdoc/hooks/gl_linux_hooks.cpp +++ b/renderdoc/hooks/gl_linux_hooks.cpp @@ -310,6 +310,8 @@ class OpenGLHook : LibraryHook GLX_CONTEXT_MINOR_VERSION_ARB, 2, GLX_CONTEXT_FLAGS_ARB, + 0, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0, 0, }; @@ -404,7 +406,7 @@ GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList data.wnd = (GLXDrawable)NULL; data.ctx = ret; - OpenGLHook::glhooks.GetDriver()->CreateContext(data, shareList, init); + OpenGLHook::glhooks.GetDriver()->CreateContext(data, shareList, init, false); return ret; } @@ -460,6 +462,20 @@ GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, GLXConte attribs = &attribVec[0]; } + RDCDEBUG("glXCreateContextAttribsARB:"); + + bool core = false; + + int *a = (int *)attribs; + while(*a) + { + RDCDEBUG("%x: %d", a[0], a[1]); + a += 2; + + if(a[0] == GLX_CONTEXT_PROFILE_MASK_ARB) + core = (a[1] & GLX_CONTEXT_CORE_PROFILE_BIT_ARB); + } + GLXContext ret = OpenGLHook::glhooks.glXCreateContextAttribsARB_real(dpy, config, shareList, direct, attribs); XVisualInfo *vis = OpenGLHook::glhooks.glXGetVisualFromFBConfig_real(dpy, config); @@ -488,7 +504,7 @@ GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, GLXConte data.wnd = (GLXDrawable)NULL; data.ctx = ret; - OpenGLHook::glhooks.GetDriver()->CreateContext(data, shareList, init); + OpenGLHook::glhooks.GetDriver()->CreateContext(data, shareList, init, core); return ret; } diff --git a/renderdoc/hooks/gl_win32_hooks.cpp b/renderdoc/hooks/gl_win32_hooks.cpp index bd836b111..dd3b727a8 100644 --- a/renderdoc/hooks/gl_win32_hooks.cpp +++ b/renderdoc/hooks/gl_win32_hooks.cpp @@ -277,6 +277,8 @@ class OpenGLHook : LibraryHook WGL_CONTEXT_MINOR_VERSION_ARB, 2, WGL_CONTEXT_FLAGS_ARB, + 0, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 0, 0, }; @@ -377,7 +379,7 @@ class OpenGLHook : LibraryHook data.wnd = WindowFromDC(dc); data.ctx = ret; - glhooks.GetDriver()->CreateContext(data, NULL, GetInitParamsForDC(dc)); + glhooks.GetDriver()->CreateContext(data, NULL, GetInitParamsForDC(dc), false); return ret; } @@ -398,7 +400,7 @@ class OpenGLHook : LibraryHook data.wnd = WindowFromDC(dc); data.ctx = ret; - glhooks.GetDriver()->CreateContext(data, NULL, GetInitParamsForDC(dc)); + glhooks.GetDriver()->CreateContext(data, NULL, GetInitParamsForDC(dc), false); return ret; } @@ -447,11 +449,16 @@ class OpenGLHook : LibraryHook RDCDEBUG("wglCreateContextAttribsARB:"); + bool core = false; + int *a = (int *)attribs; while(*a) { RDCDEBUG("%x: %d", a[0], a[1]); a += 2; + + if(a[0] == WGL_CONTEXT_PROFILE_MASK_ARB) + core = (a[1] & WGL_CONTEXT_CORE_PROFILE_BIT_ARB); } HGLRC ret = glhooks.wglCreateContextAttribsARB_realfunc(dc, hShareContext, attribs); @@ -461,7 +468,7 @@ class OpenGLHook : LibraryHook data.wnd = WindowFromDC(dc); data.ctx = ret; - glhooks.GetDriver()->CreateContext(data, hShareContext, GetInitParamsForDC(dc)); + glhooks.GetDriver()->CreateContext(data, hShareContext, GetInitParamsForDC(dc), core); return ret; }