GL: Wrap extension support inside GLContext

This makes it possible to disable all the extensions when forcing
workarounds.

Also it will allow future options to selectively disable each extension
to know which one is buggy.
This commit is contained in:
Clément Foucault 2020-09-10 14:18:19 +02:00
parent 9d5977f5e1
commit 8d59f060ca
8 changed files with 76 additions and 44 deletions

View File

@ -209,11 +209,20 @@ static void detect_workarounds(void)
GCaps.mip_render_workaround = true;
GLContext::debug_layer_workaround = true;
GLContext::unused_fb_slot_workaround = true;
GLContext::texture_copy_workaround = true;
/* Turn off extensions. */
GLContext::base_instance_support = false;
GLContext::clear_texture_support = false;
GLContext::copy_image_support = false;
GLContext::debug_layer_support = false;
GLContext::direct_state_access_support = false;
GLContext::fixed_restart_index_support = false;
GLContext::multi_bind_support = false;
GLContext::multi_draw_indirect_support = false;
GLContext::shader_draw_parameters_support = false;
GLContext::texture_cube_map_array_support = false;
GLContext::texture_filter_anisotropic_support = false;
GLContext::texture_gather_support = false;
GLContext::vertex_attrib_binding_support = false;
return;
}
@ -268,7 +277,7 @@ static void detect_workarounds(void)
* 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;
GLContext::copy_image_support = false;
}
/* Special fix for theses specific GPUs.
* Without this workaround, blender crashes on startup. (see T72098) */
@ -305,6 +314,11 @@ static void detect_workarounds(void)
strstr(version, "Mesa 19.1") || strstr(version, "Mesa 19.2"))) {
GLContext::unused_fb_slot_workaround = true;
}
/* There is a bug on older Nvidia GPU where GL_ARB_texture_gather
* is reported to be supported but yield a compile error (see T55802). */
if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) && !GLEW_VERSION_4_0) {
GLContext::texture_gather_support = false;
}
/* dFdx/dFdy calculation factors, those are dependent on driver. */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) &&
@ -323,6 +337,11 @@ static void detect_workarounds(void)
GLContext::derivative_signs[1] = 1.0;
}
}
/* Disable multidraw if the base instance cannot be read. */
if (GLContext::shader_draw_parameters_support == false) {
GLContext::multi_draw_indirect_support = false;
}
/* Enable our own incomplete debug layer if no other is available. */
if (GLContext::debug_layer_support == false) {
GLContext::debug_layer_workaround = true;
@ -336,11 +355,20 @@ GLint GLContext::max_ubo_size;
GLint GLContext::max_ubo_binds;
/** Extensions. */
bool GLContext::base_instance_support = false;
bool GLContext::clear_texture_support = false;
bool GLContext::copy_image_support = false;
bool GLContext::debug_layer_support = false;
bool GLContext::direct_state_access_support = false;
bool GLContext::fixed_restart_index_support = false;
bool GLContext::multi_bind_support = false;
bool GLContext::multi_draw_indirect_support = false;
bool GLContext::shader_draw_parameters_support = false;
bool GLContext::texture_cube_map_array_support = false;
bool GLContext::texture_filter_anisotropic_support = false;
bool GLContext::texture_gather_support = false;
bool GLContext::vertex_attrib_binding_support = false;
/** Workarounds. */
bool GLContext::debug_layer_workaround = false;
bool GLContext::texture_copy_workaround = false;
bool GLContext::unused_fb_slot_workaround = false;
float GLContext::derivative_signs[2] = {1.0f, 1.0f};
@ -361,8 +389,18 @@ void GLBackend::capabilities_init(void)
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;
GLContext::clear_texture_support = GLEW_ARB_clear_texture;
GLContext::copy_image_support = GLEW_ARB_copy_image;
GLContext::debug_layer_support = GLEW_VERSION_4_3 || GLEW_KHR_debug || GLEW_ARB_debug_output;
GLContext::direct_state_access_support = GLEW_ARB_direct_state_access;
GLContext::fixed_restart_index_support = GLEW_ARB_ES3_compatibility;
GLContext::multi_bind_support = GLEW_ARB_multi_bind;
GLContext::multi_draw_indirect_support = GLEW_ARB_multi_draw_indirect;
GLContext::shader_draw_parameters_support = GLEW_ARB_shader_draw_parameters;
GLContext::texture_cube_map_array_support = GLEW_ARB_texture_cube_map_array;
GLContext::texture_filter_anisotropic_support = GLEW_EXT_texture_filter_anisotropic;
GLContext::texture_gather_support = GLEW_ARB_texture_gather;
GLContext::vertex_attrib_binding_support = GLEW_ARB_vertex_attrib_binding;
detect_workarounds();

View File

@ -307,7 +307,7 @@ void GLBatch::bind(int i_first)
#if GPU_TRACK_INDEX_RANGE
/* Can be removed if GL 4.3 is required. */
if (!GLEW_ARB_ES3_compatibility && (elem != NULL)) {
if (!GLContext::fixed_restart_index_support && (elem != NULL)) {
glPrimitiveRestartIndex(this->elem_()->restart_index());
}
#endif

View File

@ -62,11 +62,20 @@ class GLContext : public Context {
static GLint max_ubo_binds;
/** Extensions. */
static bool base_instance_support;
static bool clear_texture_support;
static bool copy_image_support;
static bool debug_layer_support;
static bool direct_state_access_support;
static bool fixed_restart_index_support;
static bool multi_bind_support;
static bool multi_draw_indirect_support;
static bool shader_draw_parameters_support;
static bool texture_cube_map_array_support;
static bool texture_filter_anisotropic_support;
static bool texture_gather_support;
static bool vertex_attrib_binding_support;
/** Workarounds. */
static bool debug_layer_workaround;
static bool texture_copy_workaround;
static bool unused_fb_slot_workaround;
static float derivative_signs[2];

View File

@ -41,8 +41,6 @@
#include <limits.h>
#define USE_MULTI_DRAW_INDIRECT 1
using namespace blender::gpu;
typedef struct GLDrawCommand {
@ -75,8 +73,7 @@ GLDrawList::GLDrawList(int length)
data_size_ = 0;
data_ = NULL;
if (USE_MULTI_DRAW_INDIRECT && GLEW_ARB_multi_draw_indirect &&
GLContext::base_instance_support) {
if (GLContext::multi_draw_indirect_support) {
/* Alloc the biggest possible command list, which is indexed. */
buffer_size_ = sizeof(GLDrawCommandIndexed) * length;
}

View File

@ -85,25 +85,15 @@ char *GLShader::glsl_patch_get(void)
/* Enable extensions for features that are not part of our base GLSL version
* don't use an extension for something already available! */
if (GLEW_ARB_texture_gather) {
/* There is a bug on older Nvidia GPU where GL_ARB_texture_gather
* is reported to be supported but yield a compile error (see T55802). */
if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) || GLEW_VERSION_4_0) {
STR_CONCAT(patch, slen, "#extension GL_ARB_texture_gather: enable\n");
/* Some drivers don't agree on GLEW_ARB_texture_gather and the actual support in the
* shader so double check the preprocessor define (see T56544). */
if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) && !GLEW_VERSION_4_0) {
STR_CONCAT(patch, slen, "#ifdef GL_ARB_texture_gather\n");
STR_CONCAT(patch, slen, "# define GPU_ARB_texture_gather\n");
STR_CONCAT(patch, slen, "#endif\n");
}
else {
STR_CONCAT(patch, slen, "#define GPU_ARB_texture_gather\n");
}
}
if (GLContext::texture_gather_support) {
STR_CONCAT(patch, slen, "#extension GL_ARB_texture_gather: enable\n");
/* Some drivers don't agree on GLEW_ARB_texture_gather and the actual support in the
* shader so double check the preprocessor define (see T56544). */
STR_CONCAT(patch, slen, "#ifdef GL_ARB_texture_gather\n");
STR_CONCAT(patch, slen, "# define GPU_ARB_texture_gather\n");
STR_CONCAT(patch, slen, "#endif\n");
}
if (GLEW_ARB_shader_draw_parameters) {
if (GLContext::shader_draw_parameters_support) {
STR_CONCAT(patch, slen, "#extension GL_ARB_shader_draw_parameters : enable\n");
STR_CONCAT(patch, slen, "#define GPU_ARB_shader_draw_parameters\n");
}

View File

@ -56,7 +56,7 @@ GLStateManager::GLStateManager(void) : GPUStateManager()
glPrimitiveRestartIndex((GLuint)0xFFFFFFFF);
/* TODO: Should become default. But needs at least GL 4.3 */
if (GLEW_ARB_ES3_compatibility) {
if (GLContext::fixed_restart_index_support) {
/* Takes precedence over #GL_PRIMITIVE_RESTART. */
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
}
@ -454,7 +454,6 @@ void GLStateManager::texture_bind(Texture *tex_, eGPUSamplerState sampler_type,
/* Bind the texture to slot 0 for editing purpose. Used by legacy pipeline. */
void GLStateManager::texture_bind_temp(GLTexture *tex)
{
// BLI_assert(!GLEW_ARB_direct_state_access);
glActiveTexture(GL_TEXTURE0);
glBindTexture(tex->target_, tex->tex_id_);
/* Will reset the first texture that was originally bound to slot 0 back before drawing. */
@ -506,7 +505,7 @@ void GLStateManager::texture_bind_apply(void)
int last = 64 - bitscan_reverse_uint64(dirty_bind);
int count = last - first;
if (GLEW_ARB_multi_bind) {
if (GLContext::multi_bind_support) {
glBindTextures(first, count, textures_ + first);
glBindSamplers(first, count, samplers_ + first);
}

View File

@ -89,7 +89,7 @@ bool GLTexture::init_internal(void)
this->ensure_mipmaps(0);
/* Avoid issue with incomplete textures. */
if (GLEW_ARB_direct_state_access) {
if (GLContext::direct_state_access_support) {
glTextureParameteri(tex_id_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else {
@ -111,7 +111,7 @@ bool GLTexture::init_internal(GPUVertBuf *vbo)
GLenum internal_format = to_gl_internal_format(format_);
if (GLEW_ARB_direct_state_access) {
if (GLContext::direct_state_access_support) {
glTextureBuffer(tex_id_, internal_format, gl_vbo->vbo_id_);
}
else {
@ -244,8 +244,8 @@ void GLTexture::update_sub(
GLenum gl_format = to_gl_data_format(format_);
GLenum gl_type = to_gl(type);
/* Some drivers have issues with cubemap & glTextureSubImage3D even if it correct. */
if (GLEW_ARB_direct_state_access && (type_ != GPU_TEXTURE_CUBE)) {
/* Some drivers have issues with cubemap & glTextureSubImage3D even if it is correct. */
if (GLContext::direct_state_access_support && (type_ != GPU_TEXTURE_CUBE)) {
this->update_sub_direct_state_access(mip, offset, extent, gl_format, gl_type, data);
return;
}
@ -306,7 +306,7 @@ void GLTexture::generate_mipmap(void)
}
/* Downsample from mip 0 using implementation. */
if (GLEW_ARB_direct_state_access) {
if (GLContext::direct_state_access_support) {
glGenerateTextureMipmap(tex_id_);
}
else {
@ -319,7 +319,7 @@ void GLTexture::clear(eGPUDataFormat data_format, const void *data)
{
BLI_assert(validate_data_format(format_, data_format));
if (GLEW_ARB_clear_texture && !(G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS)) {
if (GLContext::clear_texture_support) {
int mip = 0;
GLenum gl_format = to_gl_data_format(format_);
GLenum gl_type = to_gl(data_format);
@ -348,8 +348,7 @@ void GLTexture::copy_to(Texture *dst_)
/* TODO support array / 3D textures. */
BLI_assert(dst->d_ == 0);
if (GLEW_ARB_copy_image && !GLContext::texture_copy_workaround) {
/* Opengl 4.3 */
if (GLContext::copy_image_support) {
int mip = 0;
/* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
int extent[3] = {1, 1, 1};
@ -385,7 +384,7 @@ void *GLTexture::read(int mip, eGPUDataFormat type)
GLenum gl_format = to_gl_data_format(format_);
GLenum gl_type = to_gl(type);
if (GLEW_ARB_direct_state_access) {
if (GLContext::direct_state_access_support) {
glGetTextureImage(tex_id_, mip, gl_format, gl_type, texture_size, data);
}
else {
@ -416,7 +415,7 @@ void GLTexture::swizzle_set(const char swizzle[4])
(GLint)swizzle_to_gl(swizzle[1]),
(GLint)swizzle_to_gl(swizzle[2]),
(GLint)swizzle_to_gl(swizzle[3])};
if (GLEW_ARB_direct_state_access) {
if (GLContext::direct_state_access_support) {
glTextureParameteriv(tex_id_, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle);
}
else {
@ -430,7 +429,7 @@ void GLTexture::mip_range_set(int min, int max)
BLI_assert(min <= max && min >= 0 && max <= mipmaps_);
mip_min_ = min;
mip_max_ = max;
if (GLEW_ARB_direct_state_access) {
if (GLContext::direct_state_access_support) {
glTextureParameteri(tex_id_, GL_TEXTURE_BASE_LEVEL, min);
glTextureParameteri(tex_id_, GL_TEXTURE_MAX_LEVEL, max);
}
@ -520,7 +519,7 @@ void GLTexture::samplers_init(void)
void GLTexture::samplers_update(void)
{
if (!GLEW_EXT_texture_filter_anisotropic) {
if (!GLContext::texture_filter_anisotropic_support) {
return;
}

View File

@ -135,7 +135,7 @@ void GLVertArray::update_bindings(const GLuint vao,
}
}
if (attr_mask != 0 && GLEW_ARB_vertex_attrib_binding) {
if (attr_mask != 0 && GLContext::vertex_attrib_binding_support) {
for (uint16_t mask = 1, a = 0; a < 16; a++, mask <<= 1) {
if (attr_mask & mask) {
GLContext *ctx = GLContext::get();