diff options
-rw-r--r-- | source/blender/gpu/GPU_extensions.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.c | 42 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.c | 6 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 25 |
4 files changed, 66 insertions, 8 deletions
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 1059ba06953..994f545eb38 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -51,6 +51,7 @@ int GPU_max_ubo_binds(void); int GPU_max_ubo_size(void); int GPU_color_depth(void); void GPU_get_dfdy_factors(float fac[2]); +bool GPU_mip_render_workaround(void); bool GPU_mem_stats_supported(void); void GPU_mem_stats_get(int *totalmem, int *freemem); 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"))) { diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index 346d1320b75..7329eee44b0 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -640,11 +640,15 @@ void GPU_framebuffer_recursive_downsample( for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { if (fb->attachments[type].tex != NULL) { + /* Some Intel HDXXX have issue with rendering to a mipmap that is below + * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case + * we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */ + int next_lvl = (GPU_mip_render_workaround()) ? i : i - 1; /* bind next level for rendering but first restrict fetches only to previous level */ GPUTexture *tex = fb->attachments[type].tex; GPU_texture_bind(tex, 0); glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1); + glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, next_lvl); GPU_texture_unbind(tex); /* copy attachment and replace miplevel. */ GPUAttachment attachment = fb->attachments[type]; diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 6a8e686afb3..c3a1148a360 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -916,12 +916,13 @@ GPUTexture *GPU_texture_create_cube( const int channels = gpu_get_component_count(tex_format); if (fpixels) { - fpixels_px = fpixels + 0 * w * w * channels; - fpixels_nx = fpixels + 1 * w * w * channels; - fpixels_py = fpixels + 2 * w * w * channels; - fpixels_ny = fpixels + 3 * w * w * channels; - fpixels_pz = fpixels + 4 * w * w * channels; - fpixels_nz = fpixels + 5 * w * w * channels; + int face_ofs = w * w * channels; + fpixels_px = fpixels + 0 * face_ofs; + fpixels_nx = fpixels + 1 * face_ofs; + fpixels_py = fpixels + 2 * face_ofs; + fpixels_ny = fpixels + 3 * face_ofs; + fpixels_pz = fpixels + 4 * face_ofs; + fpixels_nz = fpixels + 5 * face_ofs; } else { fpixels_px = fpixels_py = fpixels_pz = fpixels_nx = fpixels_ny = fpixels_nz = NULL; @@ -1099,6 +1100,7 @@ void *GPU_texture_read(GPUTexture *tex, GPUDataFormat gpu_data_format, int miplv samples_count *= size[0]; samples_count *= max_ii(1, size[1]); samples_count *= max_ii(1, size[2]); + samples_count *= (GPU_texture_cube(tex)) ? 6 : 1; switch (gpu_data_format) { case GPU_DATA_FLOAT: @@ -1123,7 +1125,16 @@ void *GPU_texture_read(GPUTexture *tex, GPUDataFormat gpu_data_format, int miplv glBindTexture(tex->target, tex->bindcode); - glGetTexImage(tex->target, miplvl, data_format, data_type, buf); + if (GPU_texture_cube(tex)) { + int cube_face_size = buf_size / 6; + for (int i = 0; i < 6; ++i) { + glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, miplvl, data_format, data_type, + ((char *)buf) + cube_face_size * i); + } + } + else { + glGetTexImage(tex->target, miplvl, data_format, data_type, buf); + } glBindTexture(tex->target, 0); |