diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-10-22 13:58:11 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-10-22 14:00:40 +0300 |
commit | 2d084d4ec430ec8b280a52286eeeca770f2221bc (patch) | |
tree | 2436fda8529effee889b423fabb065826a791307 /source/blender/gpu/intern/gpu_extensions.c | |
parent | 0e70feab22fd0871d61a03b43c591fb300990de7 (diff) |
GPU: Fix Issue with recursive downsample and Intel HDXXX
This is caused by a driver bug that prevent us from rendering to (or even
binding) a texture mip level that is below GL_TEXTURE_MAX_LEVEL of the
target texture. This is fine in most drivers (and legal AFAIK) but not on
thoses Intels HDXXX + Windows.
As a fix we just put GL_TEXTURE_MAX_LEVEL lower (which is illegal because
it is undefined behaviour), but in practice it works ok and does not
trigger any warnings or errors.
This commit fixes most of the problems encountered on these GPUs (T56668).
Diffstat (limited to 'source/blender/gpu/intern/gpu_extensions.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 198f986d06e..c95f5e5e252 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -37,8 +37,10 @@ #include "BLI_math_vector.h" #include "BKE_global.h" +#include "MEM_guardedalloc.h" #include "GPU_extensions.h" +#include "GPU_framebuffer.h" #include "GPU_glew.h" #include "GPU_texture.h" @@ -83,8 +85,42 @@ static struct GPUGlobal { * number is factor on screen and second is off-screen */ float dfdyfactors[2]; float max_anisotropy; + /* 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; } GG = {1, 0}; + +static void gpu_detect_mip_render_workaround(void) +{ + int cube_size = 2; + float *source_pix = 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(cube_size, GPU_RGBA16F, source_pix, NULL); + 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(); + 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 = 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 Types */ bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver) @@ -154,6 +190,11 @@ void GPU_get_dfdy_factors(float fac[2]) copy_v2_v2(fac, GG.dfdyfactors); } +bool GPU_mip_render_workaround(void) +{ + return GG.mip_render_workaround; +} + void gpu_extensions_init(void) { /* during 2.8 development each platform has its own OpenGL minimum requirements @@ -253,6 +294,7 @@ void gpu_extensions_init(void) GG.os = GPU_OS_UNIX; #endif + gpu_detect_mip_render_workaround(); /* df/dy calculation factors, those are dependent on driver */ if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) { |