Blender  V2.93
gl_backend.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2020, Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BKE_global.h"
25 
27 #include "gpu_platform_private.hh"
28 
29 #include "glew-mx.h"
30 
31 #include "gl_debug.hh"
32 
33 #include "gl_backend.hh"
34 
35 namespace blender::gpu {
36 
37 /* -------------------------------------------------------------------- */
41 static bool match_renderer(StringRef renderer, const Vector<std::string> &items)
42 {
43  for (const std::string &item : items) {
44  const std::string wrapped = " " + item + " ";
45  if (renderer.endswith(item) || renderer.find(wrapped) != StringRef::not_found) {
46  return true;
47  }
48  }
49  return false;
50 }
51 
52 void GLBackend::platform_init()
53 {
55  GPG.initialized = true;
56 
57 #ifdef _WIN32
58  GPG.os = GPU_OS_WIN;
59 #elif defined(__APPLE__)
60  GPG.os = GPU_OS_MAC;
61 #else
62  GPG.os = GPU_OS_UNIX;
63 #endif
64 
65  const char *vendor = (const char *)glGetString(GL_VENDOR);
66  const char *renderer = (const char *)glGetString(GL_RENDERER);
67  const char *version = (const char *)glGetString(GL_VERSION);
68 
69  if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) {
72  }
73  else if (strstr(vendor, "NVIDIA")) {
76  }
77  else if (strstr(vendor, "Intel") ||
78  /* src/mesa/drivers/dri/intel/intel_context.c */
79  strstr(renderer, "Mesa DRI Intel") || strstr(renderer, "Mesa DRI Mobile Intel")) {
82 
83  if (strstr(renderer, "UHD Graphics") ||
84  /* Not UHD but affected by the same bugs. */
85  strstr(renderer, "HD Graphics 530") || strstr(renderer, "Kaby Lake GT2") ||
86  strstr(renderer, "Whiskey Lake")) {
88  }
89  }
90  else if ((strstr(renderer, "Mesa DRI R")) ||
91  (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
92  (strstr(renderer, "AMD") && strstr(vendor, "X.Org")) ||
93  (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
94  (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD "))) {
97  }
98  else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
101  }
102  else if (strstr(vendor, "Mesa")) {
105  }
106  else if (strstr(vendor, "Microsoft")) {
109  }
110  else if (strstr(vendor, "Apple")) {
111  /* Apple Silicon. */
114  }
115  else if (strstr(renderer, "Apple Software Renderer")) {
118  }
119  else if (strstr(renderer, "llvmpipe") || strstr(renderer, "softpipe")) {
122  }
123  else {
124  printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n");
125  printf("Detected OpenGL configuration:\n");
126  printf("Vendor: %s\n", vendor);
127  printf("Renderer: %s\n", renderer);
130  }
131 
132  /* Detect support level */
133  if (!GLEW_VERSION_3_3) {
135  }
136  else {
138  /* Old Intel drivers with known bugs that cause material properties to crash.
139  * Version Build 10.18.14.5067 is the latest available and appears to be working
140  * ok with our workarounds, so excluded from this list. */
141  if (strstr(version, "Build 7.14") || strstr(version, "Build 7.15") ||
142  strstr(version, "Build 8.15") || strstr(version, "Build 9.17") ||
143  strstr(version, "Build 9.18") || strstr(version, "Build 10.18.10.3") ||
144  strstr(version, "Build 10.18.10.4") || strstr(version, "Build 10.18.10.5") ||
145  strstr(version, "Build 10.18.14.4")) {
147  }
148  }
150  /* Platform seems to work when SB backend is disabled. This can be done
151  * by adding the environment variable `R600_DEBUG=nosb`. */
152  if (strstr(renderer, "AMD CEDAR")) {
154  }
155  }
156  }
157  GPG.create_key(GPG.support_level, vendor, renderer, version);
158  GPG.create_gpu_name(vendor, renderer, version);
159 }
160 
161 void GLBackend::platform_exit()
162 {
164  GPG.clear();
165 }
166 
169 /* -------------------------------------------------------------------- */
174 {
175  int cube_size = 2;
176  float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f};
177  float *source_pix = (float *)MEM_callocN(sizeof(float[4]) * cube_size * cube_size * 6, __func__);
178 
179  /* NOTE: Debug layers are not yet enabled. Force use of glGetError. */
180  debug::check_gl_error("Cubemap Workaround Start");
181  /* Not using GPU API since it is not yet fully initialized. */
182  GLuint tex, fb;
183  /* Create cubemap with 2 mip level. */
184  glGenTextures(1, &tex);
185  glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
186  for (int mip = 0; mip < 2; mip++) {
187  for (int i = 0; i < 6; i++) {
188  const int width = cube_size / (1 << mip);
189  GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
190  glTexImage2D(target, mip, GL_RGBA16F, width, width, 0, GL_RGBA, GL_FLOAT, source_pix);
191  }
192  }
193  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
194  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
195  /* Attach and clear mip 1. */
196  glGenFramebuffers(1, &fb);
197  glBindFramebuffer(GL_FRAMEBUFFER, fb);
198  glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1);
199  glDrawBuffer(GL_COLOR_ATTACHMENT0);
200  glClearColor(UNPACK4(clear_color));
201  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
202  glClear(GL_COLOR_BUFFER_BIT);
203  glBindFramebuffer(GL_FRAMEBUFFER, 0);
204 
205  /* Read mip 1. If color is not the same as the clear_color, the rendering failed. */
206  glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1, GL_RGBA, GL_FLOAT, source_pix);
207  bool enable_workaround = !equals_v4v4(clear_color, source_pix);
208  MEM_freeN(source_pix);
209 
210  glDeleteFramebuffers(1, &fb);
211  glDeleteTextures(1, &tex);
212 
213  debug::check_gl_error("Cubemap Workaround End9");
214 
215  return enable_workaround;
216 }
217 
218 static void detect_workarounds()
219 {
220  const char *vendor = (const char *)glGetString(GL_VENDOR);
221  const char *renderer = (const char *)glGetString(GL_RENDERER);
222  const char *version = (const char *)glGetString(GL_VERSION);
223 
224  if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) {
225  printf("\n");
226  printf("GL: Forcing workaround usage and disabling extensions.\n");
227  printf(" OpenGL identification strings\n");
228  printf(" vendor: %s\n", vendor);
229  printf(" renderer: %s\n", renderer);
230  printf(" version: %s\n\n", version);
235  /* Turn off extensions. */
250  return;
251  }
252 
253  /* Limit support for GLEW_ARB_base_instance to OpenGL 4.0 and higher. NVIDIA Quadro FX 4800
254  * (TeraScale) report that they support GLEW_ARB_base_instance, but the driver does not support
255  * GLEW_ARB_draw_indirect as it has an OpenGL3 context what also matches the minimum needed
256  * requirements.
257  *
258  * We use it as a target for glMapBuffer(Range) what is part of the OpenGL 4 API. So better
259  * disable it when we don't have an OpenGL4 context (See T77657) */
260  if (!GLEW_VERSION_4_0) {
262  }
264  (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") ||
265  strstr(version, "4.5.13422") || strstr(version, "4.5.13467"))) {
266  /* The renderers include:
267  * Radeon HD 5000;
268  * Radeon HD 7500M;
269  * Radeon HD 7570M;
270  * Radeon HD 7600M;
271  * Radeon R5 Graphics;
272  * And others... */
276  GCaps.broken_amd_driver = true;
277  }
278  /* We have issues with this specific renderer. (see T74024) */
280  strstr(renderer, "AMD VERDE")) {
283  GCaps.broken_amd_driver = true;
284  }
285  /* Fix slowdown on this particular driver. (see T77641) */
287  strstr(version, "Mesa 19.3.4")) {
289  GCaps.broken_amd_driver = true;
290  }
291  /* See T82856: AMD drivers since 20.11 running on a polaris architecture doesn't support the
292  * `GL_INT_2_10_10_10_REV` data type correctly. This data type is used to pack normals and flags.
293  * The work around uses `GPU_RGBA16I`.
294  */
296  const Vector<std::string> matches = {"RX 460",
297  "RX 470",
298  "RX 480",
299  "RX 490",
300  "RX 560",
301  "RX 560X",
302  "RX 570",
303  "RX 580",
304  "RX 580X",
305  "RX 590",
306  "RX550/550",
307  "(TM) 520",
308  "(TM) 530",
309  "(TM) 535",
310  "R5",
311  "R7",
312  "R9"};
313 
314  if (match_renderer(renderer, matches)) {
316  }
317  }
318  /* There is an issue with the #glBlitFramebuffer on MacOS with radeon pro graphics.
319  * Blitting depth with#GL_DEPTH24_STENCIL8 is buggy so the workaround is to use
320  * #GPU_DEPTH32F_STENCIL8. Then Blitting depth will work but blitting stencil will
321  * still be broken. */
323  if (strstr(renderer, "AMD Radeon Pro") || strstr(renderer, "AMD Radeon R9") ||
324  strstr(renderer, "AMD Radeon RX")) {
326  }
327  }
328  /* Limit this fix to older hardware with GL < 4.5. This means Broadwell GPUs are
329  * covered since they only support GL 4.4 on windows.
330  * This fixes some issues with workbench anti-aliasing on Win + Intel GPU. (see T76273) */
331  if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && !GLEW_VERSION_4_5) {
333  }
334  /* Special fix for these specific GPUs.
335  * Without this workaround, blender crashes on startup. (see T72098) */
337  (strstr(renderer, "HD Graphics 620") || strstr(renderer, "HD Graphics 630"))) {
339  }
340  /* Intel Ivy Bridge GPU's seems to have buggy cube-map array support. (see T75943) */
342  (strstr(renderer, "HD Graphics 4000") || strstr(renderer, "HD Graphics 4400") ||
343  strstr(renderer, "HD Graphics 2500"))) {
345  }
346  /* Maybe not all of these drivers have problems with `GLEW_ARB_base_instance`.
347  * But it's hard to test each case.
348  * We get crashes from some crappy Intel drivers don't work well with shaders created in
349  * different rendering contexts. */
351  (strstr(version, "Build 10.18.10.3") || strstr(version, "Build 10.18.10.4") ||
352  strstr(version, "Build 10.18.10.5") || strstr(version, "Build 10.18.14.4") ||
353  strstr(version, "Build 10.18.14.5"))) {
356  }
357  /* Somehow fixes armature display issues (see T69743). */
359  (strstr(version, "Build 20.19.15.4285"))) {
361  }
362  /* See T70187: merging vertices fail. This has been tested from 18.2.2 till 19.3.0~dev of the
363  * Mesa driver */
365  (strstr(version, "Mesa 18.") || strstr(version, "Mesa 19.0") ||
366  strstr(version, "Mesa 19.1") || strstr(version, "Mesa 19.2"))) {
368  }
369  /* There is a bug on older Nvidia GPU where GL_ARB_texture_gather
370  * is reported to be supported but yield a compile error (see T55802). */
371  if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) && !GLEW_VERSION_4_0) {
373  }
374 
375  /* dFdx/dFdy calculation factors, those are dependent on driver. */
377  strstr(version, "3.3.10750")) {
379  GLContext::derivative_signs[1] = -1.0;
380  }
382  if (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
383  strstr(version, "4.0.0 - Build 9.18.10.3186") ||
384  strstr(version, "4.0.0 - Build 9.18.10.3165") ||
385  strstr(version, "3.1.0 - Build 9.17.10.3347") ||
386  strstr(version, "3.1.0 - Build 9.17.10.4101") ||
387  strstr(version, "3.3.0 - Build 8.15.10.2618")) {
388  GLContext::derivative_signs[0] = -1.0;
390  }
391  }
392 
393  /* Some Intel drivers have issues with using mips as frame-buffer targets if
394  * GL_TEXTURE_MAX_LEVEL is higher than the target MIP.
395  * Only check at the end after all other workarounds because this uses the drawing code.
396  * Also after device/driver flags to avoid the check that causes pre GCN Radeon to crash. */
397  if (GCaps.mip_render_workaround == false) {
399  }
400  /* Disable multi-draw if the base instance cannot be read. */
403  }
404  /* Enable our own incomplete debug layer if no other is available. */
405  if (GLContext::debug_layer_support == false) {
407  }
408 
409  /* Broken glGenerateMipmap on macOS 10.15.7 security update. */
411  strstr(renderer, "HD Graphics 4000")) {
413  }
414 } // namespace blender::gpu
415 
419 GLint GLContext::max_ubo_binds = 0;
420 GLint GLContext::max_ubo_size = 0;
424 bool GLContext::copy_image_support = false;
425 bool GLContext::debug_layer_support = false;
428 bool GLContext::multi_bind_support = false;
439 float GLContext::derivative_signs[2] = {1.0f, 1.0f};
440 
441 void GLBackend::capabilities_init()
442 {
443  BLI_assert(GLEW_VERSION_3_3);
444  /* Common Capabilities. */
445  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GCaps.max_texture_size);
446  glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GCaps.max_texture_layers);
447  glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GCaps.max_textures_frag);
448  glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &GCaps.max_textures_vert);
449  glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GCaps.max_textures_geom);
450  glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GCaps.max_textures);
451  GCaps.mem_stats_support = GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo;
452  GCaps.shader_image_load_store_support = GLEW_ARB_shader_image_load_store;
453  /* GL specific capabilities. */
454  glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GLContext::max_texture_3d_size);
455  glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GLContext::max_cubemap_size);
456  glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GLContext::max_ubo_binds);
457  glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GLContext::max_ubo_size);
458  GLContext::base_instance_support = GLEW_ARB_base_instance;
459  GLContext::clear_texture_support = GLEW_ARB_clear_texture;
460  GLContext::copy_image_support = GLEW_ARB_copy_image;
461  GLContext::debug_layer_support = GLEW_VERSION_4_3 || GLEW_KHR_debug || GLEW_ARB_debug_output;
462  GLContext::direct_state_access_support = GLEW_ARB_direct_state_access;
463  GLContext::fixed_restart_index_support = GLEW_ARB_ES3_compatibility;
464  GLContext::multi_bind_support = GLEW_ARB_multi_bind;
465  GLContext::multi_draw_indirect_support = GLEW_ARB_multi_draw_indirect;
466  GLContext::shader_draw_parameters_support = GLEW_ARB_shader_draw_parameters;
467  GLContext::texture_cube_map_array_support = GLEW_ARB_texture_cube_map_array;
468  GLContext::texture_filter_anisotropic_support = GLEW_EXT_texture_filter_anisotropic;
469  GLContext::texture_gather_support = GLEW_ARB_texture_gather;
470  GLContext::vertex_attrib_binding_support = GLEW_ARB_vertex_attrib_binding;
471 
473 
474  /* Disable this feature entirely when not debugging. */
475  if ((G.debug & G_DEBUG_GPU) == 0) {
478  }
479 }
480 
483 } // namespace blender::gpu
@ G_DEBUG_GPU
Definition: BKE_global.h:151
@ G_DEBUG_GPU_FORCE_WORKAROUNDS
Definition: BKE_global.h:153
#define BLI_assert(a)
Definition: BLI_assert.h:58
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT
#define UNPACK4(a)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
@ GPU_DRIVER_ANY
Definition: GPU_platform.h:56
@ GPU_DRIVER_OFFICIAL
Definition: GPU_platform.h:53
@ GPU_DRIVER_OPENSOURCE
Definition: GPU_platform.h:54
@ GPU_DRIVER_SOFTWARE
Definition: GPU_platform.h:55
@ GPU_SUPPORT_LEVEL_LIMITED
Definition: GPU_platform.h:61
@ GPU_SUPPORT_LEVEL_UNSUPPORTED
Definition: GPU_platform.h:62
@ GPU_OS_WIN
Definition: GPU_platform.h:46
@ GPU_OS_UNIX
Definition: GPU_platform.h:48
@ GPU_OS_ANY
Definition: GPU_platform.h:49
@ GPU_OS_MAC
Definition: GPU_platform.h:47
@ GPU_DEVICE_ATI
Definition: GPU_platform.h:34
@ GPU_DEVICE_INTEL_UHD
Definition: GPU_platform.h:36
@ GPU_DEVICE_SOFTWARE
Definition: GPU_platform.h:38
@ GPU_DEVICE_NVIDIA
Definition: GPU_platform.h:33
@ GPU_DEVICE_ANY
Definition: GPU_platform.h:40
@ GPU_DEVICE_APPLE
Definition: GPU_platform.h:37
@ GPU_DEVICE_INTEL
Definition: GPU_platform.h:35
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
static constexpr int64_t not_found
constexpr int64_t find(char c, int64_t pos=0) const
constexpr bool endswith(StringRef suffix) const
static bool debug_layer_support
Definition: gl_context.hh:67
static bool shader_draw_parameters_support
Definition: gl_context.hh:72
static GLint max_texture_3d_size
Definition: gl_context.hh:60
static bool debug_layer_workaround
Definition: gl_context.hh:78
static float derivative_signs[2]
Definition: gl_context.hh:81
static bool base_instance_support
Definition: gl_context.hh:64
static bool vertex_attrib_binding_support
Definition: gl_context.hh:76
static GLint max_ubo_binds
Definition: gl_context.hh:62
static bool fixed_restart_index_support
Definition: gl_context.hh:69
static bool copy_image_support
Definition: gl_context.hh:66
static bool texture_gather_support
Definition: gl_context.hh:75
static GLint max_ubo_size
Definition: gl_context.hh:61
static bool direct_state_access_support
Definition: gl_context.hh:68
static bool texture_filter_anisotropic_support
Definition: gl_context.hh:74
static bool clear_texture_support
Definition: gl_context.hh:65
static bool unused_fb_slot_workaround
Definition: gl_context.hh:79
static bool multi_bind_support
Definition: gl_context.hh:70
static GLint max_cubemap_size
Definition: gl_context.hh:59
static bool texture_cube_map_array_support
Definition: gl_context.hh:73
static bool generate_mipmap_workaround
Definition: gl_context.hh:80
static bool multi_draw_indirect_support
Definition: gl_context.hh:71
void create_gpu_name(const char *vendor, const char *renderer, const char *version)
Definition: gpu_platform.cc:67
void create_key(eGPUSupportLevel support_level, const char *vendor, const char *renderer, const char *version)
Definition: gpu_platform.cc:44
BLI_INLINE float fb(float length, float L)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void check_gl_error(const char *info)
Definition: gl_debug.cc:191
GPUPlatformGlobal GPG
Definition: gpu_platform.cc:42
static void detect_workarounds()
Definition: gl_backend.cc:218
GPUCapabilities GCaps
static bool detect_mip_render_workaround()
Definition: gl_backend.cc:173
static bool match_renderer(StringRef renderer, const Vector< std::string > &items)
Definition: gl_backend.cc:41
#define G(x, y, z)