From 9885af3bdf42cb22baf83aa9598be763a5fc2825 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Tue, 29 Oct 2019 17:40:30 +0100 Subject: [PATCH] ac: Add a shared interface between radv, radeonsi, LLVM and ACO ac_shader_args will be similar to ac_shader_abi, except for being free from LLVM-specific concepts and therefore capable of being shared between LLVM and ACO. This will help us accomplish a few different things: - Decouple setting up SGPR and VGPR arguments from translating to LLVM, so that we can reference these arguments in NIR lowering passes, which will let us lower e.g. descriptor sets in NIR. - Stop using radv-specific structures for things like determining the chip generation in ACO. In the end, we should replace ac_shader_abi with this structure + driver-specific lowering passes. Reviewed-by: Samuel Pitoiset --- src/amd/common/ac_shader_args.c | 55 ++++++++++++++++ src/amd/common/ac_shader_args.h | 111 ++++++++++++++++++++++++++++++++ src/amd/common/meson.build | 2 + src/amd/llvm/ac_llvm_build.c | 79 +++++++++++++++++++++++ src/amd/llvm/ac_llvm_build.h | 25 +++++++ src/amd/llvm/ac_shader_abi.h | 1 + 6 files changed, 273 insertions(+) create mode 100644 src/amd/common/ac_shader_args.c create mode 100644 src/amd/common/ac_shader_args.h diff --git a/src/amd/common/ac_shader_args.c b/src/amd/common/ac_shader_args.c new file mode 100644 index 00000000000..d5600eaca40 --- /dev/null +++ b/src/amd/common/ac_shader_args.c @@ -0,0 +1,55 @@ +/* + * Copyright 2019 Valve Corporation + * + * 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 "ac_shader_args.h" +#include "nir/nir_builder.h" + +void +ac_add_arg(struct ac_shader_args *info, enum ac_arg_regfile regfile, + unsigned size, enum ac_arg_type type, struct ac_arg *arg) +{ + assert(info->arg_count < AC_MAX_ARGS); + + unsigned offset; + if (regfile == AC_ARG_SGPR) { + offset = info->num_sgprs_used; + info->num_sgprs_used += size; + } else { + assert(regfile == AC_ARG_VGPR); + offset = info->num_vgprs_used; + info->num_vgprs_used += size; + } + + info->args[info->arg_count].file = regfile; + info->args[info->arg_count].offset = offset; + info->args[info->arg_count].size = size; + info->args[info->arg_count].type = type; + + if (arg) { + arg->arg_index = info->arg_count; + arg->used = true; + } + + info->arg_count++; +} + diff --git a/src/amd/common/ac_shader_args.h b/src/amd/common/ac_shader_args.h new file mode 100644 index 00000000000..e188c2ef12e --- /dev/null +++ b/src/amd/common/ac_shader_args.h @@ -0,0 +1,111 @@ +/* + * Copyright 2019 Valve Corporation + * + * 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. + */ + +#ifndef AC_SHADER_ARGS_H +#define AC_SHADER_ARGS_H + +#include +#include + +#define AC_MAX_INLINE_PUSH_CONSTS 8 + +enum ac_arg_regfile { + AC_ARG_SGPR, + AC_ARG_VGPR, +}; + +enum ac_arg_type { + AC_ARG_FLOAT, + AC_ARG_INT, + AC_ARG_CONST_PTR, /* Pointer to i8 array */ + AC_ARG_CONST_FLOAT_PTR, /* Pointer to f32 array */ + AC_ARG_CONST_PTR_PTR, /* Pointer to pointer to i8 array */ + AC_ARG_CONST_DESC_PTR, /* Pointer to v4i32 array */ + AC_ARG_CONST_IMAGE_PTR, /* Pointer to v8i32 array */ +}; + +struct ac_arg { + uint8_t arg_index; + bool used; +}; + + +#define AC_MAX_ARGS 64 +struct ac_shader_args { + /* Info on how to declare arguments */ + struct { + enum ac_arg_type type; + enum ac_arg_regfile file; + uint8_t offset; + uint8_t size; + } args[AC_MAX_ARGS]; + + uint8_t arg_count; + uint8_t sgpr_count; + uint8_t num_sgprs_used; + uint8_t num_vgprs_used; + + struct ac_arg base_vertex; + struct ac_arg start_instance; + struct ac_arg draw_id; + struct ac_arg vertex_id; + struct ac_arg instance_id; + struct ac_arg tcs_patch_id; + struct ac_arg tcs_rel_ids; + struct ac_arg tes_patch_id; + struct ac_arg gs_prim_id; + struct ac_arg gs_invocation_id; + + /* PS */ + struct ac_arg frag_pos[4]; + struct ac_arg front_face; + struct ac_arg ancillary; + struct ac_arg sample_coverage; + struct ac_arg prim_mask; + struct ac_arg persp_sample; + struct ac_arg persp_center; + struct ac_arg persp_centroid; + struct ac_arg linear_sample; + struct ac_arg linear_center; + struct ac_arg linear_centroid; + + /* CS */ + struct ac_arg local_invocation_ids; + struct ac_arg num_work_groups; + struct ac_arg workgroup_ids[3]; + struct ac_arg tg_size; + + /* Vulkan only */ + struct ac_arg push_constants; + struct ac_arg inline_push_consts[AC_MAX_INLINE_PUSH_CONSTS]; + unsigned num_inline_push_consts; + unsigned base_inline_push_consts; + struct ac_arg view_index; +}; + +void ac_add_arg(struct ac_shader_args *info, enum ac_arg_regfile regfile, + unsigned registers, enum ac_arg_type type, + struct ac_arg *arg); + +#endif + diff --git a/src/amd/common/meson.build b/src/amd/common/meson.build index d752bfce83f..25fc75fb495 100644 --- a/src/amd/common/meson.build +++ b/src/amd/common/meson.build @@ -40,6 +40,8 @@ amd_common_files = files( 'ac_binary.c', 'ac_binary.h', 'ac_exp_param.h', + 'ac_shader_args.c', + 'ac_shader_args.h', 'ac_shader_util.c', 'ac_shader_util.h', 'ac_gpu_info.c', diff --git a/src/amd/llvm/ac_llvm_build.c b/src/amd/llvm/ac_llvm_build.c index 12ee06c2678..35472900e98 100644 --- a/src/amd/llvm/ac_llvm_build.c +++ b/src/amd/llvm/ac_llvm_build.c @@ -4675,3 +4675,82 @@ ac_export_mrt_z(struct ac_llvm_context *ctx, LLVMValueRef depth, args->enabled_channels = mask; } +static LLVMTypeRef +arg_llvm_type(enum ac_arg_type type, unsigned size, struct ac_llvm_context *ctx) +{ + if (type == AC_ARG_FLOAT) { + return size == 1 ? ctx->f32 : LLVMVectorType(ctx->f32, size); + } else if (type == AC_ARG_INT) { + return size == 1 ? ctx->i32 : LLVMVectorType(ctx->i32, size); + } else { + LLVMTypeRef ptr_type; + switch (type) { + case AC_ARG_CONST_PTR: + ptr_type = ctx->i8; + break; + case AC_ARG_CONST_FLOAT_PTR: + ptr_type = ctx->f32; + break; + case AC_ARG_CONST_PTR_PTR: + ptr_type = ac_array_in_const32_addr_space(ctx->i8); + break; + case AC_ARG_CONST_DESC_PTR: + ptr_type = ctx->v4i32; + break; + case AC_ARG_CONST_IMAGE_PTR: + ptr_type = ctx->v8i32; + break; + default: + unreachable("unknown arg type"); + } + if (size == 1) { + return ac_array_in_const32_addr_space(ptr_type); + } else { + assert(size == 2); + return ac_array_in_const_addr_space(ptr_type); + } + } +} + +LLVMValueRef +ac_build_main(const struct ac_shader_args *args, + struct ac_llvm_context *ctx, + enum ac_llvm_calling_convention convention, + const char *name, LLVMTypeRef ret_type, + LLVMModuleRef module) +{ + LLVMTypeRef arg_types[AC_MAX_ARGS]; + + for (unsigned i = 0; i < args->arg_count; i++) { + arg_types[i] = arg_llvm_type(args->args[i].type, + args->args[i].size, ctx); + } + + LLVMTypeRef main_function_type = + LLVMFunctionType(ret_type, arg_types, args->arg_count, 0); + + LLVMValueRef main_function = + LLVMAddFunction(module, name, main_function_type); + LLVMBasicBlockRef main_function_body = + LLVMAppendBasicBlockInContext(ctx->context, main_function, "main_body"); + LLVMPositionBuilderAtEnd(ctx->builder, main_function_body); + + LLVMSetFunctionCallConv(main_function, convention); + for (unsigned i = 0; i < args->arg_count; ++i) { + LLVMValueRef P = LLVMGetParam(main_function, i); + + if (args->args[i].file != AC_ARG_SGPR) + continue; + + ac_add_function_attr(ctx->context, main_function, i + 1, AC_FUNC_ATTR_INREG); + + if (LLVMGetTypeKind(LLVMTypeOf(P)) == LLVMPointerTypeKind) { + ac_add_function_attr(ctx->context, main_function, i + 1, AC_FUNC_ATTR_NOALIAS); + ac_add_attr_dereferenceable(P, UINT64_MAX); + } + } + + ctx->main_function = main_function; + return main_function; +} + diff --git a/src/amd/llvm/ac_llvm_build.h b/src/amd/llvm/ac_llvm_build.h index 8cd15cbe99f..2357e42035c 100644 --- a/src/amd/llvm/ac_llvm_build.h +++ b/src/amd/llvm/ac_llvm_build.h @@ -30,6 +30,8 @@ #include "compiler/nir/nir.h" #include "amd_family.h" #include "ac_shader_util.h" +#include "ac_shader_args.h" +#include "ac_shader_abi.h" #ifdef __cplusplus extern "C" { @@ -63,6 +65,8 @@ struct ac_llvm_context { LLVMModuleRef module; LLVMBuilderRef builder; + LLVMValueRef main_function; + LLVMTypeRef voidt; LLVMTypeRef i1; LLVMTypeRef i8; @@ -743,6 +747,27 @@ ac_export_mrt_z(struct ac_llvm_context *ctx, LLVMValueRef depth, LLVMValueRef stencil, LLVMValueRef samplemask, struct ac_export_args *args); +static inline LLVMValueRef +ac_get_arg(struct ac_llvm_context *ctx, struct ac_arg arg) +{ + assert(arg.used); + return LLVMGetParam(ctx->main_function, arg.arg_index); +} + +enum ac_llvm_calling_convention { + AC_LLVM_AMDGPU_VS = 87, + AC_LLVM_AMDGPU_GS = 88, + AC_LLVM_AMDGPU_PS = 89, + AC_LLVM_AMDGPU_CS = 90, + AC_LLVM_AMDGPU_HS = 93, +}; + +LLVMValueRef ac_build_main(const struct ac_shader_args *args, + struct ac_llvm_context *ctx, + enum ac_llvm_calling_convention convention, + const char *name, LLVMTypeRef ret_type, + LLVMModuleRef module); + #ifdef __cplusplus } #endif diff --git a/src/amd/llvm/ac_shader_abi.h b/src/amd/llvm/ac_shader_abi.h index 61f1b735c49..01c321506ef 100644 --- a/src/amd/llvm/ac_shader_abi.h +++ b/src/amd/llvm/ac_shader_abi.h @@ -25,6 +25,7 @@ #define AC_SHADER_ABI_H #include +#include "ac_shader_args.h" #include "compiler/shader_enums.h" -- 2.30.2