From f2e96c2473a2c638faeea6bd5544d4dcdccc8a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Tue, 21 Sep 2021 16:38:25 +0200 Subject: Fix T87801: Eevee ambient occlusion is incorrect on M1 macMini The issue was caused by `textureSize()` returning the size of the level 0 even when the min texture level is higher than 0. Using a uniform to pass the correct size fixes the issue. This issue also affected the downsampling of radiance for reflections and refractions. This does not affect anything other than the recusive downsampling shaders. --- source/blender/draw/engines/eevee/eevee_effects.c | 24 +++++++++++++++++----- .../eevee/shaders/effect_downsample_frag.glsl | 13 ++++++++---- .../engines/eevee/shaders/effect_minmaxz_frag.glsl | 19 ++++++++++------- 3 files changed, 40 insertions(+), 16 deletions(-) (limited to 'source') diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 3a38edecec6..d5960ea57d5 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -38,7 +38,8 @@ static struct { struct GPUTexture *color_src; int depth_src_layer; - float cube_texel_size; + /* Size can be vec3. But we only use 2 components in the shader. */ + float texel_size[2]; } e_data = {NULL}; /* Engine data */ #define SETUP_BUFFER(tex, fb, fb_color) \ @@ -259,6 +260,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_PASS_CREATE(psl->color_downsample_ps, DRW_STATE_WRITE_COLOR); grp = DRW_shgroup_create(EEVEE_shaders_effect_downsample_sh_get(), psl->color_downsample_ps); DRW_shgroup_uniform_texture_ex(grp, "source", txl->filtered_radiance, GPU_SAMPLER_FILTER); + DRW_shgroup_uniform_vec2(grp, "texelSize", e_data.texel_size, 1); DRW_shgroup_call_procedural_triangles(grp, NULL, 1); } @@ -267,7 +269,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) grp = DRW_shgroup_create(EEVEE_shaders_effect_downsample_cube_sh_get(), psl->color_downsample_cube_ps); DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src); - DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1); + DRW_shgroup_uniform_float(grp, "texelSize", e_data.texel_size, 1); DRW_shgroup_uniform_int_copy(grp, "Layer", 0); DRW_shgroup_call_instances(grp, NULL, quad, 6); } @@ -277,6 +279,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_PASS_CREATE(psl->maxz_downlevel_ps, downsample_write); grp = DRW_shgroup_create(EEVEE_shaders_effect_maxz_downlevel_sh_get(), psl->maxz_downlevel_ps); DRW_shgroup_uniform_texture_ref_ex(grp, "depthBuffer", &txl->maxzbuffer, GPU_SAMPLER_DEFAULT); + DRW_shgroup_uniform_vec2(grp, "texelSize", e_data.texel_size, 1); DRW_shgroup_call(grp, quad, NULL); /* Copy depth buffer to top level of HiZ */ @@ -345,16 +348,22 @@ static void min_downsample_cb(void *vedata, int UNUSED(level)) } #endif -static void max_downsample_cb(void *vedata, int UNUSED(level)) +static void max_downsample_cb(void *vedata, int level) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl; + int texture_size[3]; + GPU_texture_get_mipmap_size(txl->maxzbuffer, level - 1, texture_size); + e_data.texel_size[0] = 1.0f / texture_size[0]; + e_data.texel_size[1] = 1.0f / texture_size[1]; DRW_draw_pass(psl->maxz_downlevel_ps); } static void simple_downsample_cube_cb(void *vedata, int level) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; - e_data.cube_texel_size = (float)(1 << level) / (float)GPU_texture_width(e_data.color_src); + e_data.texel_size[0] = (float)(1 << level) / (float)GPU_texture_width(e_data.color_src); + e_data.texel_size[1] = e_data.texel_size[0]; DRW_draw_pass(psl->color_downsample_cube_ps); } @@ -390,9 +399,14 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int l } } -static void downsample_radiance_cb(void *vedata, int UNUSED(level)) +static void downsample_radiance_cb(void *vedata, int level) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl; + int texture_size[3]; + GPU_texture_get_mipmap_size(txl->filtered_radiance, level - 1, texture_size); + e_data.texel_size[0] = 1.0f / texture_size[0]; + e_data.texel_size[1] = 1.0f / texture_size[1]; DRW_draw_pass(psl->color_downsample_ps); } diff --git a/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl index d1cb25af82f..9fc258da185 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl @@ -9,14 +9,16 @@ uniform sampler2D source; uniform float fireflyFactor; +#ifndef COPY_SRC +uniform vec2 texelSize; +#endif + out vec4 FragColor; void main() { - vec2 texel_size = 1.0 / vec2(textureSize(source, 0)); - vec2 uvs = gl_FragCoord.xy * texel_size; - #ifdef COPY_SRC + vec2 uvs = gl_FragCoord.xy / vec2(textureSize(source, 0)); FragColor = textureLod(source, uvs, 0.0); FragColor = safe_color(FragColor); @@ -25,7 +27,10 @@ void main() FragColor *= 1.0 - max(0.0, luma - fireflyFactor) / luma; #else - vec4 ofs = texel_size.xyxy * vec4(0.75, 0.75, -0.75, -0.75); + /* NOTE(@fclem): textureSize() does not work the same on all implementations + * when changing the min and max texture levels. Use uniform instead (see T87801). */ + vec2 uvs = gl_FragCoord.xy * texelSize; + vec4 ofs = texelSize.xyxy * vec4(0.75, 0.75, -0.75, -0.75); uvs *= 2.0; FragColor = textureLod(source, uvs + ofs.xy, 0.0); diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl index ccb65d2e5a6..8ef39a55921 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl @@ -14,6 +14,10 @@ uniform int depthLayer; uniform sampler2D depthBuffer; #endif +#ifndef COPY_DEPTH +uniform vec2 texelSize; +#endif + #ifdef LAYERED # define sampleLowerMip(t) texture(depthBuffer, vec3(t, depthLayer)).r # define gatherLowerMip(t) textureGather(depthBuffer, vec3(t, depthLayer)) @@ -41,23 +45,24 @@ out vec4 fragColor; void main() { vec2 texel = gl_FragCoord.xy; - vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); #ifdef COPY_DEPTH - vec2 uv = texel * texel_size; + vec2 uv = texel / vec2(textureSize(depthBuffer, 0).xy); float val = sampleLowerMip(uv); #else - vec2 uv = texel * 2.0 * texel_size; + /* NOTE(@fclem): textureSize() does not work the same on all implementations + * when changing the min and max texture levels. Use uniform instead (see T87801). */ + vec2 uv = texel * 2.0 * texelSize; vec4 samp; # ifdef GPU_ARB_texture_gather samp = gatherLowerMip(uv); # else - samp.x = sampleLowerMip(uv + vec2(-0.5, -0.5) * texel_size); - samp.y = sampleLowerMip(uv + vec2(-0.5, 0.5) * texel_size); - samp.z = sampleLowerMip(uv + vec2(0.5, -0.5) * texel_size); - samp.w = sampleLowerMip(uv + vec2(0.5, 0.5) * texel_size); + samp.x = sampleLowerMip(uv + vec2(-0.5, -0.5) * texelSize); + samp.y = sampleLowerMip(uv + vec2(-0.5, 0.5) * texelSize); + samp.z = sampleLowerMip(uv + vec2(0.5, -0.5) * texelSize); + samp.w = sampleLowerMip(uv + vec2(0.5, 0.5) * texelSize); # endif float val = minmax4(samp.x, samp.y, samp.z, samp.w); -- cgit v1.2.3