Add a vendor check to detect if FBOs or VAOs are actually shared

* This lets us detect if the FBO/VAO behaviour is different from the main
  spec, and so we won't miss deletes or other events if the context is
  different since we'll treat them as shared like any other object.
This commit is contained in:
baldurk
2014-12-11 20:30:34 +00:00
parent a777a13021
commit 9be802082f
9 changed files with 153 additions and 37 deletions
+54 -26
View File
@@ -43,21 +43,24 @@ namespace TrackedResource
}
};
namespace ExtensionSupport
{
static bool extensions[ExtensionSupported_Count];
static bool VendorChecks[VendorCheck_Count];
};
bool ExtensionSupported[ExtensionSupported_Count];
bool VendorCheck[VendorCheck_Count];
int GLCoreVersion = 0;
void DoVendorChecks(const GLHookSet &gl)
// simple wrapper for OS functions to make/delete a context
GLWindowingData MakeContext(GLWindowingData share);
void DeleteContext(GLWindowingData context);
void MakeContextCurrent(GLWindowingData data);
void DoVendorChecks(const GLHookSet &gl, GLWindowingData context)
{
GLint numExts = 0;
if(gl.glGetIntegerv) gl.glGetIntegerv(eGL_NUM_EXTENSIONS, &numExts);
RDCEraseEl(ExtensionSupport::extensions);
RDCEraseEl(ExtensionSupport::VendorChecks);
RDCEraseEl(ExtensionSupported);
RDCEraseEl(VendorCheck);
if(gl.glGetStringi)
{
@@ -69,7 +72,7 @@ void DoVendorChecks(const GLHookSet &gl)
ext += 3;
#define EXT_CHECK(extname) if(!strcmp(ext, STRINGIZE(extname))) ExtensionSupport::extensions[CONCAT(ExtensionSupported_, extname)] = true;
#define EXT_CHECK(extname) if(!strcmp(ext, STRINGIZE(extname))) ExtensionSupported[CONCAT(ExtensionSupported_, extname)] = true;
EXT_CHECK(ARB_clip_control);
EXT_CHECK(ARB_enhanced_layouts);
@@ -106,7 +109,7 @@ void DoVendorChecks(const GLHookSet &gl)
if(err != eGL_NONE)
{
// if we got an error trying to query that, we should enable this hack
ExtensionSupport::VendorChecks[VendorCheck_AMD_vertex_buffer_query] = true;
VendorCheck[VendorCheck_AMD_vertex_buffer_query] = true;
RDCWARN("Using AMD hack to avoid GL_VERTEX_BINDING_BUFFER");
}
@@ -142,11 +145,11 @@ void DoVendorChecks(const GLHookSet &gl)
if(compSize == 8)
{
ExtensionSupport::VendorChecks[VendorCheck_EXT_compressed_cube_size] = false;
VendorCheck[VendorCheck_EXT_compressed_cube_size] = false;
}
else if(compSize == 48)
{
ExtensionSupport::VendorChecks[VendorCheck_EXT_compressed_cube_size] = true;
VendorCheck[VendorCheck_EXT_compressed_cube_size] = true;
}
else
{
@@ -156,20 +159,45 @@ void DoVendorChecks(const GLHookSet &gl)
gl.glDeleteTextures(1, &dummy);
}
// only do this when we have a proper context e.g. on windows where an old
// context is first created. Check to see if FBOs or VAOs are shared between
// contexts.
if(GLCoreVersion >= 32 &&
gl.glGenVertexArrays && gl.glBindVertexArray && gl.glDeleteVertexArrays &&
gl.glGenFramebuffers && gl.glBindFramebuffer && gl.glDeleteFramebuffers)
{
// gen & create an FBO and VAO
GLuint fbo = 0;
GLuint vao = 0;
gl.glGenFramebuffers(1, &fbo);
gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, fbo);
gl.glGenVertexArrays(1, &vao);
gl.glBindVertexArray(vao);
// make a context that shares with the current one, and switch to it
GLWindowingData child = MakeContext(context);
if(child.ctx)
{
// switch to child
MakeContextCurrent(child);
// these shouldn't be visible
VendorCheck[VendorCheck_EXT_fbo_shared] = (gl.glIsFramebuffer(fbo) != GL_FALSE);
VendorCheck[VendorCheck_EXT_vao_shared] = (gl.glIsVertexArray(vao) != GL_FALSE);
// switch back to context
MakeContextCurrent(context);
DeleteContext(child);
}
gl.glDeleteFramebuffers(1, &fbo);
gl.glDeleteVertexArrays(1, &vao);
}
// don't have a test for this, just have to enable it all the time, for now.
ExtensionSupport::VendorChecks[VendorCheck_NV_avoid_D32S8_copy] = true;
}
bool ExtensionSupported(ExtensionCheckEnum ext)
{
if(ext < 0 || ext >= ExtensionSupported_Count) return false;
return ExtensionSupport::extensions[ext];
}
bool VendorCheck(VendorCheckEnum vc)
{
if(vc < 0 || vc >= VendorCheck_Count) return false;
return ExtensionSupport::VendorChecks[vc];
VendorCheck[VendorCheck_NV_avoid_D32S8_copy] = true;
}
size_t BufferIdx(GLenum buf)
@@ -311,7 +339,7 @@ GLuint GetBoundVertexBuffer(const GLHookSet &gl, GLuint i)
{
GLuint buffer = 0;
if(VendorCheck(VendorCheck_AMD_vertex_buffer_query))
if(VendorCheck[VendorCheck_AMD_vertex_buffer_query])
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint *)&buffer);
else
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_BUFFER, i, (GLint *)&buffer);
+5 -3
View File
@@ -98,7 +98,7 @@ enum ExtensionCheckEnum
ExtensionSupported_ARB_clip_control,
ExtensionSupported_Count,
};
bool ExtensionSupported(ExtensionCheckEnum ext);
extern bool ExtensionSupported[ExtensionSupported_Count];
// for some things we need to know how a specific implementation behaves to work around it
// or adjust things. We centralise that here (similar to extensions)
@@ -107,12 +107,14 @@ enum VendorCheckEnum
VendorCheck_AMD_vertex_buffer_query,
VendorCheck_EXT_compressed_cube_size,
VendorCheck_NV_avoid_D32S8_copy,
VendorCheck_EXT_fbo_shared,
VendorCheck_EXT_vao_shared,
VendorCheck_Count,
};
bool VendorCheck(VendorCheckEnum ext);
extern bool VendorCheck[VendorCheck_Count];
// fills out the extension supported array and the version-specific checks above
void DoVendorChecks(const GLHookSet &gl);
void DoVendorChecks(const GLHookSet &gl, GLWindowingData context);
#include "serialise/serialiser.h"
#include "core/core.h"
+1 -1
View File
@@ -735,7 +735,7 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
if(ver > GLCoreVersion)
{
GLCoreVersion = ver;
DoVendorChecks(gl);
DoVendorChecks(gl, winData);
}
}
+3 -3
View File
@@ -286,7 +286,7 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
// 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))
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);
@@ -573,7 +573,7 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
// 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) && t == eGL_TEXTURE_CUBE_MAP)
if(VendorCheck[VendorCheck_EXT_compressed_cube_size] && t == eGL_TEXTURE_CUBE_MAP)
size /= 6;
byte *buf = new byte[size];
@@ -969,7 +969,7 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i
// 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))
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);
+1 -1
View File
@@ -115,7 +115,7 @@ void GLRenderState::FetchState(void *ctx, WrappedOpenGL *gl)
m_Real->glGetFloatv(eGL_POINT_SIZE, &PointSize);
m_Real->glGetIntegerv(eGL_PRIMITIVE_RESTART_INDEX, (GLint *)&PrimitiveRestartIndex);
if(GLCoreVersion >= 45 || ExtensionSupported(ExtensionSupported_ARB_clip_control))
if(GLCoreVersion >= 45 || ExtensionSupported[ExtensionSupported_ARB_clip_control])
{
m_Real->glGetIntegerv(eGL_CLIP_ORIGIN, (GLint *)&ClipOrigin);
m_Real->glGetIntegerv(eGL_CLIP_DEPTH_MODE, (GLint *)&ClipDepth);
+2 -2
View File
@@ -108,10 +108,10 @@ struct GLResource
// for objects in non-shared contexts
inline GLResource TextureRes(void *ctx, GLuint i) { (void)ctx; return GLResource(NULL, eResTexture, i); }
inline GLResource SamplerRes(void *ctx, GLuint i) { (void)ctx; return GLResource(NULL, eResSampler, i); }
inline GLResource FramebufferRes(void *ctx, GLuint i) { return GLResource(ctx, eResFramebuffer, i); }
inline GLResource FramebufferRes(void *ctx, GLuint i) { return GLResource(VendorCheck[VendorCheck_EXT_fbo_shared] ? NULL : ctx, eResFramebuffer, i); }
inline GLResource RenderbufferRes(void *ctx, GLuint i) { (void)ctx; return GLResource(NULL, eResRenderbuffer, i); }
inline GLResource BufferRes(void *ctx, GLuint i) { (void)ctx; return GLResource(NULL, eResBuffer, i); }
inline GLResource VertexArrayRes(void *ctx, GLuint i) { return GLResource(ctx, eResVertexArray, i); }
inline GLResource VertexArrayRes(void *ctx, GLuint i) { return GLResource(VendorCheck[VendorCheck_EXT_vao_shared] ? NULL : ctx, eResVertexArray, i); }
inline GLResource ShaderRes(void *ctx, GLuint i) { (void)ctx; return GLResource(NULL, eResShader, i); }
inline GLResource ProgramRes(void *ctx, GLuint i) { (void)ctx; return GLResource(NULL, eResProgram, i); }
inline GLResource ProgramPipeRes(void *ctx, GLuint i) { return GLResource(ctx, eResProgramPipe, i); }
+1 -1
View File
@@ -900,7 +900,7 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg,
GLsizei numProps = (GLsizei)ARRAY_COUNT(props);
// GL_LOCATION_COMPONENT not supported on core <4.4 (or without GL_ARB_enhanced_layouts)
if(!ExtensionSupported(ExtensionSupported_ARB_enhanced_layouts) && GLCoreVersion < 44)
if(!ExtensionSupported[ExtensionSupported_ARB_enhanced_layouts] && GLCoreVersion < 44)
numProps--;
gl.glGetProgramResourceiv(sepProg, sigEnum, i, numProps, props, numProps, NULL, values);
+50
View File
@@ -298,6 +298,46 @@ class OpenGLHook : LibraryHook
if(glXMakeCurrent_real)
glXMakeCurrent_real(data.dpy, data.wnd, data.ctx);
}
GLWindowingData MakeContext(GLWindowingData share)
{
GLWindowingData ret = {0};
if(glXCreateContextAttribsARB_real)
{
const int attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB,
3,
GLX_CONTEXT_MINOR_VERSION_ARB,
2,
GLX_CONTEXT_FLAGS_ARB,
0,
0, 0,
};
PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfigProc = (PFNGLXCHOOSEFBCONFIGPROC)dlsym(RTLD_NEXT, "glXChooseFBConfig");
if(glXChooseFBConfigProc)
{
// don't need to care about the fb config as we won't be using the default framebuffer (backbuffer)
int visAttribs[] = { 0 };
int numCfgs = 0;
GLXFBConfig *fbcfg = glXChooseFBConfigProc(dpy, DefaultScreen(dpy), visAttribs, &numCfgs);
if(fbcfg)
{
ret.dpy = share.dpy;
ret.ctx = glXCreateContextAttribsARB_real(share.dpy, fbcfg[0], share.ctx, false, attribs);
}
}
}
return ret;
}
void DeleteContext(GLWindowingData context)
{
if(context.ctx && glXDestroyContext_real)
glXDestroyContext_real(context.dpy, context.ctx);
}
WrappedOpenGL *GetDriver()
{
@@ -628,3 +668,13 @@ void MakeContextCurrent(GLWindowingData data)
OpenGLHook::glhooks.MakeContextCurrent(data);
}
GLWindowingData MakeContext(GLWindowingData share)
{
return OpenGLHook::glhooks.MakeContext(share);
}
void DeleteContext(GLWindowingData context)
{
OpenGLHook::glhooks.DeleteContext(context);
}
+36
View File
@@ -258,6 +258,32 @@ class OpenGLHook : LibraryHook
if(wglMakeCurrent_hook())
wglMakeCurrent_hook()(data.DC, data.ctx);
}
GLWindowingData MakeContext(GLWindowingData share)
{
GLWindowingData ret = {0};
if(wglCreateContextAttribsARB_realfunc)
{
const int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB,
3,
WGL_CONTEXT_MINOR_VERSION_ARB,
2,
WGL_CONTEXT_FLAGS_ARB,
0,
0, 0,
};
ret.DC = share.DC;
ret.ctx = wglCreateContextAttribsARB_realfunc(share.DC, share.ctx, attribs);
}
return ret;
}
void DeleteContext(GLWindowingData context)
{
if(context.ctx && wglDeleteContext_hook())
wglDeleteContext_hook()(context.ctx);
}
private:
WrappedOpenGL *GetDriver()
@@ -650,3 +676,13 @@ void MakeContextCurrent(GLWindowingData data)
{
OpenGLHook::glhooks.MakeContextCurrent(data);
}
GLWindowingData MakeContext(GLWindowingData share)
{
return OpenGLHook::glhooks.MakeContext(share);
}
void DeleteContext(GLWindowingData context)
{
OpenGLHook::glhooks.DeleteContext(context);
}