From 171b36683a774d70a8f25529858b9c002a2a317e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 7 Sep 2020 18:52:30 +0200 Subject: GPUExtensions: GL backend isolation This is part of the Vulkan task T68990. This commits changes a few things: - Rename extensions to capabilities (but left the file name untouched). - Cubemap mip render workaround detection is rewritten using gl commands to avoid using the GPU API before initialization. - Put all the capabilities that are only relevant for the GL backend inside GLContext as static variables. - Cleanup the names of the limit variables. - Separate all GL related workaround search inside the GL module. --- source/blender/gpu/opengl/gl_backend.cc | 220 ++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) (limited to 'source/blender/gpu/opengl/gl_backend.cc') diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index d44bb9ba481..317416ca355 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -21,6 +21,9 @@ * \ingroup gpu */ +#include "BKE_global.h" + +#include "gpu_extensions_private.hh" #include "gpu_platform_private.hh" #include "glew-mx.h" @@ -29,6 +32,10 @@ namespace blender::gpu { +/* -------------------------------------------------------------------- */ +/** \name Platform + * \{ */ + void GLBackend::platform_init(void) { BLI_assert(!GPG.initialized); @@ -132,4 +139,217 @@ void GLBackend::platform_exit(void) GPG.clear(); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Capabilities + * \{ */ + +static bool detect_mip_render_workaround(void) +{ + int cube_size = 2; + float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f}; + float *source_pix = (float *)MEM_callocN(sizeof(float[4]) * cube_size * cube_size * 6, __func__); + + /* Not using GPU API since it is not yet fully initialized. */ + GLuint tex, fb; + /* Create cubemap with 2 mip level. */ + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_CUBE_MAP, tex); + for (int mip = 0; mip < 2; mip++) { + for (int i = 0; i < 6; i++) { + GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i; + glTexImage2D(target, mip, GL_RGBA16F, 2, 2, 0, GL_RGBA, GL_FLOAT, source_pix); + } + } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0); + /* Attach and clear mip 1. */ + glGenFramebuffers(1, &fb); + glBindFramebuffer(GL_FRAMEBUFFER, fb); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1); + glDrawBuffer(GL_COLOR_ATTACHMENT0); + glClearColor(UNPACK4(clear_color)); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glClear(GL_COLOR_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDrawBuffer(GL_BACK); + /* Read mip 1. If color is not the same as the clear_color, the rendering failed. */ + glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1, GL_RGBA, GL_FLOAT, source_pix); + bool enable_workaround = !equals_v4v4(clear_color, source_pix); + MEM_freeN(source_pix); + + glDeleteFramebuffers(1, &fb); + glDeleteTextures(1, &tex); + + return enable_workaround; +} + +static void detect_workarounds(void) +{ + const char *vendor = (const char *)glGetString(GL_VENDOR); + const char *renderer = (const char *)glGetString(GL_RENDERER); + const char *version = (const char *)glGetString(GL_VERSION); + + if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) { + printf("\n"); + printf("GL: Forcing workaround usage and disabling extensions.\n"); + printf(" OpenGL identification strings\n"); + printf(" vendor: %s\n", vendor); + printf(" renderer: %s\n", renderer); + printf(" version: %s\n\n", version); + GCaps.depth_blitting_workaround = true; + GCaps.mip_render_workaround = true; + GLContext::unused_fb_slot_workaround = true; + GLContext::texture_copy_workaround = true; + /* Turn off extensions. */ + GLContext::base_instance_support = false; + GLContext::texture_cube_map_array_support = false; + return; + } + + /* Some Intel drivers have issues with using mips as framebuffer targets if + * GL_TEXTURE_MAX_LEVEL is higher than the target mip. + * Only check at the end after all other workarounds because this uses the drawing code. */ + GCaps.mip_render_workaround = detect_mip_render_workaround(); + /* Limit support for GLEW_ARB_base_instance to OpenGL 4.0 and higher. NVIDIA Quadro FX 4800 + * (TeraScale) report that they support GLEW_ARB_base_instance, but the driver does not support + * GLEW_ARB_draw_indirect as it has an OpenGL3 context what also matches the minimum needed + * requirements. + * + * We use it as a target for glMapBuffer(Range) what is part of the OpenGL 4 API. So better + * disable it when we don't have an OpenGL4 context (See T77657) */ + if (!GLEW_VERSION_4_0) { + GLContext::base_instance_support = false; + } + /* The renderers include: + * Mobility Radeon HD 5000; + * Radeon HD 7500M; + * Radeon HD 7570M; + * Radeon HD 7600M; + * And many others... */ + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && + (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") || + strstr(version, "4.5.13422"))) { + GLContext::unused_fb_slot_workaround = true; + GCaps.broken_amd_driver = true; + } + /* We have issues with this specific renderer. (see T74024) */ + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && + strstr(renderer, "AMD VERDE")) { + GLContext::unused_fb_slot_workaround = true; + GCaps.broken_amd_driver = true; + } + /* Fix slowdown on this particular driver. (see T77641) */ + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && + strstr(version, "Mesa 19.3.4")) { + GCaps.broken_amd_driver = true; + } + /* There is an issue with the #glBlitFramebuffer on MacOS with radeon pro graphics. + * Blitting depth with#GL_DEPTH24_STENCIL8 is buggy so the workaround is to use + * #GPU_DEPTH32F_STENCIL8. Then Blitting depth will work but blitting stencil will + * still be broken. */ + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) { + if (strstr(renderer, "AMD Radeon Pro") || strstr(renderer, "AMD Radeon R9") || + strstr(renderer, "AMD Radeon RX")) { + GCaps.depth_blitting_workaround = true; + } + } + /* Limit this fix to older hardware with GL < 4.5. This means Broadwell GPUs are + * covered since they only support GL 4.4 on windows. + * This fixes some issues with workbench anti-aliasing on Win + Intel GPU. (see T76273) */ + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && !GLEW_VERSION_4_5) { + GLContext::texture_copy_workaround = true; + } + /* Special fix for theses specific GPUs. + * Without this workaround, blender crashes on startup. (see T72098) */ + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && + (strstr(renderer, "HD Graphics 620") || strstr(renderer, "HD Graphics 630"))) { + GCaps.mip_render_workaround = true; + } + /* Intel Ivy Bridge GPU's seems to have buggy cube-map array support. (see T75943) */ + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && + (strstr(renderer, "HD Graphics 4000") || strstr(renderer, "HD Graphics 4400") || + strstr(renderer, "HD Graphics 2500"))) { + GLContext::texture_cube_map_array_support = false; + } + /* Maybe not all of these drivers have problems with `GLEW_ARB_base_instance`. + * But it's hard to test each case. + * We get crashes from some crappy Intel drivers don't work well with shaders created in + * different rendering contexts. */ + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY) && + (strstr(version, "Build 10.18.10.3") || strstr(version, "Build 10.18.10.4") || + strstr(version, "Build 10.18.10.5") || strstr(version, "Build 10.18.14.4") || + strstr(version, "Build 10.18.14.5"))) { + GLContext::base_instance_support = false; + GCaps.use_main_context_workaround = true; + } + /* Somehow fixes armature display issues (see T69743). */ + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY) && + (strstr(version, "Build 20.19.15.4285"))) { + GCaps.use_main_context_workaround = true; + } + /* See T70187: merging vertices fail. This has been tested from 18.2.2 till 19.3.0~dev of the + * Mesa driver */ + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && + (strstr(version, "Mesa 18.") || strstr(version, "Mesa 19.0") || + strstr(version, "Mesa 19.1") || strstr(version, "Mesa 19.2"))) { + GLContext::unused_fb_slot_workaround = true; + } + + /* dFdx/dFdy calculation factors, those are dependent on driver. */ + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) && + strstr(version, "3.3.10750")) { + GLContext::derivative_signs[0] = 1.0; + GLContext::derivative_signs[1] = -1.0; + } + else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY)) { + if (strstr(version, "4.0.0 - Build 10.18.10.3308") || + strstr(version, "4.0.0 - Build 9.18.10.3186") || + strstr(version, "4.0.0 - Build 9.18.10.3165") || + strstr(version, "3.1.0 - Build 9.17.10.3347") || + strstr(version, "3.1.0 - Build 9.17.10.4101") || + strstr(version, "3.3.0 - Build 8.15.10.2618")) { + GLContext::derivative_signs[0] = -1.0; + GLContext::derivative_signs[1] = 1.0; + } + } +} + +/** Internal capabilities. */ +GLint GLContext::max_texture_3d_size; +GLint GLContext::max_cubemap_size; +GLint GLContext::max_ubo_size; +GLint GLContext::max_ubo_binds; +/** Extensions. */ +bool GLContext::base_instance_support = false; +bool GLContext::texture_cube_map_array_support = false; +/** Workarounds. */ +bool GLContext::texture_copy_workaround = false; +bool GLContext::unused_fb_slot_workaround = false; +float GLContext::derivative_signs[2] = {1.0f, 1.0f}; + +void GLBackend::capabilities_init(void) +{ + BLI_assert(GLEW_VERSION_3_3); + /* Common Capabilities. */ + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GCaps.max_texture_size); + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GCaps.max_texture_layers); + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GCaps.max_textures_frag); + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &GCaps.max_textures_vert); + glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GCaps.max_textures_geom); + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GCaps.max_textures); + /* GL specific capabilities. */ + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GLContext::max_texture_3d_size); + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GLContext::max_cubemap_size); + glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GLContext::max_ubo_binds); + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GLContext::max_ubo_size); + GLContext::base_instance_support = GLEW_ARB_base_instance; + GLContext::texture_cube_map_array_support = GLEW_ARB_texture_cube_map_array; + + detect_workarounds(); +} + +/** \} */ + } // namespace blender::gpu \ No newline at end of file -- cgit v1.2.3