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
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/blender/gpu/opengl
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/blender/gpu/opengl')
-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
9 files changed, 251 insertions, 14 deletions
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;
}