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
This commit is contained in:
Jason Fielder
2024-03-14 17:48:30 +01:00
committed by Clément Foucault
parent 8b01578826
commit 6b56ed3cd3
5 changed files with 12 additions and 11 deletions

View File

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

View File

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

View File

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

View File

@@ -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 {

View File

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