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