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.
This commit is contained in:
@@ -721,7 +721,6 @@ void DRW_state_lock(DRWState state);
|
|||||||
void DRW_select_load_id(uint id);
|
void DRW_select_load_id(uint id);
|
||||||
|
|
||||||
/* Draw State */
|
/* Draw State */
|
||||||
void DRW_state_dfdy_factors_get(float dfdyfac[2]);
|
|
||||||
bool DRW_state_is_fbo(void);
|
bool DRW_state_is_fbo(void);
|
||||||
bool DRW_state_is_select(void);
|
bool DRW_state_is_select(void);
|
||||||
bool DRW_state_is_depth(void);
|
bool DRW_state_is_depth(void);
|
||||||
|
@@ -2496,11 +2496,6 @@ void DRW_draw_depth_object(
|
|||||||
/** \name Draw Manager State (DRW_state)
|
/** \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
|
* When false, drawing doesn't output to a pixel buffer
|
||||||
* eg: Occlusion queries, or when we have setup a context to draw in already.
|
* eg: Occlusion queries, or when we have setup a context to draw in already.
|
||||||
|
@@ -137,6 +137,7 @@ set(SRC
|
|||||||
intern/gpu_codegen.h
|
intern/gpu_codegen.h
|
||||||
intern/gpu_context_private.hh
|
intern/gpu_context_private.hh
|
||||||
intern/gpu_drawlist_private.hh
|
intern/gpu_drawlist_private.hh
|
||||||
|
intern/gpu_extensions_private.hh
|
||||||
intern/gpu_framebuffer_private.hh
|
intern/gpu_framebuffer_private.hh
|
||||||
intern/gpu_immediate_private.hh
|
intern/gpu_immediate_private.hh
|
||||||
intern/gpu_index_buffer_private.hh
|
intern/gpu_index_buffer_private.hh
|
||||||
|
@@ -41,14 +41,10 @@ int GPU_max_color_texture_samples(void);
|
|||||||
int GPU_max_cube_map_size(void);
|
int GPU_max_cube_map_size(void);
|
||||||
int GPU_max_ubo_binds(void);
|
int GPU_max_ubo_binds(void);
|
||||||
int GPU_max_ubo_size(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_arb_texture_cube_map_array_is_supported(void);
|
||||||
bool GPU_mip_render_workaround(void);
|
bool GPU_mip_render_workaround(void);
|
||||||
bool GPU_depth_blitting_workaround(void);
|
bool GPU_depth_blitting_workaround(void);
|
||||||
bool GPU_unused_fb_slot_workaround(void);
|
|
||||||
bool GPU_use_main_context_workaround(void);
|
bool GPU_use_main_context_workaround(void);
|
||||||
bool GPU_texture_copy_workaround(void);
|
|
||||||
bool GPU_crappy_amd_driver(void);
|
bool GPU_crappy_amd_driver(void);
|
||||||
|
|
||||||
int GPU_texture_size_with_limit(int res);
|
int GPU_texture_size_with_limit(int res);
|
||||||
|
@@ -24,214 +24,29 @@
|
|||||||
* with checks for drivers and GPU support.
|
* 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 "DNA_userdef_types.h"
|
||||||
|
|
||||||
#include "GPU_extensions.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 "gpu_extensions_private.hh"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "gl_backend.hh" /* TODO remove */
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef WIN32
|
namespace blender::gpu {
|
||||||
# include "BLI_winstuff.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Extensions support */
|
GPUCapabilities GCaps;
|
||||||
|
|
||||||
/* -- 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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
float *data = (float *)GPU_texture_read(tex, GPU_DATA_FLOAT, 1);
|
|
||||||
GG.mip_render_workaround = !equals_v4v4(clear_color, data);
|
|
||||||
|
|
||||||
MEM_freeN(data);
|
|
||||||
GPU_texture_free(tex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GPU Extensions */
|
using namespace blender::gpu;
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Capabilities
|
||||||
|
* \{ */
|
||||||
|
|
||||||
int GPU_max_texture_size(void)
|
int GPU_max_texture_size(void)
|
||||||
{
|
{
|
||||||
return GG.maxtexsize;
|
return GCaps.max_texture_size;
|
||||||
}
|
|
||||||
|
|
||||||
int GPU_max_texture_3d_size(void)
|
|
||||||
{
|
|
||||||
return GG.maxtex3dsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GPU_max_ubo_size(void)
|
|
||||||
{
|
|
||||||
return GG.maxubosize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPU_get_dfdy_factors(float fac[2])
|
|
||||||
{
|
|
||||||
copy_v2_v2(fac, GG.dfdyfactors);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_arb_base_instance_is_supported(void)
|
|
||||||
{
|
|
||||||
return GG.glew_arb_base_instance_is_supported;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_arb_texture_cube_map_array_is_supported(void)
|
|
||||||
{
|
|
||||||
return GG.glew_arb_texture_cube_map_array_is_supported;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_mip_render_workaround(void)
|
|
||||||
{
|
|
||||||
return GG.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_use_main_context_workaround(void)
|
|
||||||
{
|
|
||||||
return GG.use_main_context_workaround;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_texture_copy_workaround(void)
|
|
||||||
{
|
|
||||||
return GG.texture_copy_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 GPU_texture_size_with_limit(int res)
|
||||||
@@ -241,165 +56,64 @@ int GPU_texture_size_with_limit(int res)
|
|||||||
return min_ii(reslimit, res);
|
return min_ii(reslimit, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpu_extensions_init(void)
|
int GPU_max_texture_layers(void)
|
||||||
{
|
{
|
||||||
/* during 2.8 development each platform has its own OpenGL minimum requirements
|
return GCaps.max_texture_layers;
|
||||||
* 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) &&
|
int GPU_max_textures_vert(void)
|
||||||
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();
|
return GCaps.max_textures_vert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GPU_max_textures_geom(void)
|
||||||
|
{
|
||||||
|
return GCaps.max_textures_geom;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GPU_max_textures_frag(void)
|
||||||
|
{
|
||||||
|
return GCaps.max_textures_frag;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GPU_max_textures(void)
|
||||||
|
{
|
||||||
|
return GCaps.max_textures;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPU_arb_texture_cube_map_array_is_supported(void)
|
||||||
|
{
|
||||||
|
/* FIXME bad level call. */
|
||||||
|
return GLContext::texture_cube_map_array_support;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPU_mip_render_workaround(void)
|
||||||
|
{
|
||||||
|
return GCaps.mip_render_workaround;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPU_depth_blitting_workaround(void)
|
||||||
|
{
|
||||||
|
return GCaps.depth_blitting_workaround;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPU_use_main_context_workaround(void)
|
||||||
|
{
|
||||||
|
return GCaps.use_main_context_workaround;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPU_crappy_amd_driver(void)
|
||||||
|
{
|
||||||
|
/* Currently are the same drivers with the `unused_fb_slot` problem. */
|
||||||
|
return GCaps.broken_amd_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Memory statistics
|
||||||
|
* \{ */
|
||||||
|
|
||||||
bool GPU_mem_stats_supported(void)
|
bool GPU_mem_stats_supported(void)
|
||||||
{
|
{
|
||||||
#ifndef GPU_STANDALONE
|
#ifndef GPU_STANDALONE
|
||||||
@@ -439,3 +153,5 @@ bool GPU_stereo_quadbuffer_support(void)
|
|||||||
glGetBooleanv(GL_STEREO, &stereo);
|
glGetBooleanv(GL_STEREO, &stereo);
|
||||||
return stereo == GL_TRUE;
|
return stereo == GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
54
source/blender/gpu/intern/gpu_extensions_private.hh
Normal file
54
source/blender/gpu/intern/gpu_extensions_private.hh
Normal file
@@ -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
|
@@ -48,7 +48,6 @@ void GPU_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
gpu_extensions_init(); /* must come first */
|
|
||||||
|
|
||||||
gpu_codegen_init();
|
gpu_codegen_init();
|
||||||
gpu_material_library_init();
|
gpu_material_library_init();
|
||||||
@@ -79,8 +78,6 @@ void GPU_exit(void)
|
|||||||
gpu_material_library_exit();
|
gpu_material_library_exit();
|
||||||
gpu_codegen_exit();
|
gpu_codegen_exit();
|
||||||
|
|
||||||
gpu_extensions_exit();
|
|
||||||
|
|
||||||
initialized = false;
|
initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,10 +24,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* call this before running any of the functions below */
|
|
||||||
void gpu_extensions_init(void);
|
|
||||||
void gpu_extensions_exit(void);
|
|
||||||
|
|
||||||
/* gpu_pbvh.c */
|
/* gpu_pbvh.c */
|
||||||
void gpu_pbvh_init(void);
|
void gpu_pbvh_init(void);
|
||||||
void gpu_pbvh_exit(void);
|
void gpu_pbvh_exit(void);
|
||||||
|
@@ -47,7 +47,6 @@ UniformBuf::UniformBuf(size_t size, const char *name)
|
|||||||
{
|
{
|
||||||
/* Make sure that UBO is padded to size of vec4 */
|
/* Make sure that UBO is padded to size of vec4 */
|
||||||
BLI_assert((size % 16) == 0);
|
BLI_assert((size % 16) == 0);
|
||||||
BLI_assert(size <= GPU_max_ubo_size());
|
|
||||||
|
|
||||||
size_in_bytes_ = size;
|
size_in_bytes_ = size;
|
||||||
|
|
||||||
|
@@ -21,6 +21,9 @@
|
|||||||
* \ingroup gpu
|
* \ingroup gpu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "BKE_global.h"
|
||||||
|
|
||||||
|
#include "gpu_extensions_private.hh"
|
||||||
#include "gpu_platform_private.hh"
|
#include "gpu_platform_private.hh"
|
||||||
|
|
||||||
#include "glew-mx.h"
|
#include "glew-mx.h"
|
||||||
@@ -29,6 +32,10 @@
|
|||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Platform
|
||||||
|
* \{ */
|
||||||
|
|
||||||
void GLBackend::platform_init(void)
|
void GLBackend::platform_init(void)
|
||||||
{
|
{
|
||||||
BLI_assert(!GPG.initialized);
|
BLI_assert(!GPG.initialized);
|
||||||
@@ -132,4 +139,217 @@ void GLBackend::platform_exit(void)
|
|||||||
GPG.clear();
|
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
|
} // namespace blender::gpu
|
@@ -50,6 +50,7 @@ class GLBackend : public GPUBackend {
|
|||||||
/* platform_init needs to go first. */
|
/* platform_init needs to go first. */
|
||||||
GLBackend::platform_init();
|
GLBackend::platform_init();
|
||||||
|
|
||||||
|
GLBackend::capabilities_init();
|
||||||
GLTexture::samplers_init();
|
GLTexture::samplers_init();
|
||||||
}
|
}
|
||||||
~GLBackend()
|
~GLBackend()
|
||||||
@@ -127,6 +128,8 @@ class GLBackend : public GPUBackend {
|
|||||||
private:
|
private:
|
||||||
static void platform_init(void);
|
static void platform_init(void);
|
||||||
static void platform_exit(void);
|
static void platform_exit(void);
|
||||||
|
|
||||||
|
static void capabilities_init(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include "gpu_batch_private.hh"
|
#include "gpu_batch_private.hh"
|
||||||
#include "gpu_shader_private.hh"
|
#include "gpu_shader_private.hh"
|
||||||
|
|
||||||
|
#include "gl_backend.hh"
|
||||||
#include "gl_context.hh"
|
#include "gl_context.hh"
|
||||||
#include "gl_debug.hh"
|
#include "gl_debug.hh"
|
||||||
#include "gl_index_buffer.hh"
|
#include "gl_index_buffer.hh"
|
||||||
@@ -314,7 +315,7 @@ void GLBatch::bind(int i_first)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Can be removed if GL 4.2 is required. */
|
/* 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));
|
glBindVertexArray(vao_cache_.base_instance_vao_get(this, i_first));
|
||||||
}
|
}
|
||||||
else {
|
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_;
|
GLint base_index = el->index_base_;
|
||||||
void *v_first_ofs = el->offset_ptr(v_first);
|
void *v_first_ofs = el->offset_ptr(v_first);
|
||||||
|
|
||||||
if (GPU_arb_base_instance_is_supported()) {
|
if (GLContext::base_instance_support) {
|
||||||
glDrawElementsInstancedBaseVertexBaseInstance(
|
glDrawElementsInstancedBaseVertexBaseInstance(
|
||||||
gl_type, v_count, index_type, v_first_ofs, i_count, base_index, i_first);
|
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__
|
#ifdef __APPLE__
|
||||||
glDisable(GL_PRIMITIVE_RESTART);
|
glDisable(GL_PRIMITIVE_RESTART);
|
||||||
#endif
|
#endif
|
||||||
if (GPU_arb_base_instance_is_supported()) {
|
if (GLContext::base_instance_support) {
|
||||||
glDrawArraysInstancedBaseInstance(gl_type, v_first, v_count, i_count, i_first);
|
glDrawArraysInstancedBaseInstance(gl_type, v_first, v_count, i_count, i_first);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -55,6 +55,19 @@ class GLSharedOrphanLists {
|
|||||||
|
|
||||||
class GLContext : public GPUContext {
|
class GLContext : public GPUContext {
|
||||||
public:
|
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. */
|
/** Used for debugging purpose. Bitflags of all bound slots. */
|
||||||
uint16_t bound_ubo_slots;
|
uint16_t bound_ubo_slots;
|
||||||
|
|
||||||
|
@@ -76,7 +76,7 @@ GLDrawList::GLDrawList(int length)
|
|||||||
data_ = NULL;
|
data_ = NULL;
|
||||||
|
|
||||||
if (USE_MULTI_DRAW_INDIRECT && GLEW_ARB_multi_draw_indirect &&
|
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. */
|
/* Alloc the biggest possible command list, which is indexed. */
|
||||||
buffer_size_ = sizeof(GLDrawCommandIndexed) * length;
|
buffer_size_ = sizeof(GLDrawCommandIndexed) * length;
|
||||||
}
|
}
|
||||||
|
@@ -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. */
|
/* Fill normally un-occupied slots to avoid rendering artifacts on some hardware. */
|
||||||
GLuint gl_tex = 0;
|
GLuint gl_tex = 0;
|
||||||
/* NOTE: Inverse iteration to get the first color texture. */
|
/* NOTE: Inverse iteration to get the first color texture. */
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "GPU_extensions.h"
|
#include "GPU_extensions.h"
|
||||||
#include "GPU_platform.h"
|
#include "GPU_platform.h"
|
||||||
|
|
||||||
|
#include "gl_backend.hh"
|
||||||
#include "gl_vertex_buffer.hh"
|
#include "gl_vertex_buffer.hh"
|
||||||
|
|
||||||
#include "gl_shader.hh"
|
#include "gl_shader.hh"
|
||||||
@@ -118,10 +119,8 @@ char *GLShader::glsl_patch_get(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Derivative sign can change depending on implementation. */
|
/* Derivative sign can change depending on implementation. */
|
||||||
float derivatives[2];
|
STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]);
|
||||||
GPU_get_dfdy_factors(derivatives);
|
STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]);
|
||||||
STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", derivatives[0]);
|
|
||||||
STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", derivatives[1]);
|
|
||||||
|
|
||||||
BLI_assert(slen < sizeof(patch));
|
BLI_assert(slen < sizeof(patch));
|
||||||
return patch;
|
return patch;
|
||||||
|
@@ -369,7 +369,7 @@ void GLTexture::copy_to(Texture *dst_)
|
|||||||
/* TODO support array / 3D textures. */
|
/* TODO support array / 3D textures. */
|
||||||
BLI_assert(dst->d_ == 0);
|
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 */
|
/* Opengl 4.3 */
|
||||||
int mip = 0;
|
int mip = 0;
|
||||||
/* NOTE: mip_size_get() won't override any dimension that is equal to 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. */
|
/* Manual validation first, since some implementation have issues with proxy creation. */
|
||||||
int max_size = GPU_max_texture_size();
|
int max_size = GPU_max_texture_size();
|
||||||
int max_3d_size = GPU_max_texture_3d_size();
|
int max_3d_size = GLContext::max_texture_3d_size;
|
||||||
int max_cube_size = GPU_max_cube_map_size();
|
int max_cube_size = GLContext::max_cubemap_size;
|
||||||
int size[3] = {1, 1, 1};
|
int size[3] = {1, 1, 1};
|
||||||
this->mip_size_get(mip, size);
|
this->mip_size_get(mip, size);
|
||||||
|
|
||||||
|
@@ -42,6 +42,7 @@ namespace blender::gpu {
|
|||||||
GLUniformBuf::GLUniformBuf(size_t size, const char *name) : UniformBuf(size, name)
|
GLUniformBuf::GLUniformBuf(size_t size, const char *name) : UniformBuf(size, name)
|
||||||
{
|
{
|
||||||
/* Do not create ubo GL buffer here to allow allocation from any thread. */
|
/* Do not create ubo GL buffer here to allow allocation from any thread. */
|
||||||
|
BLI_assert(size <= GLContext::max_ubo_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLUniformBuf::~GLUniformBuf()
|
GLUniformBuf::~GLUniformBuf()
|
||||||
@@ -90,12 +91,12 @@ void GLUniformBuf::update(const void *data)
|
|||||||
|
|
||||||
void GLUniformBuf::bind(int slot)
|
void GLUniformBuf::bind(int slot)
|
||||||
{
|
{
|
||||||
if (slot >= GPU_max_ubo_binds()) {
|
if (slot >= GLContext::max_ubo_binds) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: Trying to bind \"%s\" ubo to slot %d which is above the reported limit of %d.",
|
"Error: Trying to bind \"%s\" ubo to slot %d which is above the reported limit of %d.",
|
||||||
name_,
|
name_,
|
||||||
slot,
|
slot,
|
||||||
GPU_max_ubo_binds());
|
GLContext::max_ubo_binds);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user