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.
This commit is contained in:
Clément Foucault 2021-09-21 16:38:25 +02:00 committed by Jeroen Bakker
parent 934c724755
commit f2e96c2473
Notes: blender-bot 2023-02-14 09:38:57 +01:00
Referenced by issue #88449, Blender LTS: Maintenance Task 2.93
Referenced by issue #87801, Eevee ambient occlusion is incorrect on M1 macMini
3 changed files with 40 additions and 16 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);