From 2d084d4ec430ec8b280a52286eeeca770f2221bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 22 Oct 2018 12:58:11 +0200 Subject: 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). --- source/blender/gpu/intern/gpu_extensions.c | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'source/blender/gpu/intern/gpu_extensions.c') 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"))) { -- cgit v1.2.3