1 /*
2 * Copyright 2019 Valve Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "ac_shader_args.h"
8
9 #include "nir/nir_builder.h"
10
ac_add_arg(struct ac_shader_args * info,enum ac_arg_regfile regfile,unsigned size,enum ac_arg_type type,struct ac_arg * arg)11 void ac_add_arg(struct ac_shader_args *info, enum ac_arg_regfile regfile, unsigned size,
12 enum ac_arg_type type, struct ac_arg *arg)
13 {
14 assert(info->arg_count < AC_MAX_ARGS);
15
16 unsigned offset;
17 if (regfile == AC_ARG_SGPR) {
18 offset = info->num_sgprs_used;
19 info->num_sgprs_used += size;
20 } else {
21 assert(regfile == AC_ARG_VGPR);
22 offset = info->num_vgprs_used;
23 info->num_vgprs_used += size;
24 }
25
26 info->args[info->arg_count].file = regfile;
27 info->args[info->arg_count].offset = offset;
28 info->args[info->arg_count].size = size;
29 info->args[info->arg_count].type = type;
30
31 if (arg) {
32 arg->arg_index = info->arg_count;
33 arg->used = true;
34 }
35
36 info->arg_count++;
37 }
38
ac_add_return(struct ac_shader_args * info,enum ac_arg_regfile regfile)39 void ac_add_return(struct ac_shader_args *info, enum ac_arg_regfile regfile)
40 {
41 assert(info->return_count < AC_MAX_ARGS);
42
43 if (regfile == AC_ARG_SGPR) {
44 /* SGPRs must be inserted before VGPRs. */
45 assert(info->num_vgprs_returned == 0);
46 info->num_sgprs_returned++;;
47 } else {
48 assert(regfile == AC_ARG_VGPR);
49 info->num_vgprs_returned++;
50 }
51
52 info->return_count++;
53 }
54
ac_add_preserved(struct ac_shader_args * info,const struct ac_arg * arg)55 void ac_add_preserved(struct ac_shader_args *info, const struct ac_arg *arg)
56 {
57 info->args[arg->arg_index].preserved = true;
58 }
59
ac_compact_ps_vgpr_args(struct ac_shader_args * info,uint32_t spi_ps_input)60 void ac_compact_ps_vgpr_args(struct ac_shader_args *info, uint32_t spi_ps_input)
61 {
62 /* LLVM optimizes away unused FS inputs and computes spi_ps_input_addr itself and then
63 * communicates the results back via the ELF binary. Mirror what LLVM does by re-mapping the
64 * VGPR arguments here.
65 */
66 unsigned vgpr_arg = 0;
67 unsigned vgpr_reg = 0;
68
69 for (unsigned i = 0; i < info->arg_count; i++) {
70 if (info->args[i].file != AC_ARG_VGPR)
71 continue;
72
73 if (!(spi_ps_input & (1 << vgpr_arg))) {
74 info->args[i].skip = true;
75 } else {
76 info->args[i].offset = vgpr_reg;
77 vgpr_reg += info->args[i].size;
78 }
79 vgpr_arg++;
80 }
81
82 info->num_vgprs_used = vgpr_reg;
83 }
84