1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2016 Bas Nieuwenhuizen
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker */
6*61046927SAndroid Build Coastguard Worker
7*61046927SAndroid Build Coastguard Worker #include "ac_gpu_info.h"
8*61046927SAndroid Build Coastguard Worker #include "ac_nir.h"
9*61046927SAndroid Build Coastguard Worker #include "ac_nir_helpers.h"
10*61046927SAndroid Build Coastguard Worker #include "sid.h"
11*61046927SAndroid Build Coastguard Worker #include "nir_builder.h"
12*61046927SAndroid Build Coastguard Worker #include "nir_xfb_info.h"
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard Worker /* Sleep for the given number of clock cycles. */
15*61046927SAndroid Build Coastguard Worker void
ac_nir_sleep(nir_builder * b,unsigned num_cycles)16*61046927SAndroid Build Coastguard Worker ac_nir_sleep(nir_builder *b, unsigned num_cycles)
17*61046927SAndroid Build Coastguard Worker {
18*61046927SAndroid Build Coastguard Worker /* s_sleep can only sleep for N*64 cycles. */
19*61046927SAndroid Build Coastguard Worker if (num_cycles >= 64) {
20*61046927SAndroid Build Coastguard Worker nir_sleep_amd(b, num_cycles / 64);
21*61046927SAndroid Build Coastguard Worker num_cycles &= 63;
22*61046927SAndroid Build Coastguard Worker }
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker /* Use s_nop to sleep for the remaining cycles. */
25*61046927SAndroid Build Coastguard Worker while (num_cycles) {
26*61046927SAndroid Build Coastguard Worker unsigned nop_cycles = MIN2(num_cycles, 16);
27*61046927SAndroid Build Coastguard Worker
28*61046927SAndroid Build Coastguard Worker nir_nop_amd(b, nop_cycles - 1);
29*61046927SAndroid Build Coastguard Worker num_cycles -= nop_cycles;
30*61046927SAndroid Build Coastguard Worker }
31*61046927SAndroid Build Coastguard Worker }
32*61046927SAndroid Build Coastguard Worker
33*61046927SAndroid Build Coastguard Worker /* Load argument with index start from arg plus relative_index. */
34*61046927SAndroid Build Coastguard Worker nir_def *
ac_nir_load_arg_at_offset(nir_builder * b,const struct ac_shader_args * ac_args,struct ac_arg arg,unsigned relative_index)35*61046927SAndroid Build Coastguard Worker ac_nir_load_arg_at_offset(nir_builder *b, const struct ac_shader_args *ac_args,
36*61046927SAndroid Build Coastguard Worker struct ac_arg arg, unsigned relative_index)
37*61046927SAndroid Build Coastguard Worker {
38*61046927SAndroid Build Coastguard Worker unsigned arg_index = arg.arg_index + relative_index;
39*61046927SAndroid Build Coastguard Worker unsigned num_components = ac_args->args[arg_index].size;
40*61046927SAndroid Build Coastguard Worker
41*61046927SAndroid Build Coastguard Worker if (ac_args->args[arg_index].file == AC_ARG_SGPR)
42*61046927SAndroid Build Coastguard Worker return nir_load_scalar_arg_amd(b, num_components, .base = arg_index);
43*61046927SAndroid Build Coastguard Worker else
44*61046927SAndroid Build Coastguard Worker return nir_load_vector_arg_amd(b, num_components, .base = arg_index);
45*61046927SAndroid Build Coastguard Worker }
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Worker void
ac_nir_store_arg(nir_builder * b,const struct ac_shader_args * ac_args,struct ac_arg arg,nir_def * val)48*61046927SAndroid Build Coastguard Worker ac_nir_store_arg(nir_builder *b, const struct ac_shader_args *ac_args, struct ac_arg arg,
49*61046927SAndroid Build Coastguard Worker nir_def *val)
50*61046927SAndroid Build Coastguard Worker {
51*61046927SAndroid Build Coastguard Worker assert(nir_cursor_current_block(b->cursor)->cf_node.parent->type == nir_cf_node_function);
52*61046927SAndroid Build Coastguard Worker
53*61046927SAndroid Build Coastguard Worker if (ac_args->args[arg.arg_index].file == AC_ARG_SGPR)
54*61046927SAndroid Build Coastguard Worker nir_store_scalar_arg_amd(b, val, .base = arg.arg_index);
55*61046927SAndroid Build Coastguard Worker else
56*61046927SAndroid Build Coastguard Worker nir_store_vector_arg_amd(b, val, .base = arg.arg_index);
57*61046927SAndroid Build Coastguard Worker }
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker nir_def *
ac_nir_unpack_arg(nir_builder * b,const struct ac_shader_args * ac_args,struct ac_arg arg,unsigned rshift,unsigned bitwidth)60*61046927SAndroid Build Coastguard Worker ac_nir_unpack_arg(nir_builder *b, const struct ac_shader_args *ac_args, struct ac_arg arg,
61*61046927SAndroid Build Coastguard Worker unsigned rshift, unsigned bitwidth)
62*61046927SAndroid Build Coastguard Worker {
63*61046927SAndroid Build Coastguard Worker nir_def *value = ac_nir_load_arg(b, ac_args, arg);
64*61046927SAndroid Build Coastguard Worker if (rshift == 0 && bitwidth == 32)
65*61046927SAndroid Build Coastguard Worker return value;
66*61046927SAndroid Build Coastguard Worker else if (rshift == 0)
67*61046927SAndroid Build Coastguard Worker return nir_iand_imm(b, value, BITFIELD_MASK(bitwidth));
68*61046927SAndroid Build Coastguard Worker else if ((32 - rshift) <= bitwidth)
69*61046927SAndroid Build Coastguard Worker return nir_ushr_imm(b, value, rshift);
70*61046927SAndroid Build Coastguard Worker else
71*61046927SAndroid Build Coastguard Worker return nir_ubfe_imm(b, value, rshift, bitwidth);
72*61046927SAndroid Build Coastguard Worker }
73*61046927SAndroid Build Coastguard Worker
74*61046927SAndroid Build Coastguard Worker static bool
is_sin_cos(const nir_instr * instr,UNUSED const void * _)75*61046927SAndroid Build Coastguard Worker is_sin_cos(const nir_instr *instr, UNUSED const void *_)
76*61046927SAndroid Build Coastguard Worker {
77*61046927SAndroid Build Coastguard Worker return instr->type == nir_instr_type_alu && (nir_instr_as_alu(instr)->op == nir_op_fsin ||
78*61046927SAndroid Build Coastguard Worker nir_instr_as_alu(instr)->op == nir_op_fcos);
79*61046927SAndroid Build Coastguard Worker }
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker static nir_def *
lower_sin_cos(struct nir_builder * b,nir_instr * instr,UNUSED void * _)82*61046927SAndroid Build Coastguard Worker lower_sin_cos(struct nir_builder *b, nir_instr *instr, UNUSED void *_)
83*61046927SAndroid Build Coastguard Worker {
84*61046927SAndroid Build Coastguard Worker nir_alu_instr *sincos = nir_instr_as_alu(instr);
85*61046927SAndroid Build Coastguard Worker nir_def *src = nir_fmul_imm(b, nir_ssa_for_alu_src(b, sincos, 0), 0.15915493667125702);
86*61046927SAndroid Build Coastguard Worker return sincos->op == nir_op_fsin ? nir_fsin_amd(b, src) : nir_fcos_amd(b, src);
87*61046927SAndroid Build Coastguard Worker }
88*61046927SAndroid Build Coastguard Worker
89*61046927SAndroid Build Coastguard Worker bool
ac_nir_lower_sin_cos(nir_shader * shader)90*61046927SAndroid Build Coastguard Worker ac_nir_lower_sin_cos(nir_shader *shader)
91*61046927SAndroid Build Coastguard Worker {
92*61046927SAndroid Build Coastguard Worker return nir_shader_lower_instructions(shader, is_sin_cos, lower_sin_cos, NULL);
93*61046927SAndroid Build Coastguard Worker }
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker typedef struct {
96*61046927SAndroid Build Coastguard Worker const struct ac_shader_args *const args;
97*61046927SAndroid Build Coastguard Worker const enum amd_gfx_level gfx_level;
98*61046927SAndroid Build Coastguard Worker const enum ac_hw_stage hw_stage;
99*61046927SAndroid Build Coastguard Worker } lower_intrinsics_to_args_state;
100*61046927SAndroid Build Coastguard Worker
101*61046927SAndroid Build Coastguard Worker static bool
lower_intrinsic_to_arg(nir_builder * b,nir_instr * instr,void * state)102*61046927SAndroid Build Coastguard Worker lower_intrinsic_to_arg(nir_builder *b, nir_instr *instr, void *state)
103*61046927SAndroid Build Coastguard Worker {
104*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_intrinsic)
105*61046927SAndroid Build Coastguard Worker return false;
106*61046927SAndroid Build Coastguard Worker
107*61046927SAndroid Build Coastguard Worker lower_intrinsics_to_args_state *s = (lower_intrinsics_to_args_state *)state;
108*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
109*61046927SAndroid Build Coastguard Worker nir_def *replacement = NULL;
110*61046927SAndroid Build Coastguard Worker b->cursor = nir_after_instr(&intrin->instr);
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker switch (intrin->intrinsic) {
113*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_subgroup_id: {
114*61046927SAndroid Build Coastguard Worker if (s->hw_stage == AC_HW_COMPUTE_SHADER) {
115*61046927SAndroid Build Coastguard Worker if (s->gfx_level >= GFX12)
116*61046927SAndroid Build Coastguard Worker return false;
117*61046927SAndroid Build Coastguard Worker
118*61046927SAndroid Build Coastguard Worker assert(s->args->tg_size.used);
119*61046927SAndroid Build Coastguard Worker
120*61046927SAndroid Build Coastguard Worker if (s->gfx_level >= GFX10_3) {
121*61046927SAndroid Build Coastguard Worker replacement = ac_nir_unpack_arg(b, s->args, s->args->tg_size, 20, 5);
122*61046927SAndroid Build Coastguard Worker } else {
123*61046927SAndroid Build Coastguard Worker /* GFX6-10 don't actually support a wave id, but we can
124*61046927SAndroid Build Coastguard Worker * use the ordered id because ORDERED_APPEND_* is set to
125*61046927SAndroid Build Coastguard Worker * zero in the compute dispatch initiatior.
126*61046927SAndroid Build Coastguard Worker */
127*61046927SAndroid Build Coastguard Worker replacement = ac_nir_unpack_arg(b, s->args, s->args->tg_size, 6, 6);
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker } else if (s->hw_stage == AC_HW_HULL_SHADER && s->gfx_level >= GFX11) {
130*61046927SAndroid Build Coastguard Worker assert(s->args->tcs_wave_id.used);
131*61046927SAndroid Build Coastguard Worker replacement = ac_nir_unpack_arg(b, s->args, s->args->tcs_wave_id, 0, 3);
132*61046927SAndroid Build Coastguard Worker } else if (s->hw_stage == AC_HW_LEGACY_GEOMETRY_SHADER ||
133*61046927SAndroid Build Coastguard Worker s->hw_stage == AC_HW_NEXT_GEN_GEOMETRY_SHADER) {
134*61046927SAndroid Build Coastguard Worker assert(s->args->merged_wave_info.used);
135*61046927SAndroid Build Coastguard Worker replacement = ac_nir_unpack_arg(b, s->args, s->args->merged_wave_info, 24, 4);
136*61046927SAndroid Build Coastguard Worker } else {
137*61046927SAndroid Build Coastguard Worker replacement = nir_imm_int(b, 0);
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker break;
141*61046927SAndroid Build Coastguard Worker }
142*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_num_subgroups: {
143*61046927SAndroid Build Coastguard Worker if (s->hw_stage == AC_HW_COMPUTE_SHADER) {
144*61046927SAndroid Build Coastguard Worker assert(s->args->tg_size.used);
145*61046927SAndroid Build Coastguard Worker replacement = ac_nir_unpack_arg(b, s->args, s->args->tg_size, 0, 6);
146*61046927SAndroid Build Coastguard Worker } else if (s->hw_stage == AC_HW_LEGACY_GEOMETRY_SHADER ||
147*61046927SAndroid Build Coastguard Worker s->hw_stage == AC_HW_NEXT_GEN_GEOMETRY_SHADER) {
148*61046927SAndroid Build Coastguard Worker assert(s->args->merged_wave_info.used);
149*61046927SAndroid Build Coastguard Worker replacement = ac_nir_unpack_arg(b, s->args, s->args->merged_wave_info, 28, 4);
150*61046927SAndroid Build Coastguard Worker } else {
151*61046927SAndroid Build Coastguard Worker replacement = nir_imm_int(b, 1);
152*61046927SAndroid Build Coastguard Worker }
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker break;
155*61046927SAndroid Build Coastguard Worker }
156*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_workgroup_id:
157*61046927SAndroid Build Coastguard Worker if (b->shader->info.stage == MESA_SHADER_MESH) {
158*61046927SAndroid Build Coastguard Worker /* This lowering is only valid with fast_launch = 2, otherwise we assume that
159*61046927SAndroid Build Coastguard Worker * lower_workgroup_id_to_index removed any uses of the workgroup id by this point.
160*61046927SAndroid Build Coastguard Worker */
161*61046927SAndroid Build Coastguard Worker assert(s->gfx_level >= GFX11);
162*61046927SAndroid Build Coastguard Worker nir_def *xy = ac_nir_load_arg(b, s->args, s->args->tess_offchip_offset);
163*61046927SAndroid Build Coastguard Worker nir_def *z = ac_nir_load_arg(b, s->args, s->args->gs_attr_offset);
164*61046927SAndroid Build Coastguard Worker replacement = nir_vec3(b, nir_extract_u16(b, xy, nir_imm_int(b, 0)),
165*61046927SAndroid Build Coastguard Worker nir_extract_u16(b, xy, nir_imm_int(b, 1)),
166*61046927SAndroid Build Coastguard Worker nir_extract_u16(b, z, nir_imm_int(b, 1)));
167*61046927SAndroid Build Coastguard Worker } else {
168*61046927SAndroid Build Coastguard Worker return false;
169*61046927SAndroid Build Coastguard Worker }
170*61046927SAndroid Build Coastguard Worker
171*61046927SAndroid Build Coastguard Worker break;
172*61046927SAndroid Build Coastguard Worker default:
173*61046927SAndroid Build Coastguard Worker return false;
174*61046927SAndroid Build Coastguard Worker }
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Worker assert(replacement);
177*61046927SAndroid Build Coastguard Worker nir_def_replace(&intrin->def, replacement);
178*61046927SAndroid Build Coastguard Worker return true;
179*61046927SAndroid Build Coastguard Worker }
180*61046927SAndroid Build Coastguard Worker
181*61046927SAndroid Build Coastguard Worker bool
ac_nir_lower_intrinsics_to_args(nir_shader * shader,const enum amd_gfx_level gfx_level,const enum ac_hw_stage hw_stage,const struct ac_shader_args * ac_args)182*61046927SAndroid Build Coastguard Worker ac_nir_lower_intrinsics_to_args(nir_shader *shader, const enum amd_gfx_level gfx_level,
183*61046927SAndroid Build Coastguard Worker const enum ac_hw_stage hw_stage,
184*61046927SAndroid Build Coastguard Worker const struct ac_shader_args *ac_args)
185*61046927SAndroid Build Coastguard Worker {
186*61046927SAndroid Build Coastguard Worker lower_intrinsics_to_args_state state = {
187*61046927SAndroid Build Coastguard Worker .gfx_level = gfx_level,
188*61046927SAndroid Build Coastguard Worker .hw_stage = hw_stage,
189*61046927SAndroid Build Coastguard Worker .args = ac_args,
190*61046927SAndroid Build Coastguard Worker };
191*61046927SAndroid Build Coastguard Worker
192*61046927SAndroid Build Coastguard Worker return nir_shader_instructions_pass(shader, lower_intrinsic_to_arg,
193*61046927SAndroid Build Coastguard Worker nir_metadata_control_flow, &state);
194*61046927SAndroid Build Coastguard Worker }
195*61046927SAndroid Build Coastguard Worker
196*61046927SAndroid Build Coastguard Worker void
ac_nir_store_var_components(nir_builder * b,nir_variable * var,nir_def * value,unsigned component,unsigned writemask)197*61046927SAndroid Build Coastguard Worker ac_nir_store_var_components(nir_builder *b, nir_variable *var, nir_def *value,
198*61046927SAndroid Build Coastguard Worker unsigned component, unsigned writemask)
199*61046927SAndroid Build Coastguard Worker {
200*61046927SAndroid Build Coastguard Worker /* component store */
201*61046927SAndroid Build Coastguard Worker if (value->num_components != 4) {
202*61046927SAndroid Build Coastguard Worker nir_def *undef = nir_undef(b, 1, value->bit_size);
203*61046927SAndroid Build Coastguard Worker
204*61046927SAndroid Build Coastguard Worker /* add undef component before and after value to form a vec4 */
205*61046927SAndroid Build Coastguard Worker nir_def *comp[4];
206*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
207*61046927SAndroid Build Coastguard Worker comp[i] = (i >= component && i < component + value->num_components) ?
208*61046927SAndroid Build Coastguard Worker nir_channel(b, value, i - component) : undef;
209*61046927SAndroid Build Coastguard Worker }
210*61046927SAndroid Build Coastguard Worker
211*61046927SAndroid Build Coastguard Worker value = nir_vec(b, comp, 4);
212*61046927SAndroid Build Coastguard Worker writemask <<= component;
213*61046927SAndroid Build Coastguard Worker } else {
214*61046927SAndroid Build Coastguard Worker /* if num_component==4, there should be no component offset */
215*61046927SAndroid Build Coastguard Worker assert(component == 0);
216*61046927SAndroid Build Coastguard Worker }
217*61046927SAndroid Build Coastguard Worker
218*61046927SAndroid Build Coastguard Worker nir_store_var(b, var, value, writemask);
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker /* Process the given store_output intrinsic and process its information.
222*61046927SAndroid Build Coastguard Worker * Meant to be used for VS/TES/GS when they are the last pre-rasterization stage.
223*61046927SAndroid Build Coastguard Worker *
224*61046927SAndroid Build Coastguard Worker * Assumptions:
225*61046927SAndroid Build Coastguard Worker * - We called nir_lower_io_to_temporaries on the shader
226*61046927SAndroid Build Coastguard Worker * - 64-bit outputs are lowered
227*61046927SAndroid Build Coastguard Worker * - no indirect indexing is present
228*61046927SAndroid Build Coastguard Worker */
ac_nir_gather_prerast_store_output_info(nir_builder * b,nir_intrinsic_instr * intrin,ac_nir_prerast_out * out)229*61046927SAndroid Build Coastguard Worker void ac_nir_gather_prerast_store_output_info(nir_builder *b, nir_intrinsic_instr *intrin, ac_nir_prerast_out *out)
230*61046927SAndroid Build Coastguard Worker {
231*61046927SAndroid Build Coastguard Worker assert(intrin->intrinsic == nir_intrinsic_store_output);
232*61046927SAndroid Build Coastguard Worker assert(nir_src_is_const(intrin->src[1]) && !nir_src_as_uint(intrin->src[1]));
233*61046927SAndroid Build Coastguard Worker
234*61046927SAndroid Build Coastguard Worker const nir_io_semantics io_sem = nir_intrinsic_io_semantics(intrin);
235*61046927SAndroid Build Coastguard Worker const unsigned slot = io_sem.location;
236*61046927SAndroid Build Coastguard Worker
237*61046927SAndroid Build Coastguard Worker nir_def *store_val = intrin->src[0].ssa;
238*61046927SAndroid Build Coastguard Worker assert(store_val->bit_size == 16 || store_val->bit_size == 32);
239*61046927SAndroid Build Coastguard Worker
240*61046927SAndroid Build Coastguard Worker nir_def **output;
241*61046927SAndroid Build Coastguard Worker nir_alu_type *type;
242*61046927SAndroid Build Coastguard Worker ac_nir_prerast_per_output_info *info;
243*61046927SAndroid Build Coastguard Worker
244*61046927SAndroid Build Coastguard Worker if (slot >= VARYING_SLOT_VAR0_16BIT) {
245*61046927SAndroid Build Coastguard Worker const unsigned index = slot - VARYING_SLOT_VAR0_16BIT;
246*61046927SAndroid Build Coastguard Worker
247*61046927SAndroid Build Coastguard Worker if (io_sem.high_16bits) {
248*61046927SAndroid Build Coastguard Worker output = out->outputs_16bit_hi[index];
249*61046927SAndroid Build Coastguard Worker type = out->types_16bit_hi[index];
250*61046927SAndroid Build Coastguard Worker info = &out->infos_16bit_hi[index];
251*61046927SAndroid Build Coastguard Worker } else {
252*61046927SAndroid Build Coastguard Worker output = out->outputs_16bit_lo[index];
253*61046927SAndroid Build Coastguard Worker type = out->types_16bit_lo[index];
254*61046927SAndroid Build Coastguard Worker info = &out->infos_16bit_lo[index];
255*61046927SAndroid Build Coastguard Worker }
256*61046927SAndroid Build Coastguard Worker } else {
257*61046927SAndroid Build Coastguard Worker output = out->outputs[slot];
258*61046927SAndroid Build Coastguard Worker type = out->types[slot];
259*61046927SAndroid Build Coastguard Worker info = &out->infos[slot];
260*61046927SAndroid Build Coastguard Worker }
261*61046927SAndroid Build Coastguard Worker
262*61046927SAndroid Build Coastguard Worker unsigned component_offset = nir_intrinsic_component(intrin);
263*61046927SAndroid Build Coastguard Worker unsigned write_mask = nir_intrinsic_write_mask(intrin);
264*61046927SAndroid Build Coastguard Worker nir_alu_type src_type = nir_intrinsic_src_type(intrin);
265*61046927SAndroid Build Coastguard Worker assert(nir_alu_type_get_type_size(src_type) == store_val->bit_size);
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&intrin->instr);
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker /* 16-bit output stored in a normal varying slot that isn't a dedicated 16-bit slot. */
270*61046927SAndroid Build Coastguard Worker const bool non_dedicated_16bit = slot < VARYING_SLOT_VAR0_16BIT && store_val->bit_size == 16;
271*61046927SAndroid Build Coastguard Worker
272*61046927SAndroid Build Coastguard Worker u_foreach_bit (i, write_mask) {
273*61046927SAndroid Build Coastguard Worker const unsigned stream = (io_sem.gs_streams >> (i * 2)) & 0x3;
274*61046927SAndroid Build Coastguard Worker
275*61046927SAndroid Build Coastguard Worker if (b->shader->info.stage == MESA_SHADER_GEOMETRY) {
276*61046927SAndroid Build Coastguard Worker if (!(b->shader->info.gs.active_stream_mask & (1 << stream)))
277*61046927SAndroid Build Coastguard Worker continue;
278*61046927SAndroid Build Coastguard Worker }
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker const unsigned c = component_offset + i;
281*61046927SAndroid Build Coastguard Worker
282*61046927SAndroid Build Coastguard Worker /* The same output component should always belong to the same stream. */
283*61046927SAndroid Build Coastguard Worker assert(!(info->components_mask & (1 << c)) ||
284*61046927SAndroid Build Coastguard Worker ((info->stream >> (c * 2)) & 3) == stream);
285*61046927SAndroid Build Coastguard Worker
286*61046927SAndroid Build Coastguard Worker /* Components of the same output slot may belong to different streams. */
287*61046927SAndroid Build Coastguard Worker info->stream |= stream << (c * 2);
288*61046927SAndroid Build Coastguard Worker info->components_mask |= BITFIELD_BIT(c);
289*61046927SAndroid Build Coastguard Worker
290*61046927SAndroid Build Coastguard Worker nir_def *store_component = nir_channel(b, intrin->src[0].ssa, i);
291*61046927SAndroid Build Coastguard Worker
292*61046927SAndroid Build Coastguard Worker if (non_dedicated_16bit) {
293*61046927SAndroid Build Coastguard Worker if (io_sem.high_16bits) {
294*61046927SAndroid Build Coastguard Worker nir_def *lo = output[c] ? nir_unpack_32_2x16_split_x(b, output[c]) : nir_imm_intN_t(b, 0, 16);
295*61046927SAndroid Build Coastguard Worker output[c] = nir_pack_32_2x16_split(b, lo, store_component);
296*61046927SAndroid Build Coastguard Worker } else {
297*61046927SAndroid Build Coastguard Worker nir_def *hi = output[c] ? nir_unpack_32_2x16_split_y(b, output[c]) : nir_imm_intN_t(b, 0, 16);
298*61046927SAndroid Build Coastguard Worker output[c] = nir_pack_32_2x16_split(b, store_component, hi);
299*61046927SAndroid Build Coastguard Worker }
300*61046927SAndroid Build Coastguard Worker type[c] = nir_type_uint32;
301*61046927SAndroid Build Coastguard Worker } else {
302*61046927SAndroid Build Coastguard Worker output[c] = store_component;
303*61046927SAndroid Build Coastguard Worker type[c] = src_type;
304*61046927SAndroid Build Coastguard Worker }
305*61046927SAndroid Build Coastguard Worker }
306*61046927SAndroid Build Coastguard Worker }
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker static nir_intrinsic_instr *
export(nir_builder * b,nir_def * val,nir_def * row,unsigned base,unsigned flags,unsigned write_mask)309*61046927SAndroid Build Coastguard Worker export(nir_builder *b, nir_def *val, nir_def *row, unsigned base, unsigned flags,
310*61046927SAndroid Build Coastguard Worker unsigned write_mask)
311*61046927SAndroid Build Coastguard Worker {
312*61046927SAndroid Build Coastguard Worker if (row) {
313*61046927SAndroid Build Coastguard Worker return nir_export_row_amd(b, val, row, .base = base, .flags = flags,
314*61046927SAndroid Build Coastguard Worker .write_mask = write_mask);
315*61046927SAndroid Build Coastguard Worker } else {
316*61046927SAndroid Build Coastguard Worker return nir_export_amd(b, val, .base = base, .flags = flags,
317*61046927SAndroid Build Coastguard Worker .write_mask = write_mask);
318*61046927SAndroid Build Coastguard Worker }
319*61046927SAndroid Build Coastguard Worker }
320*61046927SAndroid Build Coastguard Worker
321*61046927SAndroid Build Coastguard Worker void
ac_nir_export_primitive(nir_builder * b,nir_def * prim,nir_def * row)322*61046927SAndroid Build Coastguard Worker ac_nir_export_primitive(nir_builder *b, nir_def *prim, nir_def *row)
323*61046927SAndroid Build Coastguard Worker {
324*61046927SAndroid Build Coastguard Worker unsigned write_mask = BITFIELD_MASK(prim->num_components);
325*61046927SAndroid Build Coastguard Worker
326*61046927SAndroid Build Coastguard Worker export(b, nir_pad_vec4(b, prim), row, V_008DFC_SQ_EXP_PRIM, AC_EXP_FLAG_DONE,
327*61046927SAndroid Build Coastguard Worker write_mask);
328*61046927SAndroid Build Coastguard Worker }
329*61046927SAndroid Build Coastguard Worker
330*61046927SAndroid Build Coastguard Worker static nir_def *
get_export_output(nir_builder * b,nir_def ** output)331*61046927SAndroid Build Coastguard Worker get_export_output(nir_builder *b, nir_def **output)
332*61046927SAndroid Build Coastguard Worker {
333*61046927SAndroid Build Coastguard Worker nir_def *vec[4];
334*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
335*61046927SAndroid Build Coastguard Worker if (output[i])
336*61046927SAndroid Build Coastguard Worker vec[i] = nir_u2uN(b, output[i], 32);
337*61046927SAndroid Build Coastguard Worker else
338*61046927SAndroid Build Coastguard Worker vec[i] = nir_undef(b, 1, 32);
339*61046927SAndroid Build Coastguard Worker }
340*61046927SAndroid Build Coastguard Worker
341*61046927SAndroid Build Coastguard Worker return nir_vec(b, vec, 4);
342*61046927SAndroid Build Coastguard Worker }
343*61046927SAndroid Build Coastguard Worker
344*61046927SAndroid Build Coastguard Worker static nir_def *
get_pos0_output(nir_builder * b,nir_def ** output)345*61046927SAndroid Build Coastguard Worker get_pos0_output(nir_builder *b, nir_def **output)
346*61046927SAndroid Build Coastguard Worker {
347*61046927SAndroid Build Coastguard Worker /* Some applications don't write position but expect (0, 0, 0, 1)
348*61046927SAndroid Build Coastguard Worker * so use that value instead of undef when it isn't written.
349*61046927SAndroid Build Coastguard Worker */
350*61046927SAndroid Build Coastguard Worker nir_def *vec[4] = {0};
351*61046927SAndroid Build Coastguard Worker
352*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
353*61046927SAndroid Build Coastguard Worker if (output[i])
354*61046927SAndroid Build Coastguard Worker vec[i] = nir_u2u32(b, output[i]);
355*61046927SAndroid Build Coastguard Worker else
356*61046927SAndroid Build Coastguard Worker vec[i] = nir_imm_float(b, i == 3 ? 1.0 : 0.0);
357*61046927SAndroid Build Coastguard Worker }
358*61046927SAndroid Build Coastguard Worker
359*61046927SAndroid Build Coastguard Worker return nir_vec(b, vec, 4);
360*61046927SAndroid Build Coastguard Worker }
361*61046927SAndroid Build Coastguard Worker
362*61046927SAndroid Build Coastguard Worker void
ac_nir_export_position(nir_builder * b,enum amd_gfx_level gfx_level,uint32_t clip_cull_mask,bool no_param_export,bool force_vrs,bool done,uint64_t outputs_written,nir_def * (* outputs)[4],nir_def * row)363*61046927SAndroid Build Coastguard Worker ac_nir_export_position(nir_builder *b,
364*61046927SAndroid Build Coastguard Worker enum amd_gfx_level gfx_level,
365*61046927SAndroid Build Coastguard Worker uint32_t clip_cull_mask,
366*61046927SAndroid Build Coastguard Worker bool no_param_export,
367*61046927SAndroid Build Coastguard Worker bool force_vrs,
368*61046927SAndroid Build Coastguard Worker bool done,
369*61046927SAndroid Build Coastguard Worker uint64_t outputs_written,
370*61046927SAndroid Build Coastguard Worker nir_def *(*outputs)[4],
371*61046927SAndroid Build Coastguard Worker nir_def *row)
372*61046927SAndroid Build Coastguard Worker {
373*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *exp[4];
374*61046927SAndroid Build Coastguard Worker unsigned exp_num = 0;
375*61046927SAndroid Build Coastguard Worker unsigned exp_pos_offset = 0;
376*61046927SAndroid Build Coastguard Worker
377*61046927SAndroid Build Coastguard Worker if (outputs_written & VARYING_BIT_POS) {
378*61046927SAndroid Build Coastguard Worker /* GFX10 (Navi1x) skip POS0 exports if EXEC=0 and DONE=0, causing a hang.
379*61046927SAndroid Build Coastguard Worker * Setting valid_mask=1 prevents it and has no other effect.
380*61046927SAndroid Build Coastguard Worker */
381*61046927SAndroid Build Coastguard Worker const unsigned pos_flags = gfx_level == GFX10 ? AC_EXP_FLAG_VALID_MASK : 0;
382*61046927SAndroid Build Coastguard Worker nir_def *pos = get_pos0_output(b, outputs[VARYING_SLOT_POS]);
383*61046927SAndroid Build Coastguard Worker
384*61046927SAndroid Build Coastguard Worker exp[exp_num] = export(b, pos, row, V_008DFC_SQ_EXP_POS + exp_num, pos_flags, 0xf);
385*61046927SAndroid Build Coastguard Worker exp_num++;
386*61046927SAndroid Build Coastguard Worker } else {
387*61046927SAndroid Build Coastguard Worker exp_pos_offset++;
388*61046927SAndroid Build Coastguard Worker }
389*61046927SAndroid Build Coastguard Worker
390*61046927SAndroid Build Coastguard Worker uint64_t mask =
391*61046927SAndroid Build Coastguard Worker VARYING_BIT_PSIZ |
392*61046927SAndroid Build Coastguard Worker VARYING_BIT_EDGE |
393*61046927SAndroid Build Coastguard Worker VARYING_BIT_LAYER |
394*61046927SAndroid Build Coastguard Worker VARYING_BIT_VIEWPORT |
395*61046927SAndroid Build Coastguard Worker VARYING_BIT_PRIMITIVE_SHADING_RATE;
396*61046927SAndroid Build Coastguard Worker
397*61046927SAndroid Build Coastguard Worker /* clear output mask if no one written */
398*61046927SAndroid Build Coastguard Worker if (!outputs[VARYING_SLOT_PSIZ][0])
399*61046927SAndroid Build Coastguard Worker outputs_written &= ~VARYING_BIT_PSIZ;
400*61046927SAndroid Build Coastguard Worker if (!outputs[VARYING_SLOT_EDGE][0])
401*61046927SAndroid Build Coastguard Worker outputs_written &= ~VARYING_BIT_EDGE;
402*61046927SAndroid Build Coastguard Worker if (!outputs[VARYING_SLOT_PRIMITIVE_SHADING_RATE][0])
403*61046927SAndroid Build Coastguard Worker outputs_written &= ~VARYING_BIT_PRIMITIVE_SHADING_RATE;
404*61046927SAndroid Build Coastguard Worker if (!outputs[VARYING_SLOT_LAYER][0])
405*61046927SAndroid Build Coastguard Worker outputs_written &= ~VARYING_BIT_LAYER;
406*61046927SAndroid Build Coastguard Worker if (!outputs[VARYING_SLOT_VIEWPORT][0])
407*61046927SAndroid Build Coastguard Worker outputs_written &= ~VARYING_BIT_VIEWPORT;
408*61046927SAndroid Build Coastguard Worker
409*61046927SAndroid Build Coastguard Worker if ((outputs_written & mask) || force_vrs) {
410*61046927SAndroid Build Coastguard Worker nir_def *zero = nir_imm_float(b, 0);
411*61046927SAndroid Build Coastguard Worker nir_def *vec[4] = { zero, zero, zero, zero };
412*61046927SAndroid Build Coastguard Worker unsigned write_mask = 0;
413*61046927SAndroid Build Coastguard Worker
414*61046927SAndroid Build Coastguard Worker if (outputs_written & VARYING_BIT_PSIZ) {
415*61046927SAndroid Build Coastguard Worker vec[0] = outputs[VARYING_SLOT_PSIZ][0];
416*61046927SAndroid Build Coastguard Worker write_mask |= BITFIELD_BIT(0);
417*61046927SAndroid Build Coastguard Worker }
418*61046927SAndroid Build Coastguard Worker
419*61046927SAndroid Build Coastguard Worker if (outputs_written & VARYING_BIT_EDGE) {
420*61046927SAndroid Build Coastguard Worker vec[1] = nir_umin(b, outputs[VARYING_SLOT_EDGE][0], nir_imm_int(b, 1));
421*61046927SAndroid Build Coastguard Worker write_mask |= BITFIELD_BIT(1);
422*61046927SAndroid Build Coastguard Worker }
423*61046927SAndroid Build Coastguard Worker
424*61046927SAndroid Build Coastguard Worker nir_def *rates = NULL;
425*61046927SAndroid Build Coastguard Worker if (outputs_written & VARYING_BIT_PRIMITIVE_SHADING_RATE) {
426*61046927SAndroid Build Coastguard Worker rates = outputs[VARYING_SLOT_PRIMITIVE_SHADING_RATE][0];
427*61046927SAndroid Build Coastguard Worker } else if (force_vrs) {
428*61046927SAndroid Build Coastguard Worker /* If Pos.W != 1 (typical for non-GUI elements), use coarse shading. */
429*61046927SAndroid Build Coastguard Worker nir_def *pos_w = outputs[VARYING_SLOT_POS][3];
430*61046927SAndroid Build Coastguard Worker pos_w = pos_w ? nir_u2u32(b, pos_w) : nir_imm_float(b, 1.0);
431*61046927SAndroid Build Coastguard Worker nir_def *cond = nir_fneu_imm(b, pos_w, 1);
432*61046927SAndroid Build Coastguard Worker rates = nir_bcsel(b, cond, nir_load_force_vrs_rates_amd(b), nir_imm_int(b, 0));
433*61046927SAndroid Build Coastguard Worker }
434*61046927SAndroid Build Coastguard Worker
435*61046927SAndroid Build Coastguard Worker if (rates) {
436*61046927SAndroid Build Coastguard Worker vec[1] = nir_ior(b, vec[1], rates);
437*61046927SAndroid Build Coastguard Worker write_mask |= BITFIELD_BIT(1);
438*61046927SAndroid Build Coastguard Worker }
439*61046927SAndroid Build Coastguard Worker
440*61046927SAndroid Build Coastguard Worker if (outputs_written & VARYING_BIT_LAYER) {
441*61046927SAndroid Build Coastguard Worker vec[2] = outputs[VARYING_SLOT_LAYER][0];
442*61046927SAndroid Build Coastguard Worker write_mask |= BITFIELD_BIT(2);
443*61046927SAndroid Build Coastguard Worker }
444*61046927SAndroid Build Coastguard Worker
445*61046927SAndroid Build Coastguard Worker if (outputs_written & VARYING_BIT_VIEWPORT) {
446*61046927SAndroid Build Coastguard Worker if (gfx_level >= GFX9) {
447*61046927SAndroid Build Coastguard Worker /* GFX9 has the layer in [10:0] and the viewport index in [19:16]. */
448*61046927SAndroid Build Coastguard Worker nir_def *v = nir_ishl_imm(b, outputs[VARYING_SLOT_VIEWPORT][0], 16);
449*61046927SAndroid Build Coastguard Worker vec[2] = nir_ior(b, vec[2], v);
450*61046927SAndroid Build Coastguard Worker write_mask |= BITFIELD_BIT(2);
451*61046927SAndroid Build Coastguard Worker } else {
452*61046927SAndroid Build Coastguard Worker vec[3] = outputs[VARYING_SLOT_VIEWPORT][0];
453*61046927SAndroid Build Coastguard Worker write_mask |= BITFIELD_BIT(3);
454*61046927SAndroid Build Coastguard Worker }
455*61046927SAndroid Build Coastguard Worker }
456*61046927SAndroid Build Coastguard Worker
457*61046927SAndroid Build Coastguard Worker exp[exp_num] = export(b, nir_vec(b, vec, 4), row,
458*61046927SAndroid Build Coastguard Worker V_008DFC_SQ_EXP_POS + exp_num + exp_pos_offset,
459*61046927SAndroid Build Coastguard Worker 0, write_mask);
460*61046927SAndroid Build Coastguard Worker exp_num++;
461*61046927SAndroid Build Coastguard Worker }
462*61046927SAndroid Build Coastguard Worker
463*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
464*61046927SAndroid Build Coastguard Worker if ((outputs_written & (VARYING_BIT_CLIP_DIST0 << i)) &&
465*61046927SAndroid Build Coastguard Worker (clip_cull_mask & BITFIELD_RANGE(i * 4, 4))) {
466*61046927SAndroid Build Coastguard Worker exp[exp_num] = export(
467*61046927SAndroid Build Coastguard Worker b, get_export_output(b, outputs[VARYING_SLOT_CLIP_DIST0 + i]), row,
468*61046927SAndroid Build Coastguard Worker V_008DFC_SQ_EXP_POS + exp_num + exp_pos_offset, 0,
469*61046927SAndroid Build Coastguard Worker (clip_cull_mask >> (i * 4)) & 0xf);
470*61046927SAndroid Build Coastguard Worker exp_num++;
471*61046927SAndroid Build Coastguard Worker }
472*61046927SAndroid Build Coastguard Worker }
473*61046927SAndroid Build Coastguard Worker
474*61046927SAndroid Build Coastguard Worker if (outputs_written & VARYING_BIT_CLIP_VERTEX) {
475*61046927SAndroid Build Coastguard Worker nir_def *vtx = get_export_output(b, outputs[VARYING_SLOT_CLIP_VERTEX]);
476*61046927SAndroid Build Coastguard Worker
477*61046927SAndroid Build Coastguard Worker /* Clip distance for clip vertex to each user clip plane. */
478*61046927SAndroid Build Coastguard Worker nir_def *clip_dist[8] = {0};
479*61046927SAndroid Build Coastguard Worker u_foreach_bit (i, clip_cull_mask) {
480*61046927SAndroid Build Coastguard Worker nir_def *ucp = nir_load_user_clip_plane(b, .ucp_id = i);
481*61046927SAndroid Build Coastguard Worker clip_dist[i] = nir_fdot4(b, vtx, ucp);
482*61046927SAndroid Build Coastguard Worker }
483*61046927SAndroid Build Coastguard Worker
484*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
485*61046927SAndroid Build Coastguard Worker if (clip_cull_mask & BITFIELD_RANGE(i * 4, 4)) {
486*61046927SAndroid Build Coastguard Worker exp[exp_num] = export(
487*61046927SAndroid Build Coastguard Worker b, get_export_output(b, clip_dist + i * 4), row,
488*61046927SAndroid Build Coastguard Worker V_008DFC_SQ_EXP_POS + exp_num + exp_pos_offset, 0,
489*61046927SAndroid Build Coastguard Worker (clip_cull_mask >> (i * 4)) & 0xf);
490*61046927SAndroid Build Coastguard Worker exp_num++;
491*61046927SAndroid Build Coastguard Worker }
492*61046927SAndroid Build Coastguard Worker }
493*61046927SAndroid Build Coastguard Worker }
494*61046927SAndroid Build Coastguard Worker
495*61046927SAndroid Build Coastguard Worker if (!exp_num)
496*61046927SAndroid Build Coastguard Worker return;
497*61046927SAndroid Build Coastguard Worker
498*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *final_exp = exp[exp_num - 1];
499*61046927SAndroid Build Coastguard Worker
500*61046927SAndroid Build Coastguard Worker if (done) {
501*61046927SAndroid Build Coastguard Worker /* Specify that this is the last export */
502*61046927SAndroid Build Coastguard Worker const unsigned final_exp_flags = nir_intrinsic_flags(final_exp);
503*61046927SAndroid Build Coastguard Worker nir_intrinsic_set_flags(final_exp, final_exp_flags | AC_EXP_FLAG_DONE);
504*61046927SAndroid Build Coastguard Worker }
505*61046927SAndroid Build Coastguard Worker
506*61046927SAndroid Build Coastguard Worker /* If a shader has no param exports, rasterization can start before
507*61046927SAndroid Build Coastguard Worker * the shader finishes and thus memory stores might not finish before
508*61046927SAndroid Build Coastguard Worker * the pixel shader starts.
509*61046927SAndroid Build Coastguard Worker */
510*61046927SAndroid Build Coastguard Worker if (gfx_level >= GFX10 && no_param_export && b->shader->info.writes_memory) {
511*61046927SAndroid Build Coastguard Worker nir_cursor cursor = b->cursor;
512*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&final_exp->instr);
513*61046927SAndroid Build Coastguard Worker nir_scoped_memory_barrier(b, SCOPE_DEVICE, NIR_MEMORY_RELEASE,
514*61046927SAndroid Build Coastguard Worker nir_var_mem_ssbo | nir_var_mem_global | nir_var_image);
515*61046927SAndroid Build Coastguard Worker b->cursor = cursor;
516*61046927SAndroid Build Coastguard Worker }
517*61046927SAndroid Build Coastguard Worker }
518*61046927SAndroid Build Coastguard Worker
519*61046927SAndroid Build Coastguard Worker void
ac_nir_export_parameters(nir_builder * b,const uint8_t * param_offsets,uint64_t outputs_written,uint16_t outputs_written_16bit,nir_def * (* outputs)[4],nir_def * (* outputs_16bit_lo)[4],nir_def * (* outputs_16bit_hi)[4])520*61046927SAndroid Build Coastguard Worker ac_nir_export_parameters(nir_builder *b,
521*61046927SAndroid Build Coastguard Worker const uint8_t *param_offsets,
522*61046927SAndroid Build Coastguard Worker uint64_t outputs_written,
523*61046927SAndroid Build Coastguard Worker uint16_t outputs_written_16bit,
524*61046927SAndroid Build Coastguard Worker nir_def *(*outputs)[4],
525*61046927SAndroid Build Coastguard Worker nir_def *(*outputs_16bit_lo)[4],
526*61046927SAndroid Build Coastguard Worker nir_def *(*outputs_16bit_hi)[4])
527*61046927SAndroid Build Coastguard Worker {
528*61046927SAndroid Build Coastguard Worker uint32_t exported_params = 0;
529*61046927SAndroid Build Coastguard Worker
530*61046927SAndroid Build Coastguard Worker u_foreach_bit64 (slot, outputs_written) {
531*61046927SAndroid Build Coastguard Worker unsigned offset = param_offsets[slot];
532*61046927SAndroid Build Coastguard Worker if (offset > AC_EXP_PARAM_OFFSET_31)
533*61046927SAndroid Build Coastguard Worker continue;
534*61046927SAndroid Build Coastguard Worker
535*61046927SAndroid Build Coastguard Worker uint32_t write_mask = 0;
536*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
537*61046927SAndroid Build Coastguard Worker if (outputs[slot][i])
538*61046927SAndroid Build Coastguard Worker write_mask |= BITFIELD_BIT(i);
539*61046927SAndroid Build Coastguard Worker }
540*61046927SAndroid Build Coastguard Worker
541*61046927SAndroid Build Coastguard Worker /* no one set this output slot, we can skip the param export */
542*61046927SAndroid Build Coastguard Worker if (!write_mask)
543*61046927SAndroid Build Coastguard Worker continue;
544*61046927SAndroid Build Coastguard Worker
545*61046927SAndroid Build Coastguard Worker /* Since param_offsets[] can map multiple varying slots to the same
546*61046927SAndroid Build Coastguard Worker * param export index (that's radeonsi-specific behavior), we need to
547*61046927SAndroid Build Coastguard Worker * do this so as not to emit duplicated exports.
548*61046927SAndroid Build Coastguard Worker */
549*61046927SAndroid Build Coastguard Worker if (exported_params & BITFIELD_BIT(offset))
550*61046927SAndroid Build Coastguard Worker continue;
551*61046927SAndroid Build Coastguard Worker
552*61046927SAndroid Build Coastguard Worker nir_export_amd(
553*61046927SAndroid Build Coastguard Worker b, get_export_output(b, outputs[slot]),
554*61046927SAndroid Build Coastguard Worker .base = V_008DFC_SQ_EXP_PARAM + offset,
555*61046927SAndroid Build Coastguard Worker .write_mask = write_mask);
556*61046927SAndroid Build Coastguard Worker exported_params |= BITFIELD_BIT(offset);
557*61046927SAndroid Build Coastguard Worker }
558*61046927SAndroid Build Coastguard Worker
559*61046927SAndroid Build Coastguard Worker u_foreach_bit (slot, outputs_written_16bit) {
560*61046927SAndroid Build Coastguard Worker unsigned offset = param_offsets[VARYING_SLOT_VAR0_16BIT + slot];
561*61046927SAndroid Build Coastguard Worker if (offset > AC_EXP_PARAM_OFFSET_31)
562*61046927SAndroid Build Coastguard Worker continue;
563*61046927SAndroid Build Coastguard Worker
564*61046927SAndroid Build Coastguard Worker uint32_t write_mask = 0;
565*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
566*61046927SAndroid Build Coastguard Worker if (outputs_16bit_lo[slot][i] || outputs_16bit_hi[slot][i])
567*61046927SAndroid Build Coastguard Worker write_mask |= BITFIELD_BIT(i);
568*61046927SAndroid Build Coastguard Worker }
569*61046927SAndroid Build Coastguard Worker
570*61046927SAndroid Build Coastguard Worker /* no one set this output slot, we can skip the param export */
571*61046927SAndroid Build Coastguard Worker if (!write_mask)
572*61046927SAndroid Build Coastguard Worker continue;
573*61046927SAndroid Build Coastguard Worker
574*61046927SAndroid Build Coastguard Worker /* Since param_offsets[] can map multiple varying slots to the same
575*61046927SAndroid Build Coastguard Worker * param export index (that's radeonsi-specific behavior), we need to
576*61046927SAndroid Build Coastguard Worker * do this so as not to emit duplicated exports.
577*61046927SAndroid Build Coastguard Worker */
578*61046927SAndroid Build Coastguard Worker if (exported_params & BITFIELD_BIT(offset))
579*61046927SAndroid Build Coastguard Worker continue;
580*61046927SAndroid Build Coastguard Worker
581*61046927SAndroid Build Coastguard Worker nir_def *vec[4];
582*61046927SAndroid Build Coastguard Worker nir_def *undef = nir_undef(b, 1, 16);
583*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
584*61046927SAndroid Build Coastguard Worker nir_def *lo = outputs_16bit_lo[slot][i] ? outputs_16bit_lo[slot][i] : undef;
585*61046927SAndroid Build Coastguard Worker nir_def *hi = outputs_16bit_hi[slot][i] ? outputs_16bit_hi[slot][i] : undef;
586*61046927SAndroid Build Coastguard Worker vec[i] = nir_pack_32_2x16_split(b, lo, hi);
587*61046927SAndroid Build Coastguard Worker }
588*61046927SAndroid Build Coastguard Worker
589*61046927SAndroid Build Coastguard Worker nir_export_amd(
590*61046927SAndroid Build Coastguard Worker b, nir_vec(b, vec, 4),
591*61046927SAndroid Build Coastguard Worker .base = V_008DFC_SQ_EXP_PARAM + offset,
592*61046927SAndroid Build Coastguard Worker .write_mask = write_mask);
593*61046927SAndroid Build Coastguard Worker exported_params |= BITFIELD_BIT(offset);
594*61046927SAndroid Build Coastguard Worker }
595*61046927SAndroid Build Coastguard Worker }
596*61046927SAndroid Build Coastguard Worker
597*61046927SAndroid Build Coastguard Worker unsigned
ac_nir_map_io_location(unsigned location,uint64_t mask,ac_nir_map_io_driver_location map_io)598*61046927SAndroid Build Coastguard Worker ac_nir_map_io_location(unsigned location,
599*61046927SAndroid Build Coastguard Worker uint64_t mask,
600*61046927SAndroid Build Coastguard Worker ac_nir_map_io_driver_location map_io)
601*61046927SAndroid Build Coastguard Worker {
602*61046927SAndroid Build Coastguard Worker /* Unlinked shaders:
603*61046927SAndroid Build Coastguard Worker * We are unaware of the inputs of the next stage while lowering outputs.
604*61046927SAndroid Build Coastguard Worker * The driver needs to pass a callback to map varyings to a fixed location.
605*61046927SAndroid Build Coastguard Worker */
606*61046927SAndroid Build Coastguard Worker if (map_io)
607*61046927SAndroid Build Coastguard Worker return map_io(location);
608*61046927SAndroid Build Coastguard Worker
609*61046927SAndroid Build Coastguard Worker /* Linked shaders:
610*61046927SAndroid Build Coastguard Worker * Take advantage of knowledge of the inputs of the next stage when lowering outputs.
611*61046927SAndroid Build Coastguard Worker * Map varyings to a prefix sum of the IO mask to save space in LDS or VRAM.
612*61046927SAndroid Build Coastguard Worker */
613*61046927SAndroid Build Coastguard Worker assert(mask & BITFIELD64_BIT(location));
614*61046927SAndroid Build Coastguard Worker return util_bitcount64(mask & BITFIELD64_MASK(location));
615*61046927SAndroid Build Coastguard Worker }
616*61046927SAndroid Build Coastguard Worker
617*61046927SAndroid Build Coastguard Worker /**
618*61046927SAndroid Build Coastguard Worker * This function takes an I/O intrinsic like load/store_input,
619*61046927SAndroid Build Coastguard Worker * and emits a sequence that calculates the full offset of that instruction,
620*61046927SAndroid Build Coastguard Worker * including a stride to the base and component offsets.
621*61046927SAndroid Build Coastguard Worker */
622*61046927SAndroid Build Coastguard Worker nir_def *
ac_nir_calc_io_off(nir_builder * b,nir_intrinsic_instr * intrin,nir_def * base_stride,unsigned component_stride,unsigned mapped_driver_location)623*61046927SAndroid Build Coastguard Worker ac_nir_calc_io_off(nir_builder *b,
624*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intrin,
625*61046927SAndroid Build Coastguard Worker nir_def *base_stride,
626*61046927SAndroid Build Coastguard Worker unsigned component_stride,
627*61046927SAndroid Build Coastguard Worker unsigned mapped_driver_location)
628*61046927SAndroid Build Coastguard Worker {
629*61046927SAndroid Build Coastguard Worker /* base is the driver_location, which is in slots (1 slot = 4x4 bytes) */
630*61046927SAndroid Build Coastguard Worker nir_def *base_op = nir_imul_imm(b, base_stride, mapped_driver_location);
631*61046927SAndroid Build Coastguard Worker
632*61046927SAndroid Build Coastguard Worker /* offset should be interpreted in relation to the base,
633*61046927SAndroid Build Coastguard Worker * so the instruction effectively reads/writes another input/output
634*61046927SAndroid Build Coastguard Worker * when it has an offset
635*61046927SAndroid Build Coastguard Worker */
636*61046927SAndroid Build Coastguard Worker nir_def *offset_op = nir_imul(b, base_stride,
637*61046927SAndroid Build Coastguard Worker nir_get_io_offset_src(intrin)->ssa);
638*61046927SAndroid Build Coastguard Worker
639*61046927SAndroid Build Coastguard Worker /* component is in bytes */
640*61046927SAndroid Build Coastguard Worker unsigned const_op = nir_intrinsic_component(intrin) * component_stride;
641*61046927SAndroid Build Coastguard Worker
642*61046927SAndroid Build Coastguard Worker return nir_iadd_imm_nuw(b, nir_iadd_nuw(b, base_op, offset_op), const_op);
643*61046927SAndroid Build Coastguard Worker }
644*61046927SAndroid Build Coastguard Worker
645*61046927SAndroid Build Coastguard Worker bool
ac_nir_lower_indirect_derefs(nir_shader * shader,enum amd_gfx_level gfx_level)646*61046927SAndroid Build Coastguard Worker ac_nir_lower_indirect_derefs(nir_shader *shader,
647*61046927SAndroid Build Coastguard Worker enum amd_gfx_level gfx_level)
648*61046927SAndroid Build Coastguard Worker {
649*61046927SAndroid Build Coastguard Worker bool progress = false;
650*61046927SAndroid Build Coastguard Worker
651*61046927SAndroid Build Coastguard Worker /* Lower large variables to scratch first so that we won't bloat the
652*61046927SAndroid Build Coastguard Worker * shader by generating large if ladders for them. We later lower
653*61046927SAndroid Build Coastguard Worker * scratch to alloca's, assuming LLVM won't generate VGPR indexing.
654*61046927SAndroid Build Coastguard Worker */
655*61046927SAndroid Build Coastguard Worker NIR_PASS(progress, shader, nir_lower_vars_to_scratch, nir_var_function_temp, 256,
656*61046927SAndroid Build Coastguard Worker glsl_get_natural_size_align_bytes, glsl_get_natural_size_align_bytes);
657*61046927SAndroid Build Coastguard Worker
658*61046927SAndroid Build Coastguard Worker /* LLVM doesn't support VGPR indexing on GFX9. */
659*61046927SAndroid Build Coastguard Worker bool llvm_has_working_vgpr_indexing = gfx_level != GFX9;
660*61046927SAndroid Build Coastguard Worker
661*61046927SAndroid Build Coastguard Worker /* TODO: Indirect indexing of GS inputs is unimplemented.
662*61046927SAndroid Build Coastguard Worker *
663*61046927SAndroid Build Coastguard Worker * TCS and TES load inputs directly from LDS or offchip memory, so
664*61046927SAndroid Build Coastguard Worker * indirect indexing is trivial.
665*61046927SAndroid Build Coastguard Worker */
666*61046927SAndroid Build Coastguard Worker nir_variable_mode indirect_mask = 0;
667*61046927SAndroid Build Coastguard Worker if (shader->info.stage == MESA_SHADER_GEOMETRY ||
668*61046927SAndroid Build Coastguard Worker (shader->info.stage != MESA_SHADER_TESS_CTRL && shader->info.stage != MESA_SHADER_TESS_EVAL &&
669*61046927SAndroid Build Coastguard Worker !llvm_has_working_vgpr_indexing)) {
670*61046927SAndroid Build Coastguard Worker indirect_mask |= nir_var_shader_in;
671*61046927SAndroid Build Coastguard Worker }
672*61046927SAndroid Build Coastguard Worker if (!llvm_has_working_vgpr_indexing && shader->info.stage != MESA_SHADER_TESS_CTRL)
673*61046927SAndroid Build Coastguard Worker indirect_mask |= nir_var_shader_out;
674*61046927SAndroid Build Coastguard Worker
675*61046927SAndroid Build Coastguard Worker /* TODO: We shouldn't need to do this, however LLVM isn't currently
676*61046927SAndroid Build Coastguard Worker * smart enough to handle indirects without causing excess spilling
677*61046927SAndroid Build Coastguard Worker * causing the gpu to hang.
678*61046927SAndroid Build Coastguard Worker *
679*61046927SAndroid Build Coastguard Worker * See the following thread for more details of the problem:
680*61046927SAndroid Build Coastguard Worker * https://lists.freedesktop.org/archives/mesa-dev/2017-July/162106.html
681*61046927SAndroid Build Coastguard Worker */
682*61046927SAndroid Build Coastguard Worker indirect_mask |= nir_var_function_temp;
683*61046927SAndroid Build Coastguard Worker
684*61046927SAndroid Build Coastguard Worker NIR_PASS(progress, shader, nir_lower_indirect_derefs, indirect_mask, UINT32_MAX);
685*61046927SAndroid Build Coastguard Worker return progress;
686*61046927SAndroid Build Coastguard Worker }
687*61046927SAndroid Build Coastguard Worker
688*61046927SAndroid Build Coastguard Worker static nir_def **
get_output_and_type(ac_nir_prerast_out * out,unsigned slot,bool high_16bits,nir_alu_type ** types)689*61046927SAndroid Build Coastguard Worker get_output_and_type(ac_nir_prerast_out *out, unsigned slot, bool high_16bits,
690*61046927SAndroid Build Coastguard Worker nir_alu_type **types)
691*61046927SAndroid Build Coastguard Worker {
692*61046927SAndroid Build Coastguard Worker nir_def **data;
693*61046927SAndroid Build Coastguard Worker nir_alu_type *type;
694*61046927SAndroid Build Coastguard Worker
695*61046927SAndroid Build Coastguard Worker /* Only VARYING_SLOT_VARn_16BIT slots need output type to convert 16bit output
696*61046927SAndroid Build Coastguard Worker * to 32bit. Vulkan is not allowed to streamout output less than 32bit.
697*61046927SAndroid Build Coastguard Worker */
698*61046927SAndroid Build Coastguard Worker if (slot < VARYING_SLOT_VAR0_16BIT) {
699*61046927SAndroid Build Coastguard Worker data = out->outputs[slot];
700*61046927SAndroid Build Coastguard Worker type = NULL;
701*61046927SAndroid Build Coastguard Worker } else {
702*61046927SAndroid Build Coastguard Worker unsigned index = slot - VARYING_SLOT_VAR0_16BIT;
703*61046927SAndroid Build Coastguard Worker
704*61046927SAndroid Build Coastguard Worker if (high_16bits) {
705*61046927SAndroid Build Coastguard Worker data = out->outputs_16bit_hi[index];
706*61046927SAndroid Build Coastguard Worker type = out->types_16bit_hi[index];
707*61046927SAndroid Build Coastguard Worker } else {
708*61046927SAndroid Build Coastguard Worker data = out->outputs[index];
709*61046927SAndroid Build Coastguard Worker type = out->types_16bit_lo[index];
710*61046927SAndroid Build Coastguard Worker }
711*61046927SAndroid Build Coastguard Worker }
712*61046927SAndroid Build Coastguard Worker
713*61046927SAndroid Build Coastguard Worker *types = type;
714*61046927SAndroid Build Coastguard Worker return data;
715*61046927SAndroid Build Coastguard Worker }
716*61046927SAndroid Build Coastguard Worker
717*61046927SAndroid Build Coastguard Worker static void
emit_streamout(nir_builder * b,unsigned stream,nir_xfb_info * info,ac_nir_prerast_out * out)718*61046927SAndroid Build Coastguard Worker emit_streamout(nir_builder *b, unsigned stream, nir_xfb_info *info, ac_nir_prerast_out *out)
719*61046927SAndroid Build Coastguard Worker {
720*61046927SAndroid Build Coastguard Worker nir_def *so_vtx_count = nir_ubfe_imm(b, nir_load_streamout_config_amd(b), 16, 7);
721*61046927SAndroid Build Coastguard Worker nir_def *tid = nir_load_subgroup_invocation(b);
722*61046927SAndroid Build Coastguard Worker
723*61046927SAndroid Build Coastguard Worker nir_push_if(b, nir_ilt(b, tid, so_vtx_count));
724*61046927SAndroid Build Coastguard Worker nir_def *so_write_index = nir_load_streamout_write_index_amd(b);
725*61046927SAndroid Build Coastguard Worker
726*61046927SAndroid Build Coastguard Worker nir_def *so_buffers[NIR_MAX_XFB_BUFFERS];
727*61046927SAndroid Build Coastguard Worker nir_def *so_write_offset[NIR_MAX_XFB_BUFFERS];
728*61046927SAndroid Build Coastguard Worker u_foreach_bit(i, info->buffers_written) {
729*61046927SAndroid Build Coastguard Worker so_buffers[i] = nir_load_streamout_buffer_amd(b, i);
730*61046927SAndroid Build Coastguard Worker
731*61046927SAndroid Build Coastguard Worker unsigned stride = info->buffers[i].stride;
732*61046927SAndroid Build Coastguard Worker nir_def *offset = nir_load_streamout_offset_amd(b, i);
733*61046927SAndroid Build Coastguard Worker offset = nir_iadd(b, nir_imul_imm(b, nir_iadd(b, so_write_index, tid), stride),
734*61046927SAndroid Build Coastguard Worker nir_imul_imm(b, offset, 4));
735*61046927SAndroid Build Coastguard Worker so_write_offset[i] = offset;
736*61046927SAndroid Build Coastguard Worker }
737*61046927SAndroid Build Coastguard Worker
738*61046927SAndroid Build Coastguard Worker nir_def *undef = nir_undef(b, 1, 32);
739*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < info->output_count; i++) {
740*61046927SAndroid Build Coastguard Worker const nir_xfb_output_info *output = info->outputs + i;
741*61046927SAndroid Build Coastguard Worker if (stream != info->buffer_to_stream[output->buffer])
742*61046927SAndroid Build Coastguard Worker continue;
743*61046927SAndroid Build Coastguard Worker
744*61046927SAndroid Build Coastguard Worker nir_alu_type *output_type;
745*61046927SAndroid Build Coastguard Worker nir_def **output_data =
746*61046927SAndroid Build Coastguard Worker get_output_and_type(out, output->location, output->high_16bits, &output_type);
747*61046927SAndroid Build Coastguard Worker
748*61046927SAndroid Build Coastguard Worker nir_def *vec[4] = {undef, undef, undef, undef};
749*61046927SAndroid Build Coastguard Worker uint8_t mask = 0;
750*61046927SAndroid Build Coastguard Worker u_foreach_bit(j, output->component_mask) {
751*61046927SAndroid Build Coastguard Worker nir_def *data = output_data[j];
752*61046927SAndroid Build Coastguard Worker
753*61046927SAndroid Build Coastguard Worker if (data) {
754*61046927SAndroid Build Coastguard Worker if (data->bit_size < 32) {
755*61046927SAndroid Build Coastguard Worker /* we need output type to convert non-32bit output to 32bit */
756*61046927SAndroid Build Coastguard Worker assert(output_type);
757*61046927SAndroid Build Coastguard Worker
758*61046927SAndroid Build Coastguard Worker nir_alu_type base_type = nir_alu_type_get_base_type(output_type[j]);
759*61046927SAndroid Build Coastguard Worker data = nir_convert_to_bit_size(b, data, base_type, 32);
760*61046927SAndroid Build Coastguard Worker }
761*61046927SAndroid Build Coastguard Worker
762*61046927SAndroid Build Coastguard Worker unsigned comp = j - output->component_offset;
763*61046927SAndroid Build Coastguard Worker vec[comp] = data;
764*61046927SAndroid Build Coastguard Worker mask |= 1 << comp;
765*61046927SAndroid Build Coastguard Worker }
766*61046927SAndroid Build Coastguard Worker }
767*61046927SAndroid Build Coastguard Worker
768*61046927SAndroid Build Coastguard Worker if (!mask)
769*61046927SAndroid Build Coastguard Worker continue;
770*61046927SAndroid Build Coastguard Worker
771*61046927SAndroid Build Coastguard Worker unsigned buffer = output->buffer;
772*61046927SAndroid Build Coastguard Worker nir_def *data = nir_vec(b, vec, util_last_bit(mask));
773*61046927SAndroid Build Coastguard Worker nir_def *zero = nir_imm_int(b, 0);
774*61046927SAndroid Build Coastguard Worker nir_store_buffer_amd(b, data, so_buffers[buffer], so_write_offset[buffer], zero, zero,
775*61046927SAndroid Build Coastguard Worker .base = output->offset, .write_mask = mask,
776*61046927SAndroid Build Coastguard Worker .access = ACCESS_COHERENT | ACCESS_NON_TEMPORAL);
777*61046927SAndroid Build Coastguard Worker }
778*61046927SAndroid Build Coastguard Worker
779*61046927SAndroid Build Coastguard Worker nir_pop_if(b, NULL);
780*61046927SAndroid Build Coastguard Worker }
781*61046927SAndroid Build Coastguard Worker
782*61046927SAndroid Build Coastguard Worker nir_shader *
ac_nir_create_gs_copy_shader(const nir_shader * gs_nir,enum amd_gfx_level gfx_level,uint32_t clip_cull_mask,const uint8_t * param_offsets,bool has_param_exports,bool disable_streamout,bool kill_pointsize,bool kill_layer,bool force_vrs,ac_nir_gs_output_info * output_info)783*61046927SAndroid Build Coastguard Worker ac_nir_create_gs_copy_shader(const nir_shader *gs_nir,
784*61046927SAndroid Build Coastguard Worker enum amd_gfx_level gfx_level,
785*61046927SAndroid Build Coastguard Worker uint32_t clip_cull_mask,
786*61046927SAndroid Build Coastguard Worker const uint8_t *param_offsets,
787*61046927SAndroid Build Coastguard Worker bool has_param_exports,
788*61046927SAndroid Build Coastguard Worker bool disable_streamout,
789*61046927SAndroid Build Coastguard Worker bool kill_pointsize,
790*61046927SAndroid Build Coastguard Worker bool kill_layer,
791*61046927SAndroid Build Coastguard Worker bool force_vrs,
792*61046927SAndroid Build Coastguard Worker ac_nir_gs_output_info *output_info)
793*61046927SAndroid Build Coastguard Worker {
794*61046927SAndroid Build Coastguard Worker nir_builder b = nir_builder_init_simple_shader(
795*61046927SAndroid Build Coastguard Worker MESA_SHADER_VERTEX, gs_nir->options, "gs_copy");
796*61046927SAndroid Build Coastguard Worker
797*61046927SAndroid Build Coastguard Worker nir_foreach_shader_out_variable(var, gs_nir)
798*61046927SAndroid Build Coastguard Worker nir_shader_add_variable(b.shader, nir_variable_clone(var, b.shader));
799*61046927SAndroid Build Coastguard Worker
800*61046927SAndroid Build Coastguard Worker b.shader->info.outputs_written = gs_nir->info.outputs_written;
801*61046927SAndroid Build Coastguard Worker b.shader->info.outputs_written_16bit = gs_nir->info.outputs_written_16bit;
802*61046927SAndroid Build Coastguard Worker
803*61046927SAndroid Build Coastguard Worker nir_def *gsvs_ring = nir_load_ring_gsvs_amd(&b);
804*61046927SAndroid Build Coastguard Worker
805*61046927SAndroid Build Coastguard Worker nir_xfb_info *info = gs_nir->xfb_info;
806*61046927SAndroid Build Coastguard Worker nir_def *stream_id = NULL;
807*61046927SAndroid Build Coastguard Worker if (!disable_streamout && info)
808*61046927SAndroid Build Coastguard Worker stream_id = nir_ubfe_imm(&b, nir_load_streamout_config_amd(&b), 24, 2);
809*61046927SAndroid Build Coastguard Worker
810*61046927SAndroid Build Coastguard Worker nir_def *vtx_offset = nir_imul_imm(&b, nir_load_vertex_id_zero_base(&b), 4);
811*61046927SAndroid Build Coastguard Worker nir_def *zero = nir_imm_zero(&b, 1, 32);
812*61046927SAndroid Build Coastguard Worker
813*61046927SAndroid Build Coastguard Worker for (unsigned stream = 0; stream < 4; stream++) {
814*61046927SAndroid Build Coastguard Worker if (stream > 0 && (!stream_id || !(info->streams_written & BITFIELD_BIT(stream))))
815*61046927SAndroid Build Coastguard Worker continue;
816*61046927SAndroid Build Coastguard Worker
817*61046927SAndroid Build Coastguard Worker if (stream_id)
818*61046927SAndroid Build Coastguard Worker nir_push_if(&b, nir_ieq_imm(&b, stream_id, stream));
819*61046927SAndroid Build Coastguard Worker
820*61046927SAndroid Build Coastguard Worker uint32_t offset = 0;
821*61046927SAndroid Build Coastguard Worker ac_nir_prerast_out out = {0};
822*61046927SAndroid Build Coastguard Worker if (output_info->types_16bit_lo)
823*61046927SAndroid Build Coastguard Worker memcpy(&out.types_16bit_lo, output_info->types_16bit_lo, sizeof(out.types_16bit_lo));
824*61046927SAndroid Build Coastguard Worker if (output_info->types_16bit_hi)
825*61046927SAndroid Build Coastguard Worker memcpy(&out.types_16bit_hi, output_info->types_16bit_hi, sizeof(out.types_16bit_hi));
826*61046927SAndroid Build Coastguard Worker
827*61046927SAndroid Build Coastguard Worker u_foreach_bit64 (i, gs_nir->info.outputs_written) {
828*61046927SAndroid Build Coastguard Worker u_foreach_bit (j, output_info->usage_mask[i]) {
829*61046927SAndroid Build Coastguard Worker if (((output_info->streams[i] >> (j * 2)) & 0x3) != stream)
830*61046927SAndroid Build Coastguard Worker continue;
831*61046927SAndroid Build Coastguard Worker
832*61046927SAndroid Build Coastguard Worker out.outputs[i][j] =
833*61046927SAndroid Build Coastguard Worker nir_load_buffer_amd(&b, 1, 32, gsvs_ring, vtx_offset, zero, zero,
834*61046927SAndroid Build Coastguard Worker .base = offset,
835*61046927SAndroid Build Coastguard Worker .access = ACCESS_COHERENT | ACCESS_NON_TEMPORAL);
836*61046927SAndroid Build Coastguard Worker
837*61046927SAndroid Build Coastguard Worker /* clamp legacy color output */
838*61046927SAndroid Build Coastguard Worker if (i == VARYING_SLOT_COL0 || i == VARYING_SLOT_COL1 ||
839*61046927SAndroid Build Coastguard Worker i == VARYING_SLOT_BFC0 || i == VARYING_SLOT_BFC1) {
840*61046927SAndroid Build Coastguard Worker nir_def *color = out.outputs[i][j];
841*61046927SAndroid Build Coastguard Worker nir_def *clamp = nir_load_clamp_vertex_color_amd(&b);
842*61046927SAndroid Build Coastguard Worker out.outputs[i][j] = nir_bcsel(&b, clamp, nir_fsat(&b, color), color);
843*61046927SAndroid Build Coastguard Worker }
844*61046927SAndroid Build Coastguard Worker
845*61046927SAndroid Build Coastguard Worker offset += gs_nir->info.gs.vertices_out * 16 * 4;
846*61046927SAndroid Build Coastguard Worker }
847*61046927SAndroid Build Coastguard Worker }
848*61046927SAndroid Build Coastguard Worker
849*61046927SAndroid Build Coastguard Worker u_foreach_bit (i, gs_nir->info.outputs_written_16bit) {
850*61046927SAndroid Build Coastguard Worker for (unsigned j = 0; j < 4; j++) {
851*61046927SAndroid Build Coastguard Worker bool has_lo_16bit = (output_info->usage_mask_16bit_lo[i] & (1 << j)) &&
852*61046927SAndroid Build Coastguard Worker ((output_info->streams_16bit_lo[i] >> (j * 2)) & 0x3) == stream;
853*61046927SAndroid Build Coastguard Worker bool has_hi_16bit = (output_info->usage_mask_16bit_hi[i] & (1 << j)) &&
854*61046927SAndroid Build Coastguard Worker ((output_info->streams_16bit_hi[i] >> (j * 2)) & 0x3) == stream;
855*61046927SAndroid Build Coastguard Worker if (!has_lo_16bit && !has_hi_16bit)
856*61046927SAndroid Build Coastguard Worker continue;
857*61046927SAndroid Build Coastguard Worker
858*61046927SAndroid Build Coastguard Worker nir_def *data =
859*61046927SAndroid Build Coastguard Worker nir_load_buffer_amd(&b, 1, 32, gsvs_ring, vtx_offset, zero, zero,
860*61046927SAndroid Build Coastguard Worker .base = offset,
861*61046927SAndroid Build Coastguard Worker .access = ACCESS_COHERENT | ACCESS_NON_TEMPORAL);
862*61046927SAndroid Build Coastguard Worker
863*61046927SAndroid Build Coastguard Worker if (has_lo_16bit)
864*61046927SAndroid Build Coastguard Worker out.outputs_16bit_lo[i][j] = nir_unpack_32_2x16_split_x(&b, data);
865*61046927SAndroid Build Coastguard Worker
866*61046927SAndroid Build Coastguard Worker if (has_hi_16bit)
867*61046927SAndroid Build Coastguard Worker out.outputs_16bit_hi[i][j] = nir_unpack_32_2x16_split_y(&b, data);
868*61046927SAndroid Build Coastguard Worker
869*61046927SAndroid Build Coastguard Worker offset += gs_nir->info.gs.vertices_out * 16 * 4;
870*61046927SAndroid Build Coastguard Worker }
871*61046927SAndroid Build Coastguard Worker }
872*61046927SAndroid Build Coastguard Worker
873*61046927SAndroid Build Coastguard Worker if (stream_id)
874*61046927SAndroid Build Coastguard Worker emit_streamout(&b, stream, info, &out);
875*61046927SAndroid Build Coastguard Worker
876*61046927SAndroid Build Coastguard Worker if (stream == 0) {
877*61046927SAndroid Build Coastguard Worker uint64_t export_outputs = b.shader->info.outputs_written | VARYING_BIT_POS;
878*61046927SAndroid Build Coastguard Worker if (kill_pointsize)
879*61046927SAndroid Build Coastguard Worker export_outputs &= ~VARYING_BIT_PSIZ;
880*61046927SAndroid Build Coastguard Worker if (kill_layer)
881*61046927SAndroid Build Coastguard Worker export_outputs &= ~VARYING_BIT_LAYER;
882*61046927SAndroid Build Coastguard Worker
883*61046927SAndroid Build Coastguard Worker ac_nir_export_position(&b, gfx_level, clip_cull_mask, !has_param_exports,
884*61046927SAndroid Build Coastguard Worker force_vrs, true, export_outputs, out.outputs, NULL);
885*61046927SAndroid Build Coastguard Worker
886*61046927SAndroid Build Coastguard Worker if (has_param_exports) {
887*61046927SAndroid Build Coastguard Worker ac_nir_export_parameters(&b, param_offsets,
888*61046927SAndroid Build Coastguard Worker b.shader->info.outputs_written,
889*61046927SAndroid Build Coastguard Worker b.shader->info.outputs_written_16bit,
890*61046927SAndroid Build Coastguard Worker out.outputs,
891*61046927SAndroid Build Coastguard Worker out.outputs_16bit_lo,
892*61046927SAndroid Build Coastguard Worker out.outputs_16bit_hi);
893*61046927SAndroid Build Coastguard Worker }
894*61046927SAndroid Build Coastguard Worker }
895*61046927SAndroid Build Coastguard Worker
896*61046927SAndroid Build Coastguard Worker if (stream_id)
897*61046927SAndroid Build Coastguard Worker nir_push_else(&b, NULL);
898*61046927SAndroid Build Coastguard Worker }
899*61046927SAndroid Build Coastguard Worker
900*61046927SAndroid Build Coastguard Worker b.shader->info.clip_distance_array_size = gs_nir->info.clip_distance_array_size;
901*61046927SAndroid Build Coastguard Worker b.shader->info.cull_distance_array_size = gs_nir->info.cull_distance_array_size;
902*61046927SAndroid Build Coastguard Worker
903*61046927SAndroid Build Coastguard Worker return b.shader;
904*61046927SAndroid Build Coastguard Worker }
905*61046927SAndroid Build Coastguard Worker
906*61046927SAndroid Build Coastguard Worker static void
gather_outputs(nir_builder * b,nir_function_impl * impl,ac_nir_prerast_out * out)907*61046927SAndroid Build Coastguard Worker gather_outputs(nir_builder *b, nir_function_impl *impl, ac_nir_prerast_out *out)
908*61046927SAndroid Build Coastguard Worker {
909*61046927SAndroid Build Coastguard Worker /* Assume:
910*61046927SAndroid Build Coastguard Worker * - the shader used nir_lower_io_to_temporaries
911*61046927SAndroid Build Coastguard Worker * - 64-bit outputs are lowered
912*61046927SAndroid Build Coastguard Worker * - no indirect indexing is present
913*61046927SAndroid Build Coastguard Worker */
914*61046927SAndroid Build Coastguard Worker nir_foreach_block (block, impl) {
915*61046927SAndroid Build Coastguard Worker nir_foreach_instr_safe (instr, block) {
916*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_intrinsic)
917*61046927SAndroid Build Coastguard Worker continue;
918*61046927SAndroid Build Coastguard Worker
919*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
920*61046927SAndroid Build Coastguard Worker if (intrin->intrinsic != nir_intrinsic_store_output)
921*61046927SAndroid Build Coastguard Worker continue;
922*61046927SAndroid Build Coastguard Worker
923*61046927SAndroid Build Coastguard Worker ac_nir_gather_prerast_store_output_info(b, intrin, out);
924*61046927SAndroid Build Coastguard Worker nir_instr_remove(instr);
925*61046927SAndroid Build Coastguard Worker }
926*61046927SAndroid Build Coastguard Worker }
927*61046927SAndroid Build Coastguard Worker }
928*61046927SAndroid Build Coastguard Worker
929*61046927SAndroid Build Coastguard Worker void
ac_nir_lower_legacy_vs(nir_shader * nir,enum amd_gfx_level gfx_level,uint32_t clip_cull_mask,const uint8_t * param_offsets,bool has_param_exports,bool export_primitive_id,bool disable_streamout,bool kill_pointsize,bool kill_layer,bool force_vrs)930*61046927SAndroid Build Coastguard Worker ac_nir_lower_legacy_vs(nir_shader *nir,
931*61046927SAndroid Build Coastguard Worker enum amd_gfx_level gfx_level,
932*61046927SAndroid Build Coastguard Worker uint32_t clip_cull_mask,
933*61046927SAndroid Build Coastguard Worker const uint8_t *param_offsets,
934*61046927SAndroid Build Coastguard Worker bool has_param_exports,
935*61046927SAndroid Build Coastguard Worker bool export_primitive_id,
936*61046927SAndroid Build Coastguard Worker bool disable_streamout,
937*61046927SAndroid Build Coastguard Worker bool kill_pointsize,
938*61046927SAndroid Build Coastguard Worker bool kill_layer,
939*61046927SAndroid Build Coastguard Worker bool force_vrs)
940*61046927SAndroid Build Coastguard Worker {
941*61046927SAndroid Build Coastguard Worker nir_function_impl *impl = nir_shader_get_entrypoint(nir);
942*61046927SAndroid Build Coastguard Worker nir_metadata preserved = nir_metadata_control_flow;
943*61046927SAndroid Build Coastguard Worker
944*61046927SAndroid Build Coastguard Worker nir_builder b = nir_builder_at(nir_after_impl(impl));
945*61046927SAndroid Build Coastguard Worker
946*61046927SAndroid Build Coastguard Worker ac_nir_prerast_out out = {0};
947*61046927SAndroid Build Coastguard Worker gather_outputs(&b, impl, &out);
948*61046927SAndroid Build Coastguard Worker b.cursor = nir_after_impl(impl);
949*61046927SAndroid Build Coastguard Worker
950*61046927SAndroid Build Coastguard Worker if (export_primitive_id) {
951*61046927SAndroid Build Coastguard Worker /* When the primitive ID is read by FS, we must ensure that it's exported by the previous
952*61046927SAndroid Build Coastguard Worker * vertex stage because it's implicit for VS or TES (but required by the Vulkan spec for GS
953*61046927SAndroid Build Coastguard Worker * or MS).
954*61046927SAndroid Build Coastguard Worker */
955*61046927SAndroid Build Coastguard Worker out.outputs[VARYING_SLOT_PRIMITIVE_ID][0] = nir_load_primitive_id(&b);
956*61046927SAndroid Build Coastguard Worker
957*61046927SAndroid Build Coastguard Worker /* Update outputs_written to reflect that the pass added a new output. */
958*61046927SAndroid Build Coastguard Worker nir->info.outputs_written |= BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID);
959*61046927SAndroid Build Coastguard Worker }
960*61046927SAndroid Build Coastguard Worker
961*61046927SAndroid Build Coastguard Worker if (!disable_streamout && nir->xfb_info) {
962*61046927SAndroid Build Coastguard Worker emit_streamout(&b, 0, nir->xfb_info, &out);
963*61046927SAndroid Build Coastguard Worker preserved = nir_metadata_none;
964*61046927SAndroid Build Coastguard Worker }
965*61046927SAndroid Build Coastguard Worker
966*61046927SAndroid Build Coastguard Worker uint64_t export_outputs = nir->info.outputs_written | VARYING_BIT_POS;
967*61046927SAndroid Build Coastguard Worker if (kill_pointsize)
968*61046927SAndroid Build Coastguard Worker export_outputs &= ~VARYING_BIT_PSIZ;
969*61046927SAndroid Build Coastguard Worker if (kill_layer)
970*61046927SAndroid Build Coastguard Worker export_outputs &= ~VARYING_BIT_LAYER;
971*61046927SAndroid Build Coastguard Worker
972*61046927SAndroid Build Coastguard Worker ac_nir_export_position(&b, gfx_level, clip_cull_mask, !has_param_exports,
973*61046927SAndroid Build Coastguard Worker force_vrs, true, export_outputs, out.outputs, NULL);
974*61046927SAndroid Build Coastguard Worker
975*61046927SAndroid Build Coastguard Worker if (has_param_exports) {
976*61046927SAndroid Build Coastguard Worker ac_nir_export_parameters(&b, param_offsets,
977*61046927SAndroid Build Coastguard Worker nir->info.outputs_written,
978*61046927SAndroid Build Coastguard Worker nir->info.outputs_written_16bit,
979*61046927SAndroid Build Coastguard Worker out.outputs,
980*61046927SAndroid Build Coastguard Worker out.outputs_16bit_lo,
981*61046927SAndroid Build Coastguard Worker out.outputs_16bit_hi);
982*61046927SAndroid Build Coastguard Worker }
983*61046927SAndroid Build Coastguard Worker
984*61046927SAndroid Build Coastguard Worker nir_metadata_preserve(impl, preserved);
985*61046927SAndroid Build Coastguard Worker }
986*61046927SAndroid Build Coastguard Worker
987*61046927SAndroid Build Coastguard Worker static nir_def *
ac_nir_accum_ior(nir_builder * b,nir_def * accum_result,nir_def * new_term)988*61046927SAndroid Build Coastguard Worker ac_nir_accum_ior(nir_builder *b, nir_def *accum_result, nir_def *new_term)
989*61046927SAndroid Build Coastguard Worker {
990*61046927SAndroid Build Coastguard Worker return accum_result ? nir_ior(b, accum_result, new_term) : new_term;
991*61046927SAndroid Build Coastguard Worker }
992*61046927SAndroid Build Coastguard Worker
993*61046927SAndroid Build Coastguard Worker bool
ac_nir_gs_shader_query(nir_builder * b,bool has_gen_prim_query,bool has_gs_invocations_query,bool has_gs_primitives_query,unsigned num_vertices_per_primitive,unsigned wave_size,nir_def * vertex_count[4],nir_def * primitive_count[4])994*61046927SAndroid Build Coastguard Worker ac_nir_gs_shader_query(nir_builder *b,
995*61046927SAndroid Build Coastguard Worker bool has_gen_prim_query,
996*61046927SAndroid Build Coastguard Worker bool has_gs_invocations_query,
997*61046927SAndroid Build Coastguard Worker bool has_gs_primitives_query,
998*61046927SAndroid Build Coastguard Worker unsigned num_vertices_per_primitive,
999*61046927SAndroid Build Coastguard Worker unsigned wave_size,
1000*61046927SAndroid Build Coastguard Worker nir_def *vertex_count[4],
1001*61046927SAndroid Build Coastguard Worker nir_def *primitive_count[4])
1002*61046927SAndroid Build Coastguard Worker {
1003*61046927SAndroid Build Coastguard Worker nir_def *pipeline_query_enabled = NULL;
1004*61046927SAndroid Build Coastguard Worker nir_def *prim_gen_query_enabled = NULL;
1005*61046927SAndroid Build Coastguard Worker nir_def *any_query_enabled = NULL;
1006*61046927SAndroid Build Coastguard Worker
1007*61046927SAndroid Build Coastguard Worker if (has_gen_prim_query) {
1008*61046927SAndroid Build Coastguard Worker prim_gen_query_enabled = nir_load_prim_gen_query_enabled_amd(b);
1009*61046927SAndroid Build Coastguard Worker any_query_enabled = ac_nir_accum_ior(b, any_query_enabled, prim_gen_query_enabled);
1010*61046927SAndroid Build Coastguard Worker }
1011*61046927SAndroid Build Coastguard Worker
1012*61046927SAndroid Build Coastguard Worker if (has_gs_invocations_query || has_gs_primitives_query) {
1013*61046927SAndroid Build Coastguard Worker pipeline_query_enabled = nir_load_pipeline_stat_query_enabled_amd(b);
1014*61046927SAndroid Build Coastguard Worker any_query_enabled = ac_nir_accum_ior(b, any_query_enabled, pipeline_query_enabled);
1015*61046927SAndroid Build Coastguard Worker }
1016*61046927SAndroid Build Coastguard Worker
1017*61046927SAndroid Build Coastguard Worker if (!any_query_enabled) {
1018*61046927SAndroid Build Coastguard Worker /* has no query */
1019*61046927SAndroid Build Coastguard Worker return false;
1020*61046927SAndroid Build Coastguard Worker }
1021*61046927SAndroid Build Coastguard Worker
1022*61046927SAndroid Build Coastguard Worker nir_if *if_shader_query = nir_push_if(b, any_query_enabled);
1023*61046927SAndroid Build Coastguard Worker
1024*61046927SAndroid Build Coastguard Worker nir_def *active_threads_mask = nir_ballot(b, 1, wave_size, nir_imm_true(b));
1025*61046927SAndroid Build Coastguard Worker nir_def *num_active_threads = nir_bit_count(b, active_threads_mask);
1026*61046927SAndroid Build Coastguard Worker
1027*61046927SAndroid Build Coastguard Worker /* Calculate the "real" number of emitted primitives from the emitted GS vertices and primitives.
1028*61046927SAndroid Build Coastguard Worker * GS emits points, line strips or triangle strips.
1029*61046927SAndroid Build Coastguard Worker * Real primitives are points, lines or triangles.
1030*61046927SAndroid Build Coastguard Worker */
1031*61046927SAndroid Build Coastguard Worker nir_def *num_prims_in_wave[4] = {0};
1032*61046927SAndroid Build Coastguard Worker u_foreach_bit (i, b->shader->info.gs.active_stream_mask) {
1033*61046927SAndroid Build Coastguard Worker assert(vertex_count[i] && primitive_count[i]);
1034*61046927SAndroid Build Coastguard Worker
1035*61046927SAndroid Build Coastguard Worker nir_scalar vtx_cnt = nir_get_scalar(vertex_count[i], 0);
1036*61046927SAndroid Build Coastguard Worker nir_scalar prm_cnt = nir_get_scalar(primitive_count[i], 0);
1037*61046927SAndroid Build Coastguard Worker
1038*61046927SAndroid Build Coastguard Worker if (nir_scalar_is_const(vtx_cnt) && nir_scalar_is_const(prm_cnt)) {
1039*61046927SAndroid Build Coastguard Worker unsigned gs_vtx_cnt = nir_scalar_as_uint(vtx_cnt);
1040*61046927SAndroid Build Coastguard Worker unsigned gs_prm_cnt = nir_scalar_as_uint(prm_cnt);
1041*61046927SAndroid Build Coastguard Worker unsigned total_prm_cnt = gs_vtx_cnt - gs_prm_cnt * (num_vertices_per_primitive - 1u);
1042*61046927SAndroid Build Coastguard Worker if (total_prm_cnt == 0)
1043*61046927SAndroid Build Coastguard Worker continue;
1044*61046927SAndroid Build Coastguard Worker
1045*61046927SAndroid Build Coastguard Worker num_prims_in_wave[i] = nir_imul_imm(b, num_active_threads, total_prm_cnt);
1046*61046927SAndroid Build Coastguard Worker } else {
1047*61046927SAndroid Build Coastguard Worker nir_def *gs_vtx_cnt = vtx_cnt.def;
1048*61046927SAndroid Build Coastguard Worker nir_def *gs_prm_cnt = prm_cnt.def;
1049*61046927SAndroid Build Coastguard Worker if (num_vertices_per_primitive > 1)
1050*61046927SAndroid Build Coastguard Worker gs_prm_cnt = nir_iadd(b, nir_imul_imm(b, gs_prm_cnt, -1u * (num_vertices_per_primitive - 1)), gs_vtx_cnt);
1051*61046927SAndroid Build Coastguard Worker num_prims_in_wave[i] = nir_reduce(b, gs_prm_cnt, .reduction_op = nir_op_iadd);
1052*61046927SAndroid Build Coastguard Worker }
1053*61046927SAndroid Build Coastguard Worker }
1054*61046927SAndroid Build Coastguard Worker
1055*61046927SAndroid Build Coastguard Worker /* Store the query result to query result using an atomic add. */
1056*61046927SAndroid Build Coastguard Worker nir_if *if_first_lane = nir_push_if(b, nir_elect(b, 1));
1057*61046927SAndroid Build Coastguard Worker {
1058*61046927SAndroid Build Coastguard Worker if (has_gs_invocations_query || has_gs_primitives_query) {
1059*61046927SAndroid Build Coastguard Worker nir_if *if_pipeline_query = nir_push_if(b, pipeline_query_enabled);
1060*61046927SAndroid Build Coastguard Worker {
1061*61046927SAndroid Build Coastguard Worker nir_def *count = NULL;
1062*61046927SAndroid Build Coastguard Worker
1063*61046927SAndroid Build Coastguard Worker /* Add all streams' number to the same counter. */
1064*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
1065*61046927SAndroid Build Coastguard Worker if (num_prims_in_wave[i]) {
1066*61046927SAndroid Build Coastguard Worker if (count)
1067*61046927SAndroid Build Coastguard Worker count = nir_iadd(b, count, num_prims_in_wave[i]);
1068*61046927SAndroid Build Coastguard Worker else
1069*61046927SAndroid Build Coastguard Worker count = num_prims_in_wave[i];
1070*61046927SAndroid Build Coastguard Worker }
1071*61046927SAndroid Build Coastguard Worker }
1072*61046927SAndroid Build Coastguard Worker
1073*61046927SAndroid Build Coastguard Worker if (has_gs_primitives_query && count)
1074*61046927SAndroid Build Coastguard Worker nir_atomic_add_gs_emit_prim_count_amd(b, count);
1075*61046927SAndroid Build Coastguard Worker
1076*61046927SAndroid Build Coastguard Worker if (has_gs_invocations_query)
1077*61046927SAndroid Build Coastguard Worker nir_atomic_add_shader_invocation_count_amd(b, num_active_threads);
1078*61046927SAndroid Build Coastguard Worker }
1079*61046927SAndroid Build Coastguard Worker nir_pop_if(b, if_pipeline_query);
1080*61046927SAndroid Build Coastguard Worker }
1081*61046927SAndroid Build Coastguard Worker
1082*61046927SAndroid Build Coastguard Worker if (has_gen_prim_query) {
1083*61046927SAndroid Build Coastguard Worker nir_if *if_prim_gen_query = nir_push_if(b, prim_gen_query_enabled);
1084*61046927SAndroid Build Coastguard Worker {
1085*61046927SAndroid Build Coastguard Worker /* Add to the counter for this stream. */
1086*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
1087*61046927SAndroid Build Coastguard Worker if (num_prims_in_wave[i])
1088*61046927SAndroid Build Coastguard Worker nir_atomic_add_gen_prim_count_amd(b, num_prims_in_wave[i], .stream_id = i);
1089*61046927SAndroid Build Coastguard Worker }
1090*61046927SAndroid Build Coastguard Worker }
1091*61046927SAndroid Build Coastguard Worker nir_pop_if(b, if_prim_gen_query);
1092*61046927SAndroid Build Coastguard Worker }
1093*61046927SAndroid Build Coastguard Worker }
1094*61046927SAndroid Build Coastguard Worker nir_pop_if(b, if_first_lane);
1095*61046927SAndroid Build Coastguard Worker
1096*61046927SAndroid Build Coastguard Worker nir_pop_if(b, if_shader_query);
1097*61046927SAndroid Build Coastguard Worker return true;
1098*61046927SAndroid Build Coastguard Worker }
1099*61046927SAndroid Build Coastguard Worker
1100*61046927SAndroid Build Coastguard Worker typedef struct {
1101*61046927SAndroid Build Coastguard Worker nir_def *outputs[64][4];
1102*61046927SAndroid Build Coastguard Worker nir_def *outputs_16bit_lo[16][4];
1103*61046927SAndroid Build Coastguard Worker nir_def *outputs_16bit_hi[16][4];
1104*61046927SAndroid Build Coastguard Worker
1105*61046927SAndroid Build Coastguard Worker ac_nir_gs_output_info *info;
1106*61046927SAndroid Build Coastguard Worker
1107*61046927SAndroid Build Coastguard Worker nir_def *vertex_count[4];
1108*61046927SAndroid Build Coastguard Worker nir_def *primitive_count[4];
1109*61046927SAndroid Build Coastguard Worker } lower_legacy_gs_state;
1110*61046927SAndroid Build Coastguard Worker
1111*61046927SAndroid Build Coastguard Worker static bool
lower_legacy_gs_store_output(nir_builder * b,nir_intrinsic_instr * intrin,lower_legacy_gs_state * s)1112*61046927SAndroid Build Coastguard Worker lower_legacy_gs_store_output(nir_builder *b, nir_intrinsic_instr *intrin,
1113*61046927SAndroid Build Coastguard Worker lower_legacy_gs_state *s)
1114*61046927SAndroid Build Coastguard Worker {
1115*61046927SAndroid Build Coastguard Worker /* Assume:
1116*61046927SAndroid Build Coastguard Worker * - the shader used nir_lower_io_to_temporaries
1117*61046927SAndroid Build Coastguard Worker * - 64-bit outputs are lowered
1118*61046927SAndroid Build Coastguard Worker * - no indirect indexing is present
1119*61046927SAndroid Build Coastguard Worker */
1120*61046927SAndroid Build Coastguard Worker assert(nir_src_is_const(intrin->src[1]) && !nir_src_as_uint(intrin->src[1]));
1121*61046927SAndroid Build Coastguard Worker
1122*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&intrin->instr);
1123*61046927SAndroid Build Coastguard Worker
1124*61046927SAndroid Build Coastguard Worker unsigned component = nir_intrinsic_component(intrin);
1125*61046927SAndroid Build Coastguard Worker unsigned write_mask = nir_intrinsic_write_mask(intrin);
1126*61046927SAndroid Build Coastguard Worker nir_io_semantics sem = nir_intrinsic_io_semantics(intrin);
1127*61046927SAndroid Build Coastguard Worker
1128*61046927SAndroid Build Coastguard Worker nir_def **outputs;
1129*61046927SAndroid Build Coastguard Worker if (sem.location < VARYING_SLOT_VAR0_16BIT) {
1130*61046927SAndroid Build Coastguard Worker outputs = s->outputs[sem.location];
1131*61046927SAndroid Build Coastguard Worker } else {
1132*61046927SAndroid Build Coastguard Worker unsigned index = sem.location - VARYING_SLOT_VAR0_16BIT;
1133*61046927SAndroid Build Coastguard Worker if (sem.high_16bits)
1134*61046927SAndroid Build Coastguard Worker outputs = s->outputs_16bit_hi[index];
1135*61046927SAndroid Build Coastguard Worker else
1136*61046927SAndroid Build Coastguard Worker outputs = s->outputs_16bit_lo[index];
1137*61046927SAndroid Build Coastguard Worker }
1138*61046927SAndroid Build Coastguard Worker
1139*61046927SAndroid Build Coastguard Worker nir_def *store_val = intrin->src[0].ssa;
1140*61046927SAndroid Build Coastguard Worker /* 64bit output has been lowered to 32bit */
1141*61046927SAndroid Build Coastguard Worker assert(store_val->bit_size <= 32);
1142*61046927SAndroid Build Coastguard Worker
1143*61046927SAndroid Build Coastguard Worker /* 16-bit output stored in a normal varying slot that isn't a dedicated 16-bit slot. */
1144*61046927SAndroid Build Coastguard Worker const bool non_dedicated_16bit = sem.location < VARYING_SLOT_VAR0_16BIT && store_val->bit_size == 16;
1145*61046927SAndroid Build Coastguard Worker
1146*61046927SAndroid Build Coastguard Worker u_foreach_bit (i, write_mask) {
1147*61046927SAndroid Build Coastguard Worker unsigned comp = component + i;
1148*61046927SAndroid Build Coastguard Worker nir_def *store_component = nir_channel(b, store_val, i);
1149*61046927SAndroid Build Coastguard Worker
1150*61046927SAndroid Build Coastguard Worker if (non_dedicated_16bit) {
1151*61046927SAndroid Build Coastguard Worker if (sem.high_16bits) {
1152*61046927SAndroid Build Coastguard Worker nir_def *lo = outputs[comp] ? nir_unpack_32_2x16_split_x(b, outputs[comp]) : nir_imm_intN_t(b, 0, 16);
1153*61046927SAndroid Build Coastguard Worker outputs[comp] = nir_pack_32_2x16_split(b, lo, store_component);
1154*61046927SAndroid Build Coastguard Worker } else {
1155*61046927SAndroid Build Coastguard Worker nir_def *hi = outputs[comp] ? nir_unpack_32_2x16_split_y(b, outputs[comp]) : nir_imm_intN_t(b, 0, 16);
1156*61046927SAndroid Build Coastguard Worker outputs[comp] = nir_pack_32_2x16_split(b, store_component, hi);
1157*61046927SAndroid Build Coastguard Worker }
1158*61046927SAndroid Build Coastguard Worker } else {
1159*61046927SAndroid Build Coastguard Worker outputs[comp] = store_component;
1160*61046927SAndroid Build Coastguard Worker }
1161*61046927SAndroid Build Coastguard Worker }
1162*61046927SAndroid Build Coastguard Worker
1163*61046927SAndroid Build Coastguard Worker nir_instr_remove(&intrin->instr);
1164*61046927SAndroid Build Coastguard Worker return true;
1165*61046927SAndroid Build Coastguard Worker }
1166*61046927SAndroid Build Coastguard Worker
1167*61046927SAndroid Build Coastguard Worker static bool
lower_legacy_gs_emit_vertex_with_counter(nir_builder * b,nir_intrinsic_instr * intrin,lower_legacy_gs_state * s)1168*61046927SAndroid Build Coastguard Worker lower_legacy_gs_emit_vertex_with_counter(nir_builder *b, nir_intrinsic_instr *intrin,
1169*61046927SAndroid Build Coastguard Worker lower_legacy_gs_state *s)
1170*61046927SAndroid Build Coastguard Worker {
1171*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&intrin->instr);
1172*61046927SAndroid Build Coastguard Worker
1173*61046927SAndroid Build Coastguard Worker unsigned stream = nir_intrinsic_stream_id(intrin);
1174*61046927SAndroid Build Coastguard Worker nir_def *vtxidx = intrin->src[0].ssa;
1175*61046927SAndroid Build Coastguard Worker
1176*61046927SAndroid Build Coastguard Worker nir_def *gsvs_ring = nir_load_ring_gsvs_amd(b, .stream_id = stream);
1177*61046927SAndroid Build Coastguard Worker nir_def *soffset = nir_load_ring_gs2vs_offset_amd(b);
1178*61046927SAndroid Build Coastguard Worker
1179*61046927SAndroid Build Coastguard Worker unsigned offset = 0;
1180*61046927SAndroid Build Coastguard Worker u_foreach_bit64 (i, b->shader->info.outputs_written) {
1181*61046927SAndroid Build Coastguard Worker for (unsigned j = 0; j < 4; j++) {
1182*61046927SAndroid Build Coastguard Worker nir_def *output = s->outputs[i][j];
1183*61046927SAndroid Build Coastguard Worker /* Next vertex emit need a new value, reset all outputs. */
1184*61046927SAndroid Build Coastguard Worker s->outputs[i][j] = NULL;
1185*61046927SAndroid Build Coastguard Worker
1186*61046927SAndroid Build Coastguard Worker if (!(s->info->usage_mask[i] & (1 << j)) ||
1187*61046927SAndroid Build Coastguard Worker ((s->info->streams[i] >> (j * 2)) & 0x3) != stream)
1188*61046927SAndroid Build Coastguard Worker continue;
1189*61046927SAndroid Build Coastguard Worker
1190*61046927SAndroid Build Coastguard Worker unsigned base = offset * b->shader->info.gs.vertices_out * 4;
1191*61046927SAndroid Build Coastguard Worker offset++;
1192*61046927SAndroid Build Coastguard Worker
1193*61046927SAndroid Build Coastguard Worker /* no one set this output, skip the buffer store */
1194*61046927SAndroid Build Coastguard Worker if (!output)
1195*61046927SAndroid Build Coastguard Worker continue;
1196*61046927SAndroid Build Coastguard Worker
1197*61046927SAndroid Build Coastguard Worker nir_def *voffset = nir_ishl_imm(b, vtxidx, 2);
1198*61046927SAndroid Build Coastguard Worker
1199*61046927SAndroid Build Coastguard Worker /* extend 8/16 bit to 32 bit, 64 bit has been lowered */
1200*61046927SAndroid Build Coastguard Worker nir_def *data = nir_u2uN(b, output, 32);
1201*61046927SAndroid Build Coastguard Worker
1202*61046927SAndroid Build Coastguard Worker nir_store_buffer_amd(b, data, gsvs_ring, voffset, soffset, nir_imm_int(b, 0),
1203*61046927SAndroid Build Coastguard Worker .access = ACCESS_COHERENT | ACCESS_NON_TEMPORAL |
1204*61046927SAndroid Build Coastguard Worker ACCESS_IS_SWIZZLED_AMD,
1205*61046927SAndroid Build Coastguard Worker .base = base,
1206*61046927SAndroid Build Coastguard Worker /* For ACO to not reorder this store around EmitVertex/EndPrimitve */
1207*61046927SAndroid Build Coastguard Worker .memory_modes = nir_var_shader_out);
1208*61046927SAndroid Build Coastguard Worker }
1209*61046927SAndroid Build Coastguard Worker }
1210*61046927SAndroid Build Coastguard Worker
1211*61046927SAndroid Build Coastguard Worker u_foreach_bit (i, b->shader->info.outputs_written_16bit) {
1212*61046927SAndroid Build Coastguard Worker for (unsigned j = 0; j < 4; j++) {
1213*61046927SAndroid Build Coastguard Worker nir_def *output_lo = s->outputs_16bit_lo[i][j];
1214*61046927SAndroid Build Coastguard Worker nir_def *output_hi = s->outputs_16bit_hi[i][j];
1215*61046927SAndroid Build Coastguard Worker /* Next vertex emit need a new value, reset all outputs. */
1216*61046927SAndroid Build Coastguard Worker s->outputs_16bit_lo[i][j] = NULL;
1217*61046927SAndroid Build Coastguard Worker s->outputs_16bit_hi[i][j] = NULL;
1218*61046927SAndroid Build Coastguard Worker
1219*61046927SAndroid Build Coastguard Worker bool has_lo_16bit = (s->info->usage_mask_16bit_lo[i] & (1 << j)) &&
1220*61046927SAndroid Build Coastguard Worker ((s->info->streams_16bit_lo[i] >> (j * 2)) & 0x3) == stream;
1221*61046927SAndroid Build Coastguard Worker bool has_hi_16bit = (s->info->usage_mask_16bit_hi[i] & (1 << j)) &&
1222*61046927SAndroid Build Coastguard Worker ((s->info->streams_16bit_hi[i] >> (j * 2)) & 0x3) == stream;
1223*61046927SAndroid Build Coastguard Worker if (!has_lo_16bit && !has_hi_16bit)
1224*61046927SAndroid Build Coastguard Worker continue;
1225*61046927SAndroid Build Coastguard Worker
1226*61046927SAndroid Build Coastguard Worker unsigned base = offset * b->shader->info.gs.vertices_out;
1227*61046927SAndroid Build Coastguard Worker offset++;
1228*61046927SAndroid Build Coastguard Worker
1229*61046927SAndroid Build Coastguard Worker bool has_lo_16bit_out = has_lo_16bit && output_lo;
1230*61046927SAndroid Build Coastguard Worker bool has_hi_16bit_out = has_hi_16bit && output_hi;
1231*61046927SAndroid Build Coastguard Worker
1232*61046927SAndroid Build Coastguard Worker /* no one set needed output, skip the buffer store */
1233*61046927SAndroid Build Coastguard Worker if (!has_lo_16bit_out && !has_hi_16bit_out)
1234*61046927SAndroid Build Coastguard Worker continue;
1235*61046927SAndroid Build Coastguard Worker
1236*61046927SAndroid Build Coastguard Worker if (!has_lo_16bit_out)
1237*61046927SAndroid Build Coastguard Worker output_lo = nir_undef(b, 1, 16);
1238*61046927SAndroid Build Coastguard Worker
1239*61046927SAndroid Build Coastguard Worker if (!has_hi_16bit_out)
1240*61046927SAndroid Build Coastguard Worker output_hi = nir_undef(b, 1, 16);
1241*61046927SAndroid Build Coastguard Worker
1242*61046927SAndroid Build Coastguard Worker nir_def *voffset = nir_iadd_imm(b, vtxidx, base);
1243*61046927SAndroid Build Coastguard Worker voffset = nir_ishl_imm(b, voffset, 2);
1244*61046927SAndroid Build Coastguard Worker
1245*61046927SAndroid Build Coastguard Worker nir_store_buffer_amd(b, nir_pack_32_2x16_split(b, output_lo, output_hi),
1246*61046927SAndroid Build Coastguard Worker gsvs_ring, voffset, soffset, nir_imm_int(b, 0),
1247*61046927SAndroid Build Coastguard Worker .access = ACCESS_COHERENT | ACCESS_NON_TEMPORAL |
1248*61046927SAndroid Build Coastguard Worker ACCESS_IS_SWIZZLED_AMD,
1249*61046927SAndroid Build Coastguard Worker /* For ACO to not reorder this store around EmitVertex/EndPrimitve */
1250*61046927SAndroid Build Coastguard Worker .memory_modes = nir_var_shader_out);
1251*61046927SAndroid Build Coastguard Worker }
1252*61046927SAndroid Build Coastguard Worker }
1253*61046927SAndroid Build Coastguard Worker
1254*61046927SAndroid Build Coastguard Worker /* Signal vertex emission. */
1255*61046927SAndroid Build Coastguard Worker nir_sendmsg_amd(b, nir_load_gs_wave_id_amd(b),
1256*61046927SAndroid Build Coastguard Worker .base = AC_SENDMSG_GS_OP_EMIT | AC_SENDMSG_GS | (stream << 8));
1257*61046927SAndroid Build Coastguard Worker
1258*61046927SAndroid Build Coastguard Worker nir_instr_remove(&intrin->instr);
1259*61046927SAndroid Build Coastguard Worker return true;
1260*61046927SAndroid Build Coastguard Worker }
1261*61046927SAndroid Build Coastguard Worker
1262*61046927SAndroid Build Coastguard Worker static bool
lower_legacy_gs_set_vertex_and_primitive_count(nir_builder * b,nir_intrinsic_instr * intrin,lower_legacy_gs_state * s)1263*61046927SAndroid Build Coastguard Worker lower_legacy_gs_set_vertex_and_primitive_count(nir_builder *b, nir_intrinsic_instr *intrin,
1264*61046927SAndroid Build Coastguard Worker lower_legacy_gs_state *s)
1265*61046927SAndroid Build Coastguard Worker {
1266*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&intrin->instr);
1267*61046927SAndroid Build Coastguard Worker
1268*61046927SAndroid Build Coastguard Worker unsigned stream = nir_intrinsic_stream_id(intrin);
1269*61046927SAndroid Build Coastguard Worker
1270*61046927SAndroid Build Coastguard Worker s->vertex_count[stream] = intrin->src[0].ssa;
1271*61046927SAndroid Build Coastguard Worker s->primitive_count[stream] = intrin->src[1].ssa;
1272*61046927SAndroid Build Coastguard Worker
1273*61046927SAndroid Build Coastguard Worker nir_instr_remove(&intrin->instr);
1274*61046927SAndroid Build Coastguard Worker return true;
1275*61046927SAndroid Build Coastguard Worker }
1276*61046927SAndroid Build Coastguard Worker
1277*61046927SAndroid Build Coastguard Worker static bool
lower_legacy_gs_end_primitive_with_counter(nir_builder * b,nir_intrinsic_instr * intrin,lower_legacy_gs_state * s)1278*61046927SAndroid Build Coastguard Worker lower_legacy_gs_end_primitive_with_counter(nir_builder *b, nir_intrinsic_instr *intrin,
1279*61046927SAndroid Build Coastguard Worker lower_legacy_gs_state *s)
1280*61046927SAndroid Build Coastguard Worker {
1281*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&intrin->instr);
1282*61046927SAndroid Build Coastguard Worker const unsigned stream = nir_intrinsic_stream_id(intrin);
1283*61046927SAndroid Build Coastguard Worker
1284*61046927SAndroid Build Coastguard Worker /* Signal primitive emission. */
1285*61046927SAndroid Build Coastguard Worker nir_sendmsg_amd(b, nir_load_gs_wave_id_amd(b),
1286*61046927SAndroid Build Coastguard Worker .base = AC_SENDMSG_GS_OP_CUT | AC_SENDMSG_GS | (stream << 8));
1287*61046927SAndroid Build Coastguard Worker
1288*61046927SAndroid Build Coastguard Worker nir_instr_remove(&intrin->instr);
1289*61046927SAndroid Build Coastguard Worker return true;
1290*61046927SAndroid Build Coastguard Worker }
1291*61046927SAndroid Build Coastguard Worker
1292*61046927SAndroid Build Coastguard Worker static bool
lower_legacy_gs_intrinsic(nir_builder * b,nir_instr * instr,void * state)1293*61046927SAndroid Build Coastguard Worker lower_legacy_gs_intrinsic(nir_builder *b, nir_instr *instr, void *state)
1294*61046927SAndroid Build Coastguard Worker {
1295*61046927SAndroid Build Coastguard Worker lower_legacy_gs_state *s = (lower_legacy_gs_state *) state;
1296*61046927SAndroid Build Coastguard Worker
1297*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_intrinsic)
1298*61046927SAndroid Build Coastguard Worker return false;
1299*61046927SAndroid Build Coastguard Worker
1300*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
1301*61046927SAndroid Build Coastguard Worker
1302*61046927SAndroid Build Coastguard Worker if (intrin->intrinsic == nir_intrinsic_store_output)
1303*61046927SAndroid Build Coastguard Worker return lower_legacy_gs_store_output(b, intrin, s);
1304*61046927SAndroid Build Coastguard Worker else if (intrin->intrinsic == nir_intrinsic_emit_vertex_with_counter)
1305*61046927SAndroid Build Coastguard Worker return lower_legacy_gs_emit_vertex_with_counter(b, intrin, s);
1306*61046927SAndroid Build Coastguard Worker else if (intrin->intrinsic == nir_intrinsic_end_primitive_with_counter)
1307*61046927SAndroid Build Coastguard Worker return lower_legacy_gs_end_primitive_with_counter(b, intrin, s);
1308*61046927SAndroid Build Coastguard Worker else if (intrin->intrinsic == nir_intrinsic_set_vertex_and_primitive_count)
1309*61046927SAndroid Build Coastguard Worker return lower_legacy_gs_set_vertex_and_primitive_count(b, intrin, s);
1310*61046927SAndroid Build Coastguard Worker
1311*61046927SAndroid Build Coastguard Worker return false;
1312*61046927SAndroid Build Coastguard Worker }
1313*61046927SAndroid Build Coastguard Worker
1314*61046927SAndroid Build Coastguard Worker void
ac_nir_lower_legacy_gs(nir_shader * nir,bool has_gen_prim_query,bool has_pipeline_stats_query,ac_nir_gs_output_info * output_info)1315*61046927SAndroid Build Coastguard Worker ac_nir_lower_legacy_gs(nir_shader *nir,
1316*61046927SAndroid Build Coastguard Worker bool has_gen_prim_query,
1317*61046927SAndroid Build Coastguard Worker bool has_pipeline_stats_query,
1318*61046927SAndroid Build Coastguard Worker ac_nir_gs_output_info *output_info)
1319*61046927SAndroid Build Coastguard Worker {
1320*61046927SAndroid Build Coastguard Worker lower_legacy_gs_state s = {
1321*61046927SAndroid Build Coastguard Worker .info = output_info,
1322*61046927SAndroid Build Coastguard Worker };
1323*61046927SAndroid Build Coastguard Worker
1324*61046927SAndroid Build Coastguard Worker unsigned num_vertices_per_primitive = 0;
1325*61046927SAndroid Build Coastguard Worker switch (nir->info.gs.output_primitive) {
1326*61046927SAndroid Build Coastguard Worker case MESA_PRIM_POINTS:
1327*61046927SAndroid Build Coastguard Worker num_vertices_per_primitive = 1;
1328*61046927SAndroid Build Coastguard Worker break;
1329*61046927SAndroid Build Coastguard Worker case MESA_PRIM_LINE_STRIP:
1330*61046927SAndroid Build Coastguard Worker num_vertices_per_primitive = 2;
1331*61046927SAndroid Build Coastguard Worker break;
1332*61046927SAndroid Build Coastguard Worker case MESA_PRIM_TRIANGLE_STRIP:
1333*61046927SAndroid Build Coastguard Worker num_vertices_per_primitive = 3;
1334*61046927SAndroid Build Coastguard Worker break;
1335*61046927SAndroid Build Coastguard Worker default:
1336*61046927SAndroid Build Coastguard Worker unreachable("Invalid GS output primitive.");
1337*61046927SAndroid Build Coastguard Worker break;
1338*61046927SAndroid Build Coastguard Worker }
1339*61046927SAndroid Build Coastguard Worker
1340*61046927SAndroid Build Coastguard Worker nir_shader_instructions_pass(nir, lower_legacy_gs_intrinsic,
1341*61046927SAndroid Build Coastguard Worker nir_metadata_control_flow, &s);
1342*61046927SAndroid Build Coastguard Worker
1343*61046927SAndroid Build Coastguard Worker nir_function_impl *impl = nir_shader_get_entrypoint(nir);
1344*61046927SAndroid Build Coastguard Worker
1345*61046927SAndroid Build Coastguard Worker nir_builder builder = nir_builder_at(nir_after_impl(impl));
1346*61046927SAndroid Build Coastguard Worker nir_builder *b = &builder;
1347*61046927SAndroid Build Coastguard Worker
1348*61046927SAndroid Build Coastguard Worker /* Emit shader query for mix use legacy/NGG GS */
1349*61046927SAndroid Build Coastguard Worker bool progress = ac_nir_gs_shader_query(b,
1350*61046927SAndroid Build Coastguard Worker has_gen_prim_query,
1351*61046927SAndroid Build Coastguard Worker has_pipeline_stats_query,
1352*61046927SAndroid Build Coastguard Worker has_pipeline_stats_query,
1353*61046927SAndroid Build Coastguard Worker num_vertices_per_primitive,
1354*61046927SAndroid Build Coastguard Worker 64,
1355*61046927SAndroid Build Coastguard Worker s.vertex_count,
1356*61046927SAndroid Build Coastguard Worker s.primitive_count);
1357*61046927SAndroid Build Coastguard Worker
1358*61046927SAndroid Build Coastguard Worker /* Wait for all stores to finish. */
1359*61046927SAndroid Build Coastguard Worker nir_barrier(b, .execution_scope = SCOPE_INVOCATION,
1360*61046927SAndroid Build Coastguard Worker .memory_scope = SCOPE_DEVICE,
1361*61046927SAndroid Build Coastguard Worker .memory_semantics = NIR_MEMORY_RELEASE,
1362*61046927SAndroid Build Coastguard Worker .memory_modes = nir_var_shader_out | nir_var_mem_ssbo |
1363*61046927SAndroid Build Coastguard Worker nir_var_mem_global | nir_var_image);
1364*61046927SAndroid Build Coastguard Worker
1365*61046927SAndroid Build Coastguard Worker /* Signal that the GS is done. */
1366*61046927SAndroid Build Coastguard Worker nir_sendmsg_amd(b, nir_load_gs_wave_id_amd(b),
1367*61046927SAndroid Build Coastguard Worker .base = AC_SENDMSG_GS_OP_NOP | AC_SENDMSG_GS_DONE);
1368*61046927SAndroid Build Coastguard Worker
1369*61046927SAndroid Build Coastguard Worker if (progress)
1370*61046927SAndroid Build Coastguard Worker nir_metadata_preserve(impl, nir_metadata_none);
1371*61046927SAndroid Build Coastguard Worker }
1372*61046927SAndroid Build Coastguard Worker
1373*61046927SAndroid Build Coastguard Worker /* Shader logging function for printing nir_def values. The driver prints this after
1374*61046927SAndroid Build Coastguard Worker * command submission.
1375*61046927SAndroid Build Coastguard Worker *
1376*61046927SAndroid Build Coastguard Worker * Ring buffer layout: {uint32_t num_dwords; vec4; vec4; vec4; ... }
1377*61046927SAndroid Build Coastguard Worker * - The buffer size must be 2^N * 16 + 4
1378*61046927SAndroid Build Coastguard Worker * - num_dwords is incremented atomically and the ring wraps around, removing
1379*61046927SAndroid Build Coastguard Worker * the oldest entries.
1380*61046927SAndroid Build Coastguard Worker */
1381*61046927SAndroid Build Coastguard Worker void
ac_nir_store_debug_log_amd(nir_builder * b,nir_def * uvec4)1382*61046927SAndroid Build Coastguard Worker ac_nir_store_debug_log_amd(nir_builder *b, nir_def *uvec4)
1383*61046927SAndroid Build Coastguard Worker {
1384*61046927SAndroid Build Coastguard Worker nir_def *buf = nir_load_debug_log_desc_amd(b);
1385*61046927SAndroid Build Coastguard Worker nir_def *zero = nir_imm_int(b, 0);
1386*61046927SAndroid Build Coastguard Worker
1387*61046927SAndroid Build Coastguard Worker nir_def *max_index =
1388*61046927SAndroid Build Coastguard Worker nir_iadd_imm(b, nir_ushr_imm(b, nir_iadd_imm(b, nir_channel(b, buf, 2), -4), 4), -1);
1389*61046927SAndroid Build Coastguard Worker nir_def *index = nir_ssbo_atomic(b, 32, buf, zero, nir_imm_int(b, 1),
1390*61046927SAndroid Build Coastguard Worker .atomic_op = nir_atomic_op_iadd);
1391*61046927SAndroid Build Coastguard Worker index = nir_iand(b, index, max_index);
1392*61046927SAndroid Build Coastguard Worker nir_def *offset = nir_iadd_imm(b, nir_imul_imm(b, index, 16), 4);
1393*61046927SAndroid Build Coastguard Worker nir_store_buffer_amd(b, uvec4, buf, offset, zero, zero);
1394*61046927SAndroid Build Coastguard Worker }
1395*61046927SAndroid Build Coastguard Worker
1396*61046927SAndroid Build Coastguard Worker static bool
needs_rounding_mode_16_64(nir_instr * instr)1397*61046927SAndroid Build Coastguard Worker needs_rounding_mode_16_64(nir_instr *instr)
1398*61046927SAndroid Build Coastguard Worker {
1399*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_alu)
1400*61046927SAndroid Build Coastguard Worker return false;
1401*61046927SAndroid Build Coastguard Worker nir_alu_instr *alu = nir_instr_as_alu(instr);
1402*61046927SAndroid Build Coastguard Worker if (alu->op == nir_op_fquantize2f16)
1403*61046927SAndroid Build Coastguard Worker return true;
1404*61046927SAndroid Build Coastguard Worker if (alu->def.bit_size != 16 && alu->def.bit_size != 64)
1405*61046927SAndroid Build Coastguard Worker return false;
1406*61046927SAndroid Build Coastguard Worker if (nir_alu_type_get_base_type(nir_op_infos[alu->op].output_type) != nir_type_float)
1407*61046927SAndroid Build Coastguard Worker return false;
1408*61046927SAndroid Build Coastguard Worker
1409*61046927SAndroid Build Coastguard Worker switch (alu->op) {
1410*61046927SAndroid Build Coastguard Worker case nir_op_f2f64:
1411*61046927SAndroid Build Coastguard Worker case nir_op_b2f64:
1412*61046927SAndroid Build Coastguard Worker case nir_op_f2f16_rtz:
1413*61046927SAndroid Build Coastguard Worker case nir_op_b2f16:
1414*61046927SAndroid Build Coastguard Worker case nir_op_fsat:
1415*61046927SAndroid Build Coastguard Worker case nir_op_fabs:
1416*61046927SAndroid Build Coastguard Worker case nir_op_fneg:
1417*61046927SAndroid Build Coastguard Worker case nir_op_fsign:
1418*61046927SAndroid Build Coastguard Worker case nir_op_ftrunc:
1419*61046927SAndroid Build Coastguard Worker case nir_op_fceil:
1420*61046927SAndroid Build Coastguard Worker case nir_op_ffloor:
1421*61046927SAndroid Build Coastguard Worker case nir_op_ffract:
1422*61046927SAndroid Build Coastguard Worker case nir_op_fround_even:
1423*61046927SAndroid Build Coastguard Worker case nir_op_fmin:
1424*61046927SAndroid Build Coastguard Worker case nir_op_fmax:
1425*61046927SAndroid Build Coastguard Worker return false;
1426*61046927SAndroid Build Coastguard Worker default:
1427*61046927SAndroid Build Coastguard Worker return true;
1428*61046927SAndroid Build Coastguard Worker }
1429*61046927SAndroid Build Coastguard Worker }
1430*61046927SAndroid Build Coastguard Worker
1431*61046927SAndroid Build Coastguard Worker static bool
can_use_fmamix(nir_scalar s,enum amd_gfx_level gfx_level)1432*61046927SAndroid Build Coastguard Worker can_use_fmamix(nir_scalar s, enum amd_gfx_level gfx_level)
1433*61046927SAndroid Build Coastguard Worker {
1434*61046927SAndroid Build Coastguard Worker s = nir_scalar_chase_movs(s);
1435*61046927SAndroid Build Coastguard Worker if (!list_is_singular(&s.def->uses))
1436*61046927SAndroid Build Coastguard Worker return false;
1437*61046927SAndroid Build Coastguard Worker
1438*61046927SAndroid Build Coastguard Worker if (nir_scalar_is_intrinsic(s) &&
1439*61046927SAndroid Build Coastguard Worker nir_scalar_intrinsic_op(s) == nir_intrinsic_load_interpolated_input)
1440*61046927SAndroid Build Coastguard Worker return gfx_level >= GFX11;
1441*61046927SAndroid Build Coastguard Worker
1442*61046927SAndroid Build Coastguard Worker if (!nir_scalar_is_alu(s))
1443*61046927SAndroid Build Coastguard Worker return false;
1444*61046927SAndroid Build Coastguard Worker
1445*61046927SAndroid Build Coastguard Worker switch (nir_scalar_alu_op(s)) {
1446*61046927SAndroid Build Coastguard Worker case nir_op_fmul:
1447*61046927SAndroid Build Coastguard Worker case nir_op_ffma:
1448*61046927SAndroid Build Coastguard Worker case nir_op_fadd:
1449*61046927SAndroid Build Coastguard Worker case nir_op_fsub:
1450*61046927SAndroid Build Coastguard Worker return true;
1451*61046927SAndroid Build Coastguard Worker case nir_op_fsat:
1452*61046927SAndroid Build Coastguard Worker return can_use_fmamix(nir_scalar_chase_alu_src(s, 0), gfx_level);
1453*61046927SAndroid Build Coastguard Worker default:
1454*61046927SAndroid Build Coastguard Worker return false;
1455*61046927SAndroid Build Coastguard Worker }
1456*61046927SAndroid Build Coastguard Worker }
1457*61046927SAndroid Build Coastguard Worker
1458*61046927SAndroid Build Coastguard Worker static bool
split_pack_half(nir_builder * b,nir_instr * instr,void * param)1459*61046927SAndroid Build Coastguard Worker split_pack_half(nir_builder *b, nir_instr *instr, void *param)
1460*61046927SAndroid Build Coastguard Worker {
1461*61046927SAndroid Build Coastguard Worker enum amd_gfx_level gfx_level = *(enum amd_gfx_level *)param;
1462*61046927SAndroid Build Coastguard Worker
1463*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_alu)
1464*61046927SAndroid Build Coastguard Worker return false;
1465*61046927SAndroid Build Coastguard Worker nir_alu_instr *alu = nir_instr_as_alu(instr);
1466*61046927SAndroid Build Coastguard Worker if (alu->op != nir_op_pack_half_2x16_rtz_split && alu->op != nir_op_pack_half_2x16_split)
1467*61046927SAndroid Build Coastguard Worker return false;
1468*61046927SAndroid Build Coastguard Worker
1469*61046927SAndroid Build Coastguard Worker nir_scalar s = nir_get_scalar(&alu->def, 0);
1470*61046927SAndroid Build Coastguard Worker
1471*61046927SAndroid Build Coastguard Worker if (!can_use_fmamix(nir_scalar_chase_alu_src(s, 0), gfx_level) ||
1472*61046927SAndroid Build Coastguard Worker !can_use_fmamix(nir_scalar_chase_alu_src(s, 1), gfx_level))
1473*61046927SAndroid Build Coastguard Worker return false;
1474*61046927SAndroid Build Coastguard Worker
1475*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(instr);
1476*61046927SAndroid Build Coastguard Worker
1477*61046927SAndroid Build Coastguard Worker /* Split pack_half into two f2f16 to create v_fma_mix{lo,hi}_f16
1478*61046927SAndroid Build Coastguard Worker * in the backend.
1479*61046927SAndroid Build Coastguard Worker */
1480*61046927SAndroid Build Coastguard Worker nir_def *lo = nir_f2f16(b, nir_ssa_for_alu_src(b, alu, 0));
1481*61046927SAndroid Build Coastguard Worker nir_def *hi = nir_f2f16(b, nir_ssa_for_alu_src(b, alu, 1));
1482*61046927SAndroid Build Coastguard Worker nir_def_replace(&alu->def, nir_pack_32_2x16_split(b, lo, hi));
1483*61046927SAndroid Build Coastguard Worker return true;
1484*61046927SAndroid Build Coastguard Worker }
1485*61046927SAndroid Build Coastguard Worker
1486*61046927SAndroid Build Coastguard Worker bool
ac_nir_opt_pack_half(nir_shader * shader,enum amd_gfx_level gfx_level)1487*61046927SAndroid Build Coastguard Worker ac_nir_opt_pack_half(nir_shader *shader, enum amd_gfx_level gfx_level)
1488*61046927SAndroid Build Coastguard Worker {
1489*61046927SAndroid Build Coastguard Worker if (gfx_level < GFX10)
1490*61046927SAndroid Build Coastguard Worker return false;
1491*61046927SAndroid Build Coastguard Worker
1492*61046927SAndroid Build Coastguard Worker unsigned exec_mode = shader->info.float_controls_execution_mode;
1493*61046927SAndroid Build Coastguard Worker bool set_mode = false;
1494*61046927SAndroid Build Coastguard Worker if (!nir_is_rounding_mode_rtz(exec_mode, 16)) {
1495*61046927SAndroid Build Coastguard Worker nir_foreach_function_impl(impl, shader) {
1496*61046927SAndroid Build Coastguard Worker nir_foreach_block(block, impl) {
1497*61046927SAndroid Build Coastguard Worker nir_foreach_instr(instr, block) {
1498*61046927SAndroid Build Coastguard Worker if (needs_rounding_mode_16_64(instr))
1499*61046927SAndroid Build Coastguard Worker return false;
1500*61046927SAndroid Build Coastguard Worker }
1501*61046927SAndroid Build Coastguard Worker }
1502*61046927SAndroid Build Coastguard Worker }
1503*61046927SAndroid Build Coastguard Worker set_mode = true;
1504*61046927SAndroid Build Coastguard Worker }
1505*61046927SAndroid Build Coastguard Worker
1506*61046927SAndroid Build Coastguard Worker bool progress = nir_shader_instructions_pass(shader, split_pack_half,
1507*61046927SAndroid Build Coastguard Worker nir_metadata_control_flow,
1508*61046927SAndroid Build Coastguard Worker &gfx_level);
1509*61046927SAndroid Build Coastguard Worker
1510*61046927SAndroid Build Coastguard Worker if (set_mode && progress) {
1511*61046927SAndroid Build Coastguard Worker exec_mode &= ~(FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP16 | FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP64);
1512*61046927SAndroid Build Coastguard Worker exec_mode |= FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP16 | FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP64;
1513*61046927SAndroid Build Coastguard Worker shader->info.float_controls_execution_mode = exec_mode;
1514*61046927SAndroid Build Coastguard Worker }
1515*61046927SAndroid Build Coastguard Worker return progress;
1516*61046927SAndroid Build Coastguard Worker }
1517*61046927SAndroid Build Coastguard Worker
1518*61046927SAndroid Build Coastguard Worker nir_def *
ac_average_samples(nir_builder * b,nir_def ** samples,unsigned num_samples)1519*61046927SAndroid Build Coastguard Worker ac_average_samples(nir_builder *b, nir_def **samples, unsigned num_samples)
1520*61046927SAndroid Build Coastguard Worker {
1521*61046927SAndroid Build Coastguard Worker /* This works like add-reduce by computing the sum of each pair independently, and then
1522*61046927SAndroid Build Coastguard Worker * computing the sum of each pair of sums, and so on, to get better instruction-level
1523*61046927SAndroid Build Coastguard Worker * parallelism.
1524*61046927SAndroid Build Coastguard Worker */
1525*61046927SAndroid Build Coastguard Worker if (num_samples == 16) {
1526*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 8; i++)
1527*61046927SAndroid Build Coastguard Worker samples[i] = nir_fadd(b, samples[i * 2], samples[i * 2 + 1]);
1528*61046927SAndroid Build Coastguard Worker }
1529*61046927SAndroid Build Coastguard Worker if (num_samples >= 8) {
1530*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++)
1531*61046927SAndroid Build Coastguard Worker samples[i] = nir_fadd(b, samples[i * 2], samples[i * 2 + 1]);
1532*61046927SAndroid Build Coastguard Worker }
1533*61046927SAndroid Build Coastguard Worker if (num_samples >= 4) {
1534*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 2; i++)
1535*61046927SAndroid Build Coastguard Worker samples[i] = nir_fadd(b, samples[i * 2], samples[i * 2 + 1]);
1536*61046927SAndroid Build Coastguard Worker }
1537*61046927SAndroid Build Coastguard Worker if (num_samples >= 2)
1538*61046927SAndroid Build Coastguard Worker samples[0] = nir_fadd(b, samples[0], samples[1]);
1539*61046927SAndroid Build Coastguard Worker
1540*61046927SAndroid Build Coastguard Worker return nir_fmul_imm(b, samples[0], 1.0 / num_samples); /* average the sum */
1541*61046927SAndroid Build Coastguard Worker }
1542*61046927SAndroid Build Coastguard Worker
1543*61046927SAndroid Build Coastguard Worker void
ac_optimization_barrier_vgpr_array(const struct radeon_info * info,nir_builder * b,nir_def ** array,unsigned num_elements,unsigned num_components)1544*61046927SAndroid Build Coastguard Worker ac_optimization_barrier_vgpr_array(const struct radeon_info *info, nir_builder *b,
1545*61046927SAndroid Build Coastguard Worker nir_def **array, unsigned num_elements,
1546*61046927SAndroid Build Coastguard Worker unsigned num_components)
1547*61046927SAndroid Build Coastguard Worker {
1548*61046927SAndroid Build Coastguard Worker /* We use the optimization barrier to force LLVM to form VMEM clauses by constraining its
1549*61046927SAndroid Build Coastguard Worker * instruction scheduling options.
1550*61046927SAndroid Build Coastguard Worker *
1551*61046927SAndroid Build Coastguard Worker * VMEM clauses are supported since GFX10. It's not recommended to use the optimization
1552*61046927SAndroid Build Coastguard Worker * barrier in the compute blit for GFX6-8 because the lack of A16 combined with optimization
1553*61046927SAndroid Build Coastguard Worker * barriers would unnecessarily increase VGPR usage for MSAA resources.
1554*61046927SAndroid Build Coastguard Worker */
1555*61046927SAndroid Build Coastguard Worker if (!b->shader->info.use_aco_amd && info->gfx_level >= GFX10) {
1556*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < num_elements; i++) {
1557*61046927SAndroid Build Coastguard Worker unsigned prev_num = array[i]->num_components;
1558*61046927SAndroid Build Coastguard Worker array[i] = nir_trim_vector(b, array[i], num_components);
1559*61046927SAndroid Build Coastguard Worker array[i] = nir_optimization_barrier_vgpr_amd(b, array[i]->bit_size, array[i]);
1560*61046927SAndroid Build Coastguard Worker array[i] = nir_pad_vector(b, array[i], prev_num);
1561*61046927SAndroid Build Coastguard Worker }
1562*61046927SAndroid Build Coastguard Worker }
1563*61046927SAndroid Build Coastguard Worker }
1564*61046927SAndroid Build Coastguard Worker
1565*61046927SAndroid Build Coastguard Worker nir_def *
ac_get_global_ids(nir_builder * b,unsigned num_components,unsigned bit_size)1566*61046927SAndroid Build Coastguard Worker ac_get_global_ids(nir_builder *b, unsigned num_components, unsigned bit_size)
1567*61046927SAndroid Build Coastguard Worker {
1568*61046927SAndroid Build Coastguard Worker unsigned mask = BITFIELD_MASK(num_components);
1569*61046927SAndroid Build Coastguard Worker
1570*61046927SAndroid Build Coastguard Worker nir_def *local_ids = nir_channels(b, nir_load_local_invocation_id(b), mask);
1571*61046927SAndroid Build Coastguard Worker nir_def *block_ids = nir_channels(b, nir_load_workgroup_id(b), mask);
1572*61046927SAndroid Build Coastguard Worker nir_def *block_size = nir_channels(b, nir_load_workgroup_size(b), mask);
1573*61046927SAndroid Build Coastguard Worker
1574*61046927SAndroid Build Coastguard Worker assert(bit_size == 32 || bit_size == 16);
1575*61046927SAndroid Build Coastguard Worker if (bit_size == 16) {
1576*61046927SAndroid Build Coastguard Worker local_ids = nir_i2iN(b, local_ids, bit_size);
1577*61046927SAndroid Build Coastguard Worker block_ids = nir_i2iN(b, block_ids, bit_size);
1578*61046927SAndroid Build Coastguard Worker block_size = nir_i2iN(b, block_size, bit_size);
1579*61046927SAndroid Build Coastguard Worker }
1580*61046927SAndroid Build Coastguard Worker
1581*61046927SAndroid Build Coastguard Worker return nir_iadd(b, nir_imul(b, block_ids, block_size), local_ids);
1582*61046927SAndroid Build Coastguard Worker }
1583*61046927SAndroid Build Coastguard Worker
1584*61046927SAndroid Build Coastguard Worker unsigned
ac_nir_varying_expression_max_cost(nir_shader * producer,nir_shader * consumer)1585*61046927SAndroid Build Coastguard Worker ac_nir_varying_expression_max_cost(nir_shader *producer, nir_shader *consumer)
1586*61046927SAndroid Build Coastguard Worker {
1587*61046927SAndroid Build Coastguard Worker switch (consumer->info.stage) {
1588*61046927SAndroid Build Coastguard Worker case MESA_SHADER_TESS_CTRL:
1589*61046927SAndroid Build Coastguard Worker /* VS->TCS
1590*61046927SAndroid Build Coastguard Worker * Non-amplifying shaders can always have their varying expressions
1591*61046927SAndroid Build Coastguard Worker * moved into later shaders.
1592*61046927SAndroid Build Coastguard Worker */
1593*61046927SAndroid Build Coastguard Worker return UINT_MAX;
1594*61046927SAndroid Build Coastguard Worker
1595*61046927SAndroid Build Coastguard Worker case MESA_SHADER_GEOMETRY:
1596*61046927SAndroid Build Coastguard Worker /* VS->GS, TES->GS */
1597*61046927SAndroid Build Coastguard Worker return consumer->info.gs.vertices_in == 1 ? UINT_MAX :
1598*61046927SAndroid Build Coastguard Worker consumer->info.gs.vertices_in == 2 ? 20 : 14;
1599*61046927SAndroid Build Coastguard Worker
1600*61046927SAndroid Build Coastguard Worker case MESA_SHADER_TESS_EVAL:
1601*61046927SAndroid Build Coastguard Worker /* TCS->TES and VS->TES (OpenGL only) */
1602*61046927SAndroid Build Coastguard Worker case MESA_SHADER_FRAGMENT:
1603*61046927SAndroid Build Coastguard Worker /* Up to 3 uniforms and 5 ALUs. */
1604*61046927SAndroid Build Coastguard Worker return 14;
1605*61046927SAndroid Build Coastguard Worker
1606*61046927SAndroid Build Coastguard Worker default:
1607*61046927SAndroid Build Coastguard Worker unreachable("unexpected shader stage");
1608*61046927SAndroid Build Coastguard Worker }
1609*61046927SAndroid Build Coastguard Worker }
1610*61046927SAndroid Build Coastguard Worker
1611*61046927SAndroid Build Coastguard Worker unsigned
ac_nir_varying_estimate_instr_cost(nir_instr * instr)1612*61046927SAndroid Build Coastguard Worker ac_nir_varying_estimate_instr_cost(nir_instr *instr)
1613*61046927SAndroid Build Coastguard Worker {
1614*61046927SAndroid Build Coastguard Worker unsigned dst_bit_size, src_bit_size, num_dst_dwords;
1615*61046927SAndroid Build Coastguard Worker nir_op alu_op;
1616*61046927SAndroid Build Coastguard Worker
1617*61046927SAndroid Build Coastguard Worker /* This is a very loose approximation based on gfx10. */
1618*61046927SAndroid Build Coastguard Worker switch (instr->type) {
1619*61046927SAndroid Build Coastguard Worker case nir_instr_type_alu:
1620*61046927SAndroid Build Coastguard Worker dst_bit_size = nir_instr_as_alu(instr)->def.bit_size;
1621*61046927SAndroid Build Coastguard Worker src_bit_size = nir_instr_as_alu(instr)->src[0].src.ssa->bit_size;
1622*61046927SAndroid Build Coastguard Worker alu_op = nir_instr_as_alu(instr)->op;
1623*61046927SAndroid Build Coastguard Worker num_dst_dwords = DIV_ROUND_UP(dst_bit_size, 32);
1624*61046927SAndroid Build Coastguard Worker
1625*61046927SAndroid Build Coastguard Worker switch (alu_op) {
1626*61046927SAndroid Build Coastguard Worker case nir_op_mov:
1627*61046927SAndroid Build Coastguard Worker case nir_op_vec2:
1628*61046927SAndroid Build Coastguard Worker case nir_op_vec3:
1629*61046927SAndroid Build Coastguard Worker case nir_op_vec4:
1630*61046927SAndroid Build Coastguard Worker case nir_op_vec5:
1631*61046927SAndroid Build Coastguard Worker case nir_op_vec8:
1632*61046927SAndroid Build Coastguard Worker case nir_op_vec16:
1633*61046927SAndroid Build Coastguard Worker case nir_op_fabs:
1634*61046927SAndroid Build Coastguard Worker case nir_op_fneg:
1635*61046927SAndroid Build Coastguard Worker case nir_op_fsat:
1636*61046927SAndroid Build Coastguard Worker return 0;
1637*61046927SAndroid Build Coastguard Worker
1638*61046927SAndroid Build Coastguard Worker case nir_op_imul:
1639*61046927SAndroid Build Coastguard Worker case nir_op_umul_low:
1640*61046927SAndroid Build Coastguard Worker return dst_bit_size <= 16 ? 1 : 4 * num_dst_dwords;
1641*61046927SAndroid Build Coastguard Worker
1642*61046927SAndroid Build Coastguard Worker case nir_op_imul_high:
1643*61046927SAndroid Build Coastguard Worker case nir_op_umul_high:
1644*61046927SAndroid Build Coastguard Worker case nir_op_imul_2x32_64:
1645*61046927SAndroid Build Coastguard Worker case nir_op_umul_2x32_64:
1646*61046927SAndroid Build Coastguard Worker return 4;
1647*61046927SAndroid Build Coastguard Worker
1648*61046927SAndroid Build Coastguard Worker case nir_op_fexp2:
1649*61046927SAndroid Build Coastguard Worker case nir_op_flog2:
1650*61046927SAndroid Build Coastguard Worker case nir_op_frcp:
1651*61046927SAndroid Build Coastguard Worker case nir_op_frsq:
1652*61046927SAndroid Build Coastguard Worker case nir_op_fsqrt:
1653*61046927SAndroid Build Coastguard Worker case nir_op_fsin:
1654*61046927SAndroid Build Coastguard Worker case nir_op_fcos:
1655*61046927SAndroid Build Coastguard Worker case nir_op_fsin_amd:
1656*61046927SAndroid Build Coastguard Worker case nir_op_fcos_amd:
1657*61046927SAndroid Build Coastguard Worker return 4; /* FP16 & FP32. */
1658*61046927SAndroid Build Coastguard Worker
1659*61046927SAndroid Build Coastguard Worker case nir_op_fpow:
1660*61046927SAndroid Build Coastguard Worker return 4 + 1 + 4; /* log2 + mul + exp2 */
1661*61046927SAndroid Build Coastguard Worker
1662*61046927SAndroid Build Coastguard Worker case nir_op_fsign:
1663*61046927SAndroid Build Coastguard Worker return dst_bit_size == 64 ? 4 : 3; /* See ac_build_fsign. */
1664*61046927SAndroid Build Coastguard Worker
1665*61046927SAndroid Build Coastguard Worker case nir_op_idiv:
1666*61046927SAndroid Build Coastguard Worker case nir_op_udiv:
1667*61046927SAndroid Build Coastguard Worker case nir_op_imod:
1668*61046927SAndroid Build Coastguard Worker case nir_op_umod:
1669*61046927SAndroid Build Coastguard Worker case nir_op_irem:
1670*61046927SAndroid Build Coastguard Worker return dst_bit_size == 64 ? 80 : 40;
1671*61046927SAndroid Build Coastguard Worker
1672*61046927SAndroid Build Coastguard Worker case nir_op_fdiv:
1673*61046927SAndroid Build Coastguard Worker return dst_bit_size == 64 ? 80 : 5; /* FP16 & FP32: rcp + mul */
1674*61046927SAndroid Build Coastguard Worker
1675*61046927SAndroid Build Coastguard Worker case nir_op_fmod:
1676*61046927SAndroid Build Coastguard Worker case nir_op_frem:
1677*61046927SAndroid Build Coastguard Worker return dst_bit_size == 64 ? 80 : 8;
1678*61046927SAndroid Build Coastguard Worker
1679*61046927SAndroid Build Coastguard Worker default:
1680*61046927SAndroid Build Coastguard Worker /* Double opcodes. Comparisons have always full performance. */
1681*61046927SAndroid Build Coastguard Worker if ((dst_bit_size == 64 &&
1682*61046927SAndroid Build Coastguard Worker nir_op_infos[alu_op].output_type & nir_type_float) ||
1683*61046927SAndroid Build Coastguard Worker (dst_bit_size >= 8 && src_bit_size == 64 &&
1684*61046927SAndroid Build Coastguard Worker nir_op_infos[alu_op].input_types[0] & nir_type_float))
1685*61046927SAndroid Build Coastguard Worker return 16;
1686*61046927SAndroid Build Coastguard Worker
1687*61046927SAndroid Build Coastguard Worker return DIV_ROUND_UP(MAX2(dst_bit_size, src_bit_size), 32);
1688*61046927SAndroid Build Coastguard Worker }
1689*61046927SAndroid Build Coastguard Worker
1690*61046927SAndroid Build Coastguard Worker case nir_instr_type_intrinsic:
1691*61046927SAndroid Build Coastguard Worker dst_bit_size = nir_instr_as_intrinsic(instr)->def.bit_size;
1692*61046927SAndroid Build Coastguard Worker num_dst_dwords = DIV_ROUND_UP(dst_bit_size, 32);
1693*61046927SAndroid Build Coastguard Worker
1694*61046927SAndroid Build Coastguard Worker switch (nir_instr_as_intrinsic(instr)->intrinsic) {
1695*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_deref:
1696*61046927SAndroid Build Coastguard Worker /* Uniform or UBO load.
1697*61046927SAndroid Build Coastguard Worker * Set a low cost to balance the number of scalar loads and ALUs.
1698*61046927SAndroid Build Coastguard Worker */
1699*61046927SAndroid Build Coastguard Worker return 3 * num_dst_dwords;
1700*61046927SAndroid Build Coastguard Worker
1701*61046927SAndroid Build Coastguard Worker default:
1702*61046927SAndroid Build Coastguard Worker unreachable("unexpected intrinsic");
1703*61046927SAndroid Build Coastguard Worker }
1704*61046927SAndroid Build Coastguard Worker
1705*61046927SAndroid Build Coastguard Worker default:
1706*61046927SAndroid Build Coastguard Worker unreachable("unexpected instr type");
1707*61046927SAndroid Build Coastguard Worker }
1708*61046927SAndroid Build Coastguard Worker }
1709