From fe1d84e08372e021bbde92bd9d69b4dcbfc0421e Mon Sep 17 00:00:00 2001 From: Sushma Venkatesh Reddy Date: Fri, 15 Aug 2025 03:06:24 +0000 Subject: [PATCH] intel/compiler: apply sqrt workaround for Horizon Forbidden West shader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added a workaround for a known shader in Horizon Forbidden West that causes visual corruption on Intel anv driver. The fix clamps fsqrt inputs using fmax(x, 1e-12) to avoid invalid values. Integrated the workaround via brw_nir_apply_sqrt_workarounds() and applied it conditionally in the Vulkan pipeline based on the shader's BLAKE3 hash. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12555 Reviewed-by: Kenneth Graunke Reviewed-by: Tapani Pälli Part-of: --- src/intel/compiler/brw_nir.h | 2 + .../compiler/brw_nir_trig_workarounds.py | 6 +++ src/intel/vulkan/anv_shader_compile.c | 54 +++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/src/intel/compiler/brw_nir.h b/src/intel/compiler/brw_nir.h index 90bf060dd91..aaff0f97256 100644 --- a/src/intel/compiler/brw_nir.h +++ b/src/intel/compiler/brw_nir.h @@ -239,6 +239,8 @@ bool brw_nir_apply_trig_workarounds(nir_shader *nir); bool brw_nir_limit_trig_input_range_workaround(nir_shader *nir); +bool brw_nir_apply_sqrt_workarounds(nir_shader *nir); + bool brw_nir_lower_fsign(nir_shader *nir); bool brw_nir_opt_fsat(nir_shader *); diff --git a/src/intel/compiler/brw_nir_trig_workarounds.py b/src/intel/compiler/brw_nir_trig_workarounds.py index 5d6a7601d31..06eb15a5448 100644 --- a/src/intel/compiler/brw_nir_trig_workarounds.py +++ b/src/intel/compiler/brw_nir_trig_workarounds.py @@ -45,6 +45,10 @@ LIMIT_TRIG_INPUT_RANGE_WORKAROUND = [ (('fcos', 'x(is_not_const)'), ('fcos', ('fmod', 'x', 2.0 * pi))), ] +SQRT_WORKAROUND = [ + (('fsqrt', 'x(is_not_const)'), ('fsqrt', ('fmax', 'x', 1e-12))), +] + def main(): parser = argparse.ArgumentParser() parser.add_argument('-p', '--import-path', required=True) @@ -61,6 +65,8 @@ def run(): TRIG_WORKAROUNDS).render()) print(nir_algebraic.AlgebraicPass("brw_nir_limit_trig_input_range_workaround", LIMIT_TRIG_INPUT_RANGE_WORKAROUND).render()) + print(nir_algebraic.AlgebraicPass("brw_nir_apply_sqrt_workarounds", + SQRT_WORKAROUND).render()) if __name__ == '__main__': diff --git a/src/intel/vulkan/anv_shader_compile.c b/src/intel/vulkan/anv_shader_compile.c index e4b583a688f..8978238a6e7 100644 --- a/src/intel/vulkan/anv_shader_compile.c +++ b/src/intel/vulkan/anv_shader_compile.c @@ -16,6 +16,58 @@ #include "compiler/brw_nir_rt.h" #include "compiler/intel_nir.h" +typedef void (*game_wa_callback)(nir_shader *nir); + +/* Structure to hold a game-specific workaround entry */ +struct game_wa_entry { + game_wa_callback cb; + uint32_t shader_blake3s[16][BLAKE3_OUT_LEN32]; +}; + +/* Workaround for a shader in Horizon Forbidden West that causes + * visual corruption. The shader writes the result of fsqrt to + * storage images with a 16-bit image format and misrendering + * occurs when those values are denormal for an unknown reason. + * + * This clamps the image writes to the smallest fp16 normalized + * value. (Pattern matching against fsqrt is easy to do in a one + * line algebraic pass, while matching image stores is harder.) + * + * See https://gitlab.freedesktop.org/mesa/mesa/-/issues/12555 + */ +static void +wa_forbidden_west(nir_shader *nir) +{ + NIR_PASS(_, nir, brw_nir_apply_sqrt_workarounds); +} + +/* List of game-specific workarounds identified by BLAKE3 hash of the shader. + * Add new workarounds here as needed. + */ +static const struct game_wa_entry game_was[] = { + { + .cb = wa_forbidden_west, + .shader_blake3s = { + {0x51683151, 0xe044f0ce, 0xc210a762, 0xb12b2da4, 0x4e69ddc0, 0x237b1cc1, 0xc84bcf09, 0x31cfe883}, + }, + }, +}; + +/* Apply game-specific workarounds based on the shader's BLAKE3 hash */ +static void +anv_nir_apply_shader_workarounds(nir_shader *nir) +{ + for (unsigned i = 0; i < ARRAY_SIZE(game_was); i++) { + const struct game_wa_entry *wa = &game_was[i]; + for (unsigned j = 0; j < ARRAY_SIZE(wa->shader_blake3s); j++) { + if (_mesa_printed_blake3_equal(nir->info.source_blake3, wa->shader_blake3s[j])) { + wa->cb(nir); + return; + } + } + } +} + static enum brw_robustness_flags anv_get_robust_flags(const struct vk_pipeline_robustness_state *rstate) { @@ -1742,6 +1794,8 @@ anv_shader_compile(struct vk_device *vk_device, anv_fixup_subgroup_size(device->physical->instance, &shader_data->info->nir->info); + + anv_nir_apply_shader_workarounds(shader_data->info->nir); } /* Combine intersection & any-hit before lowering */