diff --git a/src/gallium/drivers/radeonsi/meson.build b/src/gallium/drivers/radeonsi/meson.build index e7da90d0f90..7c7d0ec09eb 100644 --- a/src/gallium/drivers/radeonsi/meson.build +++ b/src/gallium/drivers/radeonsi/meson.build @@ -52,6 +52,7 @@ files_libradeonsi = files( 'si_sdma_copy_image.c', 'si_shader.c', 'si_shader.h', + 'si_shader_aco.c', 'si_shader_info.c', 'si_shader_internal.h', 'si_shader_llvm.c', @@ -104,7 +105,7 @@ files_libradeonsi = files( ) radeonsi_include_dirs = [inc_src, inc_include, inc_gallium, inc_gallium_aux, inc_amd_common, - inc_amd_common_llvm, inc_gallium_drivers] + inc_amd_common_llvm, inc_gallium_drivers, inc_compiler] radeonsi_deps = [dep_llvm, dep_clock, dep_libdrm_radeon, idep_nir_headers, idep_amdgfxregs_h, idep_mesautil, idep_aco] radeonsi_gfx_libs = [] diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 29602d240e8..e5ecf5b7152 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -2621,14 +2621,11 @@ bool si_compile_shader(struct si_screen *sscreen, struct ac_llvm_compiler *compi FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP64)) float_mode &= ~V_00B028_FP_16_64_DENORMS; - /* TODO: ACO could compile non-monolithic shaders here (starting - * with PS and NGG VS), but monolithic shaders should be compiled - * by LLVM due to more complicated compilation. - */ - if (!si_llvm_compile_shader(sscreen, compiler, shader, &args, debug, nir)) { - ret = false; + ret = shader->use_aco ? + si_aco_compile_shader(shader, &args, nir, debug) : + si_llvm_compile_shader(sscreen, compiler, shader, &args, debug, nir); + if (!ret) goto out; - } shader->config.float_mode = float_mode; diff --git a/src/gallium/drivers/radeonsi/si_shader_aco.c b/src/gallium/drivers/radeonsi/si_shader_aco.c new file mode 100644 index 00000000000..70b2f544fc4 --- /dev/null +++ b/src/gallium/drivers/radeonsi/si_shader_aco.c @@ -0,0 +1,129 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "si_shader_internal.h" +#include "si_pipe.h" +#include "aco_interface.h" + +static void +si_aco_compiler_debug(void *private_data, enum aco_compiler_debug_level level, + const char *message) +{ + struct util_debug_callback *debug = private_data; + + util_debug_message(debug, SHADER_INFO, "%s\n", message); +} + +static void +si_fill_aco_options(struct si_shader *shader, struct aco_compiler_options *options, + struct util_debug_callback *debug) +{ + const struct si_shader_selector *sel = shader->selector; + + options->dump_shader = + si_can_dump_shader(sel->screen, sel->stage, SI_DUMP_ACO_IR) || + si_can_dump_shader(sel->screen, sel->stage, SI_DUMP_ASM); + options->dump_preoptir = si_can_dump_shader(sel->screen, sel->stage, SI_DUMP_INIT_ACO_IR); + options->record_ir = sel->screen->record_llvm_ir; + + options->load_grid_size_from_user_sgpr = true; + options->family = sel->screen->info.family; + options->gfx_level = sel->screen->info.gfx_level; + options->address32_hi = sel->screen->info.address32_hi; + + options->debug.func = si_aco_compiler_debug; + options->debug.private_data = debug; +} + +static void +si_fill_aco_shader_info(struct si_shader *shader, struct aco_shader_info *info) +{ + const struct si_shader_selector *sel = shader->selector; + + info->wave_size = shader->wave_size; + info->workgroup_size = si_get_max_workgroup_size(shader); + /* aco need non-zero value */ + if (!info->workgroup_size) + info->workgroup_size = info->wave_size; + + info->image_2d_view_of_3d = sel->screen->info.gfx_level == GFX9; + + switch (sel->stage) { + case MESA_SHADER_FRAGMENT: + info->ps.num_interp = si_get_ps_num_interp(shader); + info->ps.spi_ps_input = shader->config.spi_ps_input_ena; + break; + default: + break; + } +} + +static void +si_aco_build_shader_binary(void **data, const struct ac_shader_config *config, + const char *llvm_ir_str, unsigned llvm_ir_size, const char *disasm_str, + unsigned disasm_size, uint32_t *statistics, uint32_t stats_size, + uint32_t exec_size, const uint32_t *code, uint32_t code_dw, + const struct aco_symbol *symbols, unsigned num_symbols) +{ + struct si_shader *shader = (struct si_shader *)data; + + unsigned code_size = code_dw * 4; + char *buffer = MALLOC(code_size + disasm_size); + memcpy(buffer, code, code_size); + + shader->binary.type = SI_SHADER_BINARY_RAW; + shader->binary.code_buffer = buffer; + shader->binary.code_size = code_size; + + if (disasm_size) { + memcpy(buffer + code_size, disasm_str, disasm_size); + shader->binary.disasm_string = buffer + code_size; + shader->binary.disasm_size = disasm_size; + } + + if (llvm_ir_size) { + shader->binary.llvm_ir_string = MALLOC(llvm_ir_size); + memcpy(shader->binary.llvm_ir_string, llvm_ir_str, llvm_ir_size); + } + + shader->config = *config; +} + +bool +si_aco_compile_shader(struct si_shader *shader, + struct si_shader_args *args, + struct nir_shader *nir, + struct util_debug_callback *debug) +{ + struct aco_compiler_options options = {0}; + si_fill_aco_options(shader, &options, debug); + + struct aco_shader_info info = {0}; + si_fill_aco_shader_info(shader, &info); + + aco_compile_shader(&options, &info, 1, &nir, &args->ac, + si_aco_build_shader_binary, (void **)shader); + + return true; +} diff --git a/src/gallium/drivers/radeonsi/si_shader_internal.h b/src/gallium/drivers/radeonsi/si_shader_internal.h index 94ab629e287..5690983925c 100644 --- a/src/gallium/drivers/radeonsi/si_shader_internal.h +++ b/src/gallium/drivers/radeonsi/si_shader_internal.h @@ -239,4 +239,10 @@ void si_llvm_ps_build_end(struct si_shader_context *ctx); void si_llvm_build_vs_prolog(struct si_shader_context *ctx, union si_shader_part_key *key, bool separate_prolog); +/* si_shader_aco.c */ +bool si_aco_compile_shader(struct si_shader *shader, + struct si_shader_args *args, + struct nir_shader *nir, + struct util_debug_callback *debug); + #endif