From 6b56ed3cd32ee094ee216c11e49b8d4a2d43b222 Mon Sep 17 00:00:00 2001 From: Jason Fielder Date: Thu, 14 Mar 2024 17:48:30 +0100 Subject: [PATCH] Metal: Resolve artifact in EEVEE Next Film Cryptomatte Cryptomatte passes would generate a feathered outline in Metal due to missing texture fence in chained read->modify->write->read->... patterns. Added imageFence function to explicitly state that imageStore's should be visible to future imageLoad's. Authored by Apple: Michael Parkin-White Pull Request: https://projects.blender.org/blender/blender/pulls/119163 --- .../eevee_next/shaders/eevee_cryptomatte_lib.glsl | 4 ++++ .../shaders/eevee_film_cryptomatte_post_comp.glsl | 2 ++ .../engines/eevee_next/shaders/eevee_film_lib.glsl | 11 ----------- .../blender/gpu/shaders/metal/mtl_shader_defines.msl | 3 +++ .../gpu/shaders/opengl/glsl_shader_defines.glsl | 3 +++ 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl index 706b9365941..a5578c872e8 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl @@ -34,6 +34,8 @@ void cryptomatte_clear_samples(FilmSample dst) int layer_len = imageSize(cryptomatte_img).z; for (int i = 0; i < layer_len; i++) { imageStore(cryptomatte_img, ivec3(dst.texel, i), vec4(0.0)); + /* Ensure stores are visible to later reads. */ + imageFence(cryptomatte_img); } } @@ -71,4 +73,6 @@ void cryptomatte_store_film_sample(FilmSample dst, imageStore(cryptomatte_img, img_co, sample_pair); break; } + /* Ensure stores are visible to later reads. */ + imageFence(cryptomatte_img); } diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl index 5a77f525e3f..490abb65a4d 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl @@ -61,6 +61,8 @@ void cryptomatte_store_samples(ivec2 texel, int layer, vec2 samples[CRYPTOMATTE_ pass_sample.zw = samples[p * 2 + 1]; imageStore(cryptomatte_img, ivec3(texel, p + layer_id), pass_sample); } + /* Ensure stores are visible to later reads. */ + imageFence(cryptomatte_img); } void main() diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl index ced00efdda2..acb2d1e3862 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl @@ -142,17 +142,10 @@ void film_sample_accum_combined(FilmSample samp, inout vec4 accum, inout float w weight_accum += weight; } -#ifdef GPU_METAL -void film_sample_cryptomatte_accum(FilmSample samp, - int layer, - sampler2D tex, - thread vec2 *crypto_samples) -#else void film_sample_cryptomatte_accum(FilmSample samp, int layer, sampler2D tex, inout vec2 crypto_samples[4]) -#endif { float hash = texelFetch(tex, samp.texel, 0)[layer]; /* Find existing entry. */ @@ -247,11 +240,7 @@ vec2 film_pixel_history_motion_vector(ivec2 texel_sample) /* \a t is inter-pixel position. 0 means perfectly on a pixel center. * Returns weights in both dimensions. * Multiply each dimension weights to get final pixel weights. */ -#ifdef GPU_METAL -void film_get_catmull_rom_weights(vec2 t, thread vec2 *weights) -#else void film_get_catmull_rom_weights(vec2 t, out vec2 weights[4]) -#endif { vec2 t2 = t * t; vec2 t3 = t2 * t; diff --git a/source/blender/gpu/shaders/metal/mtl_shader_defines.msl b/source/blender/gpu/shaders/metal/mtl_shader_defines.msl index d633666adff..645e5146f9a 100644 --- a/source/blender/gpu/shaders/metal/mtl_shader_defines.msl +++ b/source/blender/gpu/shaders/metal/mtl_shader_defines.msl @@ -366,6 +366,9 @@ struct SStruct { #define imageStore(_tex, _coord, _value) _texture_write_internal(_tex, _coord, _value) #define imageStoreFast(_tex, _coord, _value) _texture_write_internal_fast(_tex, _coord, _value) +/* Texture synchronization functions. */ +#define imageFence(image) image.texture->fence() + /* Singular return values from texture functions of type DEPTH are often indexed with either .r or * .x. This is a lightweight wrapper type for handling this syntax. */ union _msl_return_float { diff --git a/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl b/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl index 14755066c5a..d65c81bda30 100644 --- a/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl +++ b/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl @@ -83,6 +83,9 @@ #define isampler2DAtomic isampler2D #define isampler3DAtomic isampler3D +/* Pass through functions. */ +#define imageFence(image) + /* Backend Functions. */ #define select(A, B, mask) mix(A, B, mask)