Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-09-07 19:52:30 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-09-07 20:37:04 +0300
commit171b36683a774d70a8f25529858b9c002a2a317e (patch)
treec87999c9f5ae85936d283868fc70f192af44263d /source
parent360489c75167d47653bc34ad9ba9a65076bf384c (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.h1
-rw-r--r--source/blender/draw/intern/draw_manager.c5
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/GPU_extensions.h4
-rw-r--r--source/blender/gpu/intern/gpu_extensions.cc352
-rw-r--r--source/blender/gpu/intern/gpu_extensions_private.hh54
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c3
-rw-r--r--source/blender/gpu/intern/gpu_private.h4
-rw-r--r--source/blender/gpu/intern/gpu_uniform_buffer.cc1
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc220
-rw-r--r--source/blender/gpu/opengl/gl_backend.hh3
-rw-r--r--source/blender/gpu/opengl/gl_batch.cc7
-rw-r--r--source/blender/gpu/opengl/gl_context.hh13
-rw-r--r--source/blender/gpu/opengl/gl_drawlist.cc2
-rw-r--r--source/blender/gpu/opengl/gl_framebuffer.cc2
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc7
-rw-r--r--source/blender/gpu/opengl/gl_texture.cc6
-rw-r--r--source/blender/gpu/opengl/gl_uniform_buffer.cc5
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;
}