From 4582056de0f86c08bc8458c586e276474291323a Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 10 May 2019 17:56:07 +0100 Subject: [PATCH] Avoid calling glCopyImageSubData on Qualcomm as some drivers have bugs --- renderdoc/driver/gl/gl_common.cpp | 14 +++++++++++- renderdoc/driver/gl/gl_common.h | 1 + renderdoc/driver/gl/gl_initstate.cpp | 34 ++++++++++++++++++++++++---- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index 33f7705f7..08ff9b8c8 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -479,11 +479,12 @@ void FetchEnabledExtensions() void DoVendorChecks(GLPlatform &platform, GLWindowingData context) { const char *vendor = ""; + const char *renderer = ""; if(GL.glGetString) { vendor = (const char *)GL.glGetString(eGL_VENDOR); - const char *renderer = (const char *)GL.glGetString(eGL_RENDERER); + renderer = (const char *)GL.glGetString(eGL_RENDERER); const char *version = (const char *)GL.glGetString(eGL_VERSION); RDCLOG("Vendor checks for %u (%s / %s / %s)", GLCoreVersion, vendor, renderer, version); @@ -769,6 +770,17 @@ void DoVendorChecks(GLPlatform &platform, GLWindowingData context) // avoiding use of the DSA function and always doing our emulated version. VendorCheck[VendorCheck_AMD_vertex_array_elem_buffer_query] = true; + // Qualcomm's implementation of glCopyImageSubData is buggy on some drivers and can cause GPU + // crashes or corrupted data. We force the initial state copies to happen via our emulation which + // uses framebuffer blits. + if(strstr(vendor, "Qualcomm") || strstr(vendor, "Adreno") || strstr(renderer, "Qualcomm") || + strstr(vendor, "Adreno")) + { + RDCWARN("Using hack to avoid glCopyImageSubData on Qualcomm"); + + VendorCheck[VendorCheck_Qualcomm_avoid_glCopyImageSubData] = true; + } + if(IsGLES) { // Check whether reading from the depth, stencil and depth-stencil buffers using glReadPixels is diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 28927863d..ef3dee57c 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -821,6 +821,7 @@ enum VendorCheckEnum VendorCheck_NV_ClearNamedFramebufferfiBugs, VendorCheck_AMD_copy_compressed_cubemaps, VendorCheck_AMD_vertex_array_elem_buffer_query, + VendorCheck_Qualcomm_avoid_glCopyImageSubData, VendorCheck_Count, }; extern bool VendorCheck[VendorCheck_Count]; diff --git a/renderdoc/driver/gl/gl_initstate.cpp b/renderdoc/driver/gl/gl_initstate.cpp index e2fad78f0..277f734c5 100644 --- a/renderdoc/driver/gl/gl_initstate.cpp +++ b/renderdoc/driver/gl/gl_initstate.cpp @@ -26,6 +26,16 @@ #include "gl_driver.h" #include "gl_manager.h" +// declare emulated glCopyImageSubData in case we need to force its use when the driver's version is +// buggy +namespace glEmulate +{ +void APIENTRY _glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, + GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, + GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, + GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +}; + const GLenum FramebufferInitialData::attachmentNames[10] = { eGL_COLOR_ATTACHMENT0, eGL_COLOR_ATTACHMENT1, eGL_COLOR_ATTACHMENT2, eGL_COLOR_ATTACHMENT3, eGL_COLOR_ATTACHMENT4, eGL_COLOR_ATTACHMENT5, eGL_COLOR_ATTACHMENT6, eGL_COLOR_ATTACHMENT7, @@ -951,10 +961,18 @@ void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, Resourc // 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(VendorCheck[VendorCheck_Qualcomm_avoid_glCopyImageSubData]) + glEmulate::_glCopyImageSubData(res.name, details.curType, i, 0, 0, 0, tex, + details.curType, i, 0, 0, 0, w, h, d); + else + GL.glCopyImageSubData(res.name, details.curType, i, 0, 0, 0, tex, details.curType, i, + 0, 0, 0, w, h, d); + } } } @@ -1971,10 +1989,18 @@ void GLResourceManager::Apply_InitialState(GLResource live, GLInitialContents in // (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(VendorCheck[VendorCheck_Qualcomm_avoid_glCopyImageSubData]) + glEmulate::_glCopyImageSubData(tex, details.curType, i, 0, 0, 0, live.name, + details.curType, i, 0, 0, 0, w, h, d); + else + GL.glCopyImageSubData(tex, details.curType, i, 0, 0, 0, live.name, details.curType, + i, 0, 0, 0, w, h, d); + } } }