mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-24 21:28:10 +02:00
Applications often miss emitting barriers between a shader initializing data & another shader writing data in the same location afterward. This is very common for UAVs (see vkd3d-proton). Vkd3d-proton does a pretty good job as inserting missing barriers between UAV clears & writes. But some applications also have similar issues with custom shaders. Here we introduce an analysis pass that recognize shaders doing clear/initialization. We'll use that information in the following commit to insert barriers after those shaders. Since Gfx12.5 our HW has become a lot more sensitive to those issues due to the introduction of an L1 untyped data cache that is not coherent across the shader units. On Gfx20+, typed data is also L1 cacheable exposing even more issues. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Cc: mesa-stable Reviewed-by: Ivan Briano <ivan.briano@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40187>
98 lines
2.7 KiB
C
98 lines
2.7 KiB
C
/* Copyright © 2026 Intel Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "anv_private.h"
|
|
#include "anv_nir.h"
|
|
|
|
#include "nir/nir_builder.h"
|
|
|
|
/**
|
|
* This file implements an analysis pass to detect shaders we assume are
|
|
* clearing/initializing some memory.
|
|
*
|
|
* The criteria for such shader is that all memory store operations are
|
|
* writing constant values.
|
|
*/
|
|
|
|
struct clear_state {
|
|
uint32_t n_image_store;
|
|
uint32_t n_image_store_const;
|
|
|
|
uint32_t n_ssbo_store;
|
|
uint32_t n_ssbo_store_const;
|
|
|
|
uint32_t n_global_store;
|
|
uint32_t n_global_store_const;
|
|
};
|
|
|
|
static bool
|
|
intrin_analysis(nir_builder *b, nir_intrinsic_instr *intrin, void *data)
|
|
{
|
|
struct clear_state *state = data;
|
|
switch (intrin->intrinsic) {
|
|
case nir_intrinsic_image_store:
|
|
case nir_intrinsic_bindless_image_store:
|
|
state->n_image_store++;
|
|
if (nir_src_is_const(intrin->src[nir_get_io_data_src_number(intrin)]))
|
|
state->n_image_store_const++;
|
|
return true;
|
|
|
|
case nir_intrinsic_image_atomic:
|
|
case nir_intrinsic_image_atomic_swap:
|
|
case nir_intrinsic_bindless_image_atomic:
|
|
case nir_intrinsic_bindless_image_atomic_swap:
|
|
state->n_image_store++;
|
|
return true;
|
|
|
|
case nir_intrinsic_store_ssbo:
|
|
state->n_ssbo_store++;
|
|
if (nir_src_is_const(intrin->src[nir_get_io_data_src_number(intrin)]))
|
|
state->n_ssbo_store_const++;
|
|
return true;
|
|
|
|
case nir_intrinsic_ssbo_atomic:
|
|
state->n_ssbo_store++;
|
|
return true;
|
|
|
|
case nir_intrinsic_store_global:
|
|
state->n_global_store++;
|
|
if (nir_src_is_const(intrin->src[nir_get_io_data_src_number(intrin)]))
|
|
state->n_global_store_const++;
|
|
return true;
|
|
|
|
case nir_intrinsic_global_atomic:
|
|
state->n_global_store++;
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
enum anv_pipeline_behavior
|
|
anv_nir_clear_shader_analysis(nir_shader *shader)
|
|
{
|
|
struct clear_state state = {};
|
|
|
|
nir_shader_intrinsics_pass(shader, intrin_analysis, nir_metadata_all, &state);
|
|
|
|
/* If something doesn't write a constant, assume no behavior. */
|
|
if (state.n_image_store != state.n_image_store_const ||
|
|
state.n_ssbo_store != state.n_ssbo_store_const ||
|
|
state.n_global_store != state.n_global_store_const)
|
|
return 0;
|
|
|
|
enum anv_pipeline_behavior behavior = 0;
|
|
if (state.n_image_store > 0 &&
|
|
state.n_image_store == state.n_image_store_const)
|
|
behavior |= ANV_PIPELINE_BEHAVIOR_CLEAR_TYPED;
|
|
if (state.n_ssbo_store > 0 &&
|
|
state.n_ssbo_store == state.n_ssbo_store_const)
|
|
behavior |= ANV_PIPELINE_BEHAVIOR_CLEAR_UNTYPED;
|
|
if (state.n_global_store > 0 &&
|
|
state.n_global_store == state.n_global_store_const)
|
|
behavior |= ANV_PIPELINE_BEHAVIOR_CLEAR_UNTYPED;
|
|
|
|
return behavior;
|
|
}
|