diff --git a/src/gallium/auxiliary/draw/draw_nir.h b/src/gallium/auxiliary/draw/draw_nir.h new file mode 100644 index 00000000000..8ed57cd4ad6 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_nir.h @@ -0,0 +1,17 @@ +/************************************************************************** + * + * Copyright 2026 Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: MIT + * + **************************************************************************/ + +#ifndef DRAW_NIR_H +#define DRAW_NIR_H + +#include "compiler/nir/nir.h" + +bool +draw_nir_lower_opcodes(struct nir_shader *shader); + +#endif diff --git a/src/gallium/auxiliary/draw/draw_nir_lower_opcodes.py b/src/gallium/auxiliary/draw/draw_nir_lower_opcodes.py new file mode 100644 index 00000000000..ec9c60e9cd8 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_nir_lower_opcodes.py @@ -0,0 +1,48 @@ +# +# Copyright 2026 Advanced Micro Devices, Inc. +# +# SPDX-License-Identifier: MIT + +import argparse +import sys + +a, b, c = 'a', 'b', 'c' + +# This contains lowerings for opcodes that driver-specific optimizations +# may introduce but gallivm does not support. +lower = [ + (('fmulz', a, b), ('bcsel', ('ior', ('feq', a, 0.0), ('feq', b, 0.0)), 0.0, ('fmul', a, b))), + (('ffmaz', a, b, c), ('bcsel', ('ior', ('feq', a, 0.0), ('feq', b, 0.0)), c, ('ffma_weak', a, b, c))), + + # draw shaders are GLSL shaders, which means we can just use ffma_weak + (('ffma', a, b, c), ('ffma_weak', a, b, c)), + + (('bitfield_select', a, b, c), ('ixor', c, ('iand', a, ('ixor', b, c)))), + (('ubfe', a, b, c), ('ubitfield_extract', a, ('iand', b, 0x1f), ('iand', c, 0x1f))), + (('ibfe', a, b, c), ('ibitfield_extract', a, ('iand', b, 0x1f), ('iand', c, 0x1f))), + (('bfm', a, b), ('ishl', ('isub', ('ishl', 1, ('iand', a, 0x1f)), 1), ('iand', b, 0x1f))), + # bfi(a, b, c) -> bitfield_select(a, ishl(b, find_lsb(a)), c) + (('bfi', a, b, c), ('ixor', c, ('iand', a, ('ixor', ('ishl', b, ('find_lsb', a)), c)))), + + (('ufind_msb_rev', a), ('bcsel', ('ige', ('ufind_msb', a), 0), ('isub', 31, ('ufind_msb', a)), -1)), + (('ifind_msb_rev', a), ('bcsel', ('ige', ('ifind_msb', a), 0), ('isub', 31, ('ifind_msb', a)), -1)), + + # uclz(a) -> umin(32, ufind_msb_rev(a)) + (('uclz', a), ('umin', 32, ('bcsel', ('ige', ('ufind_msb', a), 0), ('isub', 31, ('ufind_msb', a)), -1))), + + (('shfr', a, b, c), + ('bcsel', ('ieq', ('iand', c, 0x1f), 0), b, + ('ior', ('ishl', a, ('iadd', 32, ('ineg', ('iand', c, 0x1f)))), + ('ushr', b, ('iand', c, 0x1f))))), +] + +parser = argparse.ArgumentParser() +parser.add_argument('-p', '--import-path', required=True) +args = parser.parse_args() +sys.path.insert(0, args.import_path) + +import nir_algebraic + +p = nir_algebraic.AlgebraicPass("draw_nir_lower_opcodes", lower) +print('#include "draw/draw_nir.h"') +print(p.render()) diff --git a/src/gallium/auxiliary/meson.build b/src/gallium/auxiliary/meson.build index ad35b3d3e47..308bf6bc3e6 100644 --- a/src/gallium/auxiliary/meson.build +++ b/src/gallium/auxiliary/meson.build @@ -271,6 +271,17 @@ if with_gfx_compute 'util/u_simple_shaders.c', 'util/u_tests.c', ) + + files_libgallium += custom_target( + 'draw_nir_lower_opcodes.c', + input : 'draw/draw_nir_lower_opcodes.py', + output : 'draw_nir_lower_opcodes.c', + command : [ + prog_python, '@INPUT@', '-p', dir_compiler_nir, + ], + capture : true, + depend_files : nir_algebraic_depends, + ) endif if dep_libdrm.found() diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 7d50527e3d9..545cebb34ee 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -52,6 +52,7 @@ #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" #include "draw/draw_context.h" +#include "draw/draw_nir.h" #include "util/u_dump.h" #include "util/u_memory.h"