diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-09-07 19:52:30 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-09-07 20:37:04 +0300 |
commit | 171b36683a774d70a8f25529858b9c002a2a317e (patch) | |
tree | c87999c9f5ae85936d283868fc70f192af44263d /source | |
parent | 360489c75167d47653bc34ad9ba9a65076bf384c (diff) |
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.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 1 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 5 | ||||
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/gpu/GPU_extensions.h | 4 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.cc | 352 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions_private.hh | 54 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_init_exit.c | 3 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_private.h | 4 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_uniform_buffer.cc | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_backend.cc | 220 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_backend.hh | 3 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_batch.cc | 7 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_context.hh | 13 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_drawlist.cc | 2 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_framebuffer.cc | 2 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_shader.cc | 7 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_texture.cc | 6 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_uniform_buffer.cc | 5 |
18 files changed, 340 insertions, 350 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 680636f9e87..e154a52b32f 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -721,7 +721,6 @@ void DRW_state_lock(DRWState state); void DRW_select_load_id(uint id); /* Draw State */ -void DRW_state_dfdy_factors_get(float dfdyfac[2]); bool DRW_state_is_fbo(void); bool DRW_state_is_select(void); bool DRW_state_is_depth(void); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 09ce16efcc2..49780f59db3 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2496,11 +2496,6 @@ void DRW_draw_depth_object( /** \name Draw Manager State (DRW_state) * \{ */ -void DRW_state_dfdy_factors_get(float dfdyfac[2]) -{ - GPU_get_dfdy_factors(dfdyfac); -} - /** * When false, drawing doesn't output to a pixel buffer * eg: Occlusion queries, or when we have setup a context to draw in already. diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 47ce113230b..358bd045c2f 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -137,6 +137,7 @@ set(SRC intern/gpu_codegen.h intern/gpu_context_private.hh intern/gpu_drawlist_private.hh + intern/gpu_extensions_private.hh intern/gpu_framebuffer_private.hh intern/gpu_immediate_private.hh intern/gpu_index_buffer_private.hh diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 35967ac304f..dd0a2ec9f39 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -41,14 +41,10 @@ int GPU_max_color_texture_samples(void); int GPU_max_cube_map_size(void); int GPU_max_ubo_binds(void); int GPU_max_ubo_size(void); -void GPU_get_dfdy_factors(float fac[2]); -bool GPU_arb_base_instance_is_supported(void); bool GPU_arb_texture_cube_map_array_is_supported(void); bool GPU_mip_render_workaround(void); bool GPU_depth_blitting_workaround(void); -bool GPU_unused_fb_slot_workaround(void); bool GPU_use_main_context_workaround(void); -bool GPU_texture_copy_workaround(void); bool GPU_crappy_amd_driver(void); int GPU_texture_size_with_limit(int res); diff --git a/source/blender/gpu/intern/gpu_extensions.cc b/source/blender/gpu/intern/gpu_extensions.cc index ac7748e6430..168d2fb3fbb 100644 --- a/source/blender/gpu/intern/gpu_extensions.cc +++ b/source/blender/gpu/intern/gpu_extensions.cc @@ -24,381 +24,95 @@ * with checks for drivers and GPU support. */ -#include "BLI_math_base.h" -#include "BLI_math_vector.h" -#include "BLI_utildefines.h" - -#include "BKE_global.h" -#include "MEM_guardedalloc.h" - #include "DNA_userdef_types.h" #include "GPU_extensions.h" -#include "GPU_framebuffer.h" -#include "GPU_glew.h" -#include "GPU_platform.h" -#include "GPU_texture.h" - -#include "intern/gpu_private.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifdef WIN32 -# include "BLI_winstuff.h" -#endif - -/* Extensions support */ - -/* -- extension: version of GL that absorbs it - * EXT_gpu_shader4: 3.0 - * ARB_framebuffer object: 3.0 - * EXT_framebuffer_multisample_blit_scaled: ??? - * ARB_draw_instanced: 3.1 - * ARB_texture_multisample: 3.2 - * ARB_texture_query_lod: 4.0 - */ - -static struct GPUGlobal { - GLint maxtexsize; - GLint maxtex3dsize; - GLint maxtexlayers; - GLint maxcubemapsize; - GLint maxtextures; - GLint maxtexturesfrag; - GLint maxtexturesgeom; - GLint maxtexturesvert; - GLint maxubosize; - GLint maxubobinds; - int samples_color_texture_max; - /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers - * calculate dfdy in shader differently when drawing to an off-screen buffer. First - * number is factor on screen and second is off-screen */ - float dfdyfactors[2]; - /* Some Intel drivers have limited support for `GLEW_ARB_base_instance` so in - * these cases it is best to indicate that it is not supported. See T67951 */ - bool glew_arb_base_instance_is_supported; - /* Cubemap Array support. */ - bool glew_arb_texture_cube_map_array_is_supported; - /* Some Intel drivers have issues with using mips as framebuffer targets if - * GL_TEXTURE_MAX_LEVEL is higher than the target mip. - * We need a workaround in this cases. */ - bool mip_render_workaround; - /* 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. */ - bool depth_blitting_workaround; - /* Crappy driver don't know how to map framebuffer slot to output vars... - * We need to have no "holes" in the output buffer slots. */ - bool unused_fb_slot_workaround; - bool broken_amd_driver; - /* Some crappy Intel drivers don't work well with shaders created in different - * rendering contexts. */ - bool use_main_context_workaround; - /* Intel drivers exhibit artifacts when using #glCopyImageSubData & workbench anti-aliasing. - * (see T76273) */ - bool texture_copy_workaround; -} GG = {1, 0}; - -static void gpu_detect_mip_render_workaround(void) -{ - int cube_size = 2; - float *source_pix = (float *)MEM_callocN(sizeof(float[4][6]) * cube_size * cube_size, __func__); - float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f}; - GPUTexture *tex = GPU_texture_create_cube(__func__, cube_size, 2, GPU_RGBA16F, source_pix); - MEM_freeN(source_pix); +#include "gpu_extensions_private.hh" - GPU_texture_bind(tex, 0); - GPU_texture_generate_mipmap(tex); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, 0); - GPU_texture_unbind(tex); +#include "gl_backend.hh" /* TODO remove */ - GPUFrameBuffer *fb = GPU_framebuffer_create(__func__); - GPU_framebuffer_texture_attach(fb, tex, 0, 1); - GPU_framebuffer_bind(fb); - GPU_framebuffer_clear_color(fb, clear_color); - GPU_framebuffer_restore(); - GPU_framebuffer_free(fb); +namespace blender::gpu { - float *data = (float *)GPU_texture_read(tex, GPU_DATA_FLOAT, 1); - GG.mip_render_workaround = !equals_v4v4(clear_color, data); +GPUCapabilities GCaps; - MEM_freeN(data); - GPU_texture_free(tex); } -/* GPU Extensions */ +using namespace blender::gpu; + +/* -------------------------------------------------------------------- */ +/** \name Capabilities + * \{ */ int GPU_max_texture_size(void) { - return GG.maxtexsize; + return GCaps.max_texture_size; } -int GPU_max_texture_3d_size(void) +int GPU_texture_size_with_limit(int res) { - return GG.maxtex3dsize; + int size = GPU_max_texture_size(); + int reslimit = (U.glreslimit != 0) ? min_ii(U.glreslimit, size) : size; + return min_ii(reslimit, res); } int GPU_max_texture_layers(void) { - return GG.maxtexlayers; -} - -int GPU_max_textures(void) -{ - return GG.maxtextures; -} - -int GPU_max_textures_frag(void) -{ - return GG.maxtexturesfrag; -} - -int GPU_max_textures_geom(void) -{ - return GG.maxtexturesgeom; + return GCaps.max_texture_layers; } int GPU_max_textures_vert(void) { - return GG.maxtexturesvert; -} - -int GPU_max_color_texture_samples(void) -{ - return GG.samples_color_texture_max; -} - -int GPU_max_cube_map_size(void) -{ - return GG.maxcubemapsize; -} - -int GPU_max_ubo_binds(void) -{ - return GG.maxubobinds; + return GCaps.max_textures_vert; } -int GPU_max_ubo_size(void) +int GPU_max_textures_geom(void) { - return GG.maxubosize; + return GCaps.max_textures_geom; } -void GPU_get_dfdy_factors(float fac[2]) +int GPU_max_textures_frag(void) { - copy_v2_v2(fac, GG.dfdyfactors); + return GCaps.max_textures_frag; } -bool GPU_arb_base_instance_is_supported(void) +int GPU_max_textures(void) { - return GG.glew_arb_base_instance_is_supported; + return GCaps.max_textures; } bool GPU_arb_texture_cube_map_array_is_supported(void) { - return GG.glew_arb_texture_cube_map_array_is_supported; + /* FIXME bad level call. */ + return GLContext::texture_cube_map_array_support; } bool GPU_mip_render_workaround(void) { - return GG.mip_render_workaround; + return GCaps.mip_render_workaround; } bool GPU_depth_blitting_workaround(void) { - return GG.depth_blitting_workaround; -} - -bool GPU_unused_fb_slot_workaround(void) -{ - return GG.unused_fb_slot_workaround; + return GCaps.depth_blitting_workaround; } bool GPU_use_main_context_workaround(void) { - return GG.use_main_context_workaround; -} - -bool GPU_texture_copy_workaround(void) -{ - return GG.texture_copy_workaround; + return GCaps.use_main_context_workaround; } bool GPU_crappy_amd_driver(void) { /* Currently are the same drivers with the `unused_fb_slot` problem. */ - return GG.broken_amd_driver; -} - -int GPU_texture_size_with_limit(int res) -{ - int size = GPU_max_texture_size(); - int reslimit = (U.glreslimit != 0) ? min_ii(U.glreslimit, size) : size; - return min_ii(reslimit, res); + return GCaps.broken_amd_driver; } -void gpu_extensions_init(void) -{ - /* during 2.8 development each platform has its own OpenGL minimum requirements - * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions - * see developer.blender.org/T49012 for details - */ - BLI_assert(GLEW_VERSION_3_3); - - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesfrag); - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesvert); - glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GG.maxtexturesgeom); - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures); - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize); - glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GG.maxtex3dsize); - glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers); - glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize); +/** \} */ - glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds); - glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize); - - glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max); - - 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 (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_OFFICIAL)) { - if (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") || - strstr(version, "4.5.13422")) { - /* The renderers include: - * Mobility Radeon HD 5000; - * Radeon HD 7500M; - * Radeon HD 7570M; - * Radeon HD 7600M; - * And many others... */ - - GG.unused_fb_slot_workaround = true; - GG.broken_amd_driver = true; - } - } - - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && - strstr(renderer, "AMD VERDE")) { - /* We have issues with this specific renderer. (see T74024) */ - GG.unused_fb_slot_workaround = true; - GG.broken_amd_driver = true; - } - - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && - strstr(version, "Mesa 19.3.4")) { - /* Fix slowdown on this particular driver. (see T77641) */ - GG.broken_amd_driver = true; - } - - 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")) { - GG.depth_blitting_workaround = true; - } - } - - if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL)) { - /* 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 (!GLEW_VERSION_4_5) { - GG.texture_copy_workaround = true; - } - } - - /* 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) */ - GG.glew_arb_base_instance_is_supported = GLEW_ARB_base_instance && GLEW_VERSION_4_0; - GG.glew_arb_texture_cube_map_array_is_supported = GLEW_ARB_texture_cube_map_array; - gpu_detect_mip_render_workaround(); - - if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) { - printf("\n"); - printf("GPU: Bypassing workaround detection.\n"); - printf("GPU: OpenGL identification strings\n"); - printf("GPU: vendor: %s\n", vendor); - printf("GPU: renderer: %s\n", renderer); - printf("GPU: version: %s\n\n", version); - GG.mip_render_workaround = true; - GG.depth_blitting_workaround = true; - GG.unused_fb_slot_workaround = true; - GG.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"))) { - GG.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"))) { - GG.glew_arb_texture_cube_map_array_is_supported = false; - } - - /* df/dy calculation factors, those are dependent on driver */ - GG.dfdyfactors[0] = 1.0; - GG.dfdyfactors[1] = 1.0; - - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) && - strstr(version, "3.3.10750")) { - GG.dfdyfactors[0] = 1.0; - GG.dfdyfactors[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")) { - GG.dfdyfactors[0] = -1.0; - GG.dfdyfactors[1] = 1.0; - } - - if (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")) { - /* Maybe not all of these drivers have problems with `GLEW_ARB_base_instance`. - * But it's hard to test each case. */ - GG.glew_arb_base_instance_is_supported = false; - GG.use_main_context_workaround = true; - } - - if (strstr(version, "Build 20.19.15.4285")) { - /* Somehow fixes armature display issues (see T69743). */ - GG.use_main_context_workaround = true; - } - } - else 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"))) { - /* See T70187: merging vertices fail. This has been tested from 18.2.2 till 19.3.0~dev of the - * Mesa driver */ - GG.unused_fb_slot_workaround = true; - } - - GPU_invalid_tex_init(); -} - -void gpu_extensions_exit(void) -{ - GPU_invalid_tex_free(); -} +/* -------------------------------------------------------------------- */ +/** \name Memory statistics + * \{ */ bool GPU_mem_stats_supported(void) { @@ -439,3 +153,5 @@ bool GPU_stereo_quadbuffer_support(void) glGetBooleanv(GL_STEREO, &stereo); return stereo == GL_TRUE; } + +/** \} */ diff --git a/source/blender/gpu/intern/gpu_extensions_private.hh b/source/blender/gpu/intern/gpu_extensions_private.hh new file mode 100644 index 00000000000..ec387555bfe --- /dev/null +++ b/source/blender/gpu/intern/gpu_extensions_private.hh @@ -0,0 +1,54 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "GPU_platform.h" + +namespace blender::gpu { + +/** + * This includes both hardware capabilities & workarounds. + * Try to limit these to the implementation codebase (i.e.: gpu/opengl/). + * Only add workarounds here if they are common to all implementation or + * if you need access to it outside of the GPU module. + * Same goes for capabilities (i.e.: texture size) + **/ +struct GPUCapabilities { + int max_texture_size = 0; + int max_texture_layers = 0; + int max_textures = 0; + int max_textures_vert = 0; + int max_textures_geom = 0; + int max_textures_frag = 0; + + /* OpenGL related workarounds. */ + bool mip_render_workaround = false; + bool depth_blitting_workaround = false; + bool use_main_context_workaround = false; + bool broken_amd_driver = false; +}; + +extern GPUCapabilities GCaps; + +} // namespace blender::gpu
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c index f265d841922..129a66994b1 100644 --- a/source/blender/gpu/intern/gpu_init_exit.c +++ b/source/blender/gpu/intern/gpu_init_exit.c @@ -48,7 +48,6 @@ void GPU_init(void) } initialized = true; - gpu_extensions_init(); /* must come first */ gpu_codegen_init(); gpu_material_library_init(); @@ -79,8 +78,6 @@ void GPU_exit(void) gpu_material_library_exit(); gpu_codegen_exit(); - gpu_extensions_exit(); - initialized = false; } diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h index 059d19f1002..310a432c102 100644 --- a/source/blender/gpu/intern/gpu_private.h +++ b/source/blender/gpu/intern/gpu_private.h @@ -24,10 +24,6 @@ extern "C" { #endif -/* call this before running any of the functions below */ -void gpu_extensions_init(void); -void gpu_extensions_exit(void); - /* gpu_pbvh.c */ void gpu_pbvh_init(void); void gpu_pbvh_exit(void); diff --git a/source/blender/gpu/intern/gpu_uniform_buffer.cc b/source/blender/gpu/intern/gpu_uniform_buffer.cc index 94aa6bd76ab..24e5b452e03 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer.cc +++ b/source/blender/gpu/intern/gpu_uniform_buffer.cc @@ -47,7 +47,6 @@ UniformBuf::UniformBuf(size_t size, const char *name) { /* Make sure that UBO is padded to size of vec4 */ BLI_assert((size % 16) == 0); - BLI_assert(size <= GPU_max_ubo_size()); size_in_bytes_ = size; 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 diff --git a/source/blender/gpu/opengl/gl_backend.hh b/source/blender/gpu/opengl/gl_backend.hh index 9548aa9dd92..25f3ff38d8b 100644 --- a/source/blender/gpu/opengl/gl_backend.hh +++ b/source/blender/gpu/opengl/gl_backend.hh @@ -50,6 +50,7 @@ class GLBackend : public GPUBackend { /* platform_init needs to go first. */ GLBackend::platform_init(); + GLBackend::capabilities_init(); GLTexture::samplers_init(); } ~GLBackend() @@ -127,6 +128,8 @@ class GLBackend : public GPUBackend { private: static void platform_init(void); static void platform_exit(void); + + static void capabilities_init(void); }; } // namespace gpu diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc index db30a57953d..f4ad7194ce1 100644 --- a/source/blender/gpu/opengl/gl_batch.cc +++ b/source/blender/gpu/opengl/gl_batch.cc @@ -34,6 +34,7 @@ #include "gpu_batch_private.hh" #include "gpu_shader_private.hh" +#include "gl_backend.hh" #include "gl_context.hh" #include "gl_debug.hh" #include "gl_index_buffer.hh" @@ -314,7 +315,7 @@ void GLBatch::bind(int i_first) #endif /* Can be removed if GL 4.2 is required. */ - if (!GPU_arb_base_instance_is_supported() && (i_first > 0)) { + if (!GLContext::base_instance_support && (i_first > 0)) { glBindVertexArray(vao_cache_.base_instance_vao_get(this, i_first)); } else { @@ -339,7 +340,7 @@ void GLBatch::draw(int v_first, int v_count, int i_first, int i_count) GLint base_index = el->index_base_; void *v_first_ofs = el->offset_ptr(v_first); - if (GPU_arb_base_instance_is_supported()) { + if (GLContext::base_instance_support) { glDrawElementsInstancedBaseVertexBaseInstance( gl_type, v_count, index_type, v_first_ofs, i_count, base_index, i_first); } @@ -353,7 +354,7 @@ void GLBatch::draw(int v_first, int v_count, int i_first, int i_count) #ifdef __APPLE__ glDisable(GL_PRIMITIVE_RESTART); #endif - if (GPU_arb_base_instance_is_supported()) { + if (GLContext::base_instance_support) { glDrawArraysInstancedBaseInstance(gl_type, v_first, v_count, i_count, i_first); } else { diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh index 9e6359fabad..e2ae8bf24b2 100644 --- a/source/blender/gpu/opengl/gl_context.hh +++ b/source/blender/gpu/opengl/gl_context.hh @@ -55,6 +55,19 @@ class GLSharedOrphanLists { class GLContext : public GPUContext { public: + /** Capabilities. */ + static GLint max_texture_3d_size; + static GLint max_cubemap_size; + static GLint max_ubo_size; + static GLint max_ubo_binds; + /** Extensions. */ + static bool base_instance_support; + static bool texture_cube_map_array_support; + /** Workarounds. */ + static bool texture_copy_workaround; + static bool unused_fb_slot_workaround; + static float derivative_signs[2]; + /** Used for debugging purpose. Bitflags of all bound slots. */ uint16_t bound_ubo_slots; diff --git a/source/blender/gpu/opengl/gl_drawlist.cc b/source/blender/gpu/opengl/gl_drawlist.cc index d8c17084457..0768f7502ce 100644 --- a/source/blender/gpu/opengl/gl_drawlist.cc +++ b/source/blender/gpu/opengl/gl_drawlist.cc @@ -76,7 +76,7 @@ GLDrawList::GLDrawList(int length) data_ = NULL; if (USE_MULTI_DRAW_INDIRECT && GLEW_ARB_multi_draw_indirect && - GPU_arb_base_instance_is_supported()) { + GLContext::base_instance_support) { /* Alloc the biggest possible command list, which is indexed. */ buffer_size_ = sizeof(GLDrawCommandIndexed) * length; } diff --git a/source/blender/gpu/opengl/gl_framebuffer.cc b/source/blender/gpu/opengl/gl_framebuffer.cc index 4be471b236a..506a945d9d4 100644 --- a/source/blender/gpu/opengl/gl_framebuffer.cc +++ b/source/blender/gpu/opengl/gl_framebuffer.cc @@ -208,7 +208,7 @@ void GLFrameBuffer::update_attachments(void) } } - if (GPU_unused_fb_slot_workaround()) { + if (GLContext::unused_fb_slot_workaround) { /* Fill normally un-occupied slots to avoid rendering artifacts on some hardware. */ GLuint gl_tex = 0; /* NOTE: Inverse iteration to get the first color texture. */ diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 9136a1d9714..f125afeb535 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -28,6 +28,7 @@ #include "GPU_extensions.h" #include "GPU_platform.h" +#include "gl_backend.hh" #include "gl_vertex_buffer.hh" #include "gl_shader.hh" @@ -118,10 +119,8 @@ char *GLShader::glsl_patch_get(void) } /* Derivative sign can change depending on implementation. */ - float derivatives[2]; - GPU_get_dfdy_factors(derivatives); - STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", derivatives[0]); - STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", derivatives[1]); + STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]); + STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]); BLI_assert(slen < sizeof(patch)); return patch; diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc index 6cff97215e8..ba2e5844cc7 100644 --- a/source/blender/gpu/opengl/gl_texture.cc +++ b/source/blender/gpu/opengl/gl_texture.cc @@ -369,7 +369,7 @@ void GLTexture::copy_to(Texture *dst_) /* TODO support array / 3D textures. */ BLI_assert(dst->d_ == 0); - if (GLEW_ARB_copy_image && !GPU_texture_copy_workaround()) { + if (GLEW_ARB_copy_image && !GLContext::texture_copy_workaround) { /* Opengl 4.3 */ int mip = 0; /* NOTE: mip_size_get() won't override any dimension that is equal to 0. */ @@ -560,8 +560,8 @@ bool GLTexture::proxy_check(int mip) { /* Manual validation first, since some implementation have issues with proxy creation. */ int max_size = GPU_max_texture_size(); - int max_3d_size = GPU_max_texture_3d_size(); - int max_cube_size = GPU_max_cube_map_size(); + int max_3d_size = GLContext::max_texture_3d_size; + int max_cube_size = GLContext::max_cubemap_size; int size[3] = {1, 1, 1}; this->mip_size_get(mip, size); diff --git a/source/blender/gpu/opengl/gl_uniform_buffer.cc b/source/blender/gpu/opengl/gl_uniform_buffer.cc index 0e0c64e5c60..82b7341d145 100644 --- a/source/blender/gpu/opengl/gl_uniform_buffer.cc +++ b/source/blender/gpu/opengl/gl_uniform_buffer.cc @@ -42,6 +42,7 @@ namespace blender::gpu { GLUniformBuf::GLUniformBuf(size_t size, const char *name) : UniformBuf(size, name) { /* Do not create ubo GL buffer here to allow allocation from any thread. */ + BLI_assert(size <= GLContext::max_ubo_size); } GLUniformBuf::~GLUniformBuf() @@ -90,12 +91,12 @@ void GLUniformBuf::update(const void *data) void GLUniformBuf::bind(int slot) { - if (slot >= GPU_max_ubo_binds()) { + if (slot >= GLContext::max_ubo_binds) { fprintf(stderr, "Error: Trying to bind \"%s\" ubo to slot %d which is above the reported limit of %d.", name_, slot, - GPU_max_ubo_binds()); + GLContext::max_ubo_binds); return; } |