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"