radv: add set_output_usage_mask() helper
[mesa.git] / src / amd / vulkan / radv_shader_info.c
1 /*
2 * Copyright © 2017 Red Hat
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23 #include "radv_private.h"
24 #include "radv_shader.h"
25 #include "nir/nir.h"
26 #include "nir/nir_deref.h"
27
28 static void mark_sampler_desc(const nir_variable *var,
29 struct radv_shader_info *info)
30 {
31 info->desc_set_used_mask |= (1 << var->data.descriptor_set);
32 }
33
34 static void mark_ls_output(struct radv_shader_info *info,
35 uint32_t param, int num_slots)
36 {
37 uint64_t mask = (1ull << num_slots) - 1ull;
38 info->vs.ls_outputs_written |= (mask << param);
39 }
40
41 static void mark_tess_output(struct radv_shader_info *info,
42 bool is_patch, uint32_t param, int num_slots)
43 {
44 uint64_t mask = (1ull << num_slots) - 1ull;
45 if (is_patch)
46 info->tcs.patch_outputs_written |= (mask << param);
47 else
48 info->tcs.outputs_written |= (mask << param);
49 }
50
51 static void
52 get_deref_offset(nir_deref_instr *instr,
53 unsigned *const_out)
54 {
55 nir_variable *var = nir_deref_instr_get_variable(instr);
56 nir_deref_path path;
57 unsigned idx_lvl = 1;
58
59 if (var->data.compact) {
60 assert(instr->deref_type == nir_deref_type_array);
61 nir_const_value *v = nir_src_as_const_value(instr->arr.index);
62 assert(v);
63 *const_out = v->u32[0];
64 return;
65 }
66
67 nir_deref_path_init(&path, instr, NULL);
68
69 uint32_t const_offset = 0;
70
71 for (; path.path[idx_lvl]; ++idx_lvl) {
72 const struct glsl_type *parent_type = path.path[idx_lvl - 1]->type;
73 if (path.path[idx_lvl]->deref_type == nir_deref_type_struct) {
74 unsigned index = path.path[idx_lvl]->strct.index;
75
76 for (unsigned i = 0; i < index; i++) {
77 const struct glsl_type *ft = glsl_get_struct_field(parent_type, i);
78 const_offset += glsl_count_attribute_slots(ft, false);
79 }
80 } else if(path.path[idx_lvl]->deref_type == nir_deref_type_array) {
81 unsigned size = glsl_count_attribute_slots(path.path[idx_lvl]->type, false);
82 nir_const_value *v = nir_src_as_const_value(path.path[idx_lvl]->arr.index);
83 if (v)
84 const_offset += v->u32[0] * size;
85 } else
86 unreachable("Uhandled deref type in get_deref_instr_offset");
87 }
88
89 *const_out = const_offset;
90
91 nir_deref_path_finish(&path);
92 }
93
94 static void
95 gather_intrinsic_load_deref_info(const nir_shader *nir,
96 const nir_intrinsic_instr *instr,
97 struct radv_shader_info *info)
98 {
99 switch (nir->info.stage) {
100 case MESA_SHADER_VERTEX: {
101 nir_variable *var = nir_deref_instr_get_variable(nir_instr_as_deref(instr->src[0].ssa->parent_instr));
102
103 if (var->data.mode == nir_var_shader_in) {
104 unsigned idx = var->data.location;
105 uint8_t mask = nir_ssa_def_components_read(&instr->dest.ssa);
106
107 info->vs.input_usage_mask[idx] |=
108 mask << var->data.location_frac;
109 }
110 break;
111 }
112 default:
113 break;
114 }
115 }
116
117 static void
118 set_output_usage_mask(const nir_shader *nir, const nir_intrinsic_instr *instr,
119 uint8_t *output_usage_mask)
120 {
121 nir_deref_instr *deref_instr =
122 nir_instr_as_deref(instr->src[0].ssa->parent_instr);
123 nir_variable *var = nir_deref_instr_get_variable(deref_instr);
124 unsigned attrib_count = glsl_count_attribute_slots(var->type, false);
125 unsigned idx = var->data.location;
126 unsigned comp = var->data.location_frac;
127 unsigned const_offset = 0;
128
129 get_deref_offset(deref_instr, &const_offset);
130
131 for (unsigned i = 0; i < attrib_count; i++) {
132 output_usage_mask[idx + i + const_offset] |=
133 instr->const_index[0] << comp;
134 }
135 }
136
137 static void
138 gather_intrinsic_store_deref_info(const nir_shader *nir,
139 const nir_intrinsic_instr *instr,
140 struct radv_shader_info *info)
141 {
142 nir_variable *var = nir_deref_instr_get_variable(nir_instr_as_deref(instr->src[0].ssa->parent_instr));
143
144 if (var->data.mode == nir_var_shader_out) {
145 unsigned idx = var->data.location;
146
147 switch (nir->info.stage) {
148 case MESA_SHADER_VERTEX:
149 set_output_usage_mask(nir, instr,
150 info->vs.output_usage_mask);
151 break;
152 case MESA_SHADER_GEOMETRY:
153 set_output_usage_mask(nir, instr,
154 info->gs.output_usage_mask);
155 break;
156 case MESA_SHADER_TESS_EVAL:
157 set_output_usage_mask(nir, instr,
158 info->tes.output_usage_mask);
159 break;
160 case MESA_SHADER_TESS_CTRL: {
161 unsigned param = shader_io_get_unique_index(idx);
162 const struct glsl_type *type = var->type;
163
164 if (!var->data.patch)
165 type = glsl_get_array_element(var->type);
166
167 unsigned slots =
168 var->data.compact ? DIV_ROUND_UP(glsl_get_length(type), 4)
169 : glsl_count_attribute_slots(type, false);
170
171 if (idx == VARYING_SLOT_CLIP_DIST0)
172 slots = (nir->info.clip_distance_array_size +
173 nir->info.cull_distance_array_size > 4) ? 2 : 1;
174
175 mark_tess_output(info, var->data.patch, param, slots);
176 break;
177 }
178 default:
179 break;
180 }
181 }
182 }
183
184 static void
185 gather_intrinsic_info(const nir_shader *nir, const nir_intrinsic_instr *instr,
186 struct radv_shader_info *info)
187 {
188 switch (instr->intrinsic) {
189 case nir_intrinsic_interp_deref_at_sample:
190 info->ps.needs_sample_positions = true;
191 break;
192 case nir_intrinsic_load_draw_id:
193 info->vs.needs_draw_id = true;
194 break;
195 case nir_intrinsic_load_instance_id:
196 info->vs.needs_instance_id = true;
197 break;
198 case nir_intrinsic_load_num_work_groups:
199 info->cs.uses_grid_size = true;
200 break;
201 case nir_intrinsic_load_local_invocation_id:
202 case nir_intrinsic_load_work_group_id: {
203 unsigned mask = nir_ssa_def_components_read(&instr->dest.ssa);
204 while (mask) {
205 unsigned i = u_bit_scan(&mask);
206
207 if (instr->intrinsic == nir_intrinsic_load_work_group_id)
208 info->cs.uses_block_id[i] = true;
209 else
210 info->cs.uses_thread_id[i] = true;
211 }
212 break;
213 }
214 case nir_intrinsic_load_local_invocation_index:
215 case nir_intrinsic_load_subgroup_id:
216 case nir_intrinsic_load_num_subgroups:
217 info->cs.uses_local_invocation_idx = true;
218 break;
219 case nir_intrinsic_load_sample_id:
220 info->ps.force_persample = true;
221 break;
222 case nir_intrinsic_load_sample_pos:
223 info->ps.force_persample = true;
224 break;
225 case nir_intrinsic_load_view_index:
226 info->needs_multiview_view_index = true;
227 if (nir->info.stage == MESA_SHADER_FRAGMENT)
228 info->ps.layer_input = true;
229 break;
230 case nir_intrinsic_load_invocation_id:
231 info->uses_invocation_id = true;
232 break;
233 case nir_intrinsic_load_primitive_id:
234 info->uses_prim_id = true;
235 break;
236 case nir_intrinsic_load_push_constant:
237 info->loads_push_constants = true;
238 break;
239 case nir_intrinsic_vulkan_resource_index:
240 info->desc_set_used_mask |= (1 << nir_intrinsic_desc_set(instr));
241 break;
242 case nir_intrinsic_image_deref_load:
243 case nir_intrinsic_image_deref_store:
244 case nir_intrinsic_image_deref_atomic_add:
245 case nir_intrinsic_image_deref_atomic_min:
246 case nir_intrinsic_image_deref_atomic_max:
247 case nir_intrinsic_image_deref_atomic_and:
248 case nir_intrinsic_image_deref_atomic_or:
249 case nir_intrinsic_image_deref_atomic_xor:
250 case nir_intrinsic_image_deref_atomic_exchange:
251 case nir_intrinsic_image_deref_atomic_comp_swap:
252 case nir_intrinsic_image_deref_size: {
253 nir_variable *var = nir_deref_instr_get_variable(nir_instr_as_deref(instr->src[0].ssa->parent_instr));
254 const struct glsl_type *type = glsl_without_array(var->type);
255
256 enum glsl_sampler_dim dim = glsl_get_sampler_dim(type);
257 if (dim == GLSL_SAMPLER_DIM_SUBPASS ||
258 dim == GLSL_SAMPLER_DIM_SUBPASS_MS) {
259 info->ps.layer_input = true;
260 info->ps.uses_input_attachments = true;
261 }
262 mark_sampler_desc(var, info);
263
264 if (nir_intrinsic_image_deref_store ||
265 nir_intrinsic_image_deref_atomic_add ||
266 nir_intrinsic_image_deref_atomic_min ||
267 nir_intrinsic_image_deref_atomic_max ||
268 nir_intrinsic_image_deref_atomic_and ||
269 nir_intrinsic_image_deref_atomic_or ||
270 nir_intrinsic_image_deref_atomic_xor ||
271 nir_intrinsic_image_deref_atomic_exchange ||
272 nir_intrinsic_image_deref_atomic_comp_swap) {
273 if (nir->info.stage == MESA_SHADER_FRAGMENT)
274 info->ps.writes_memory = true;
275 }
276 break;
277 }
278 case nir_intrinsic_store_ssbo:
279 case nir_intrinsic_ssbo_atomic_add:
280 case nir_intrinsic_ssbo_atomic_imin:
281 case nir_intrinsic_ssbo_atomic_umin:
282 case nir_intrinsic_ssbo_atomic_imax:
283 case nir_intrinsic_ssbo_atomic_umax:
284 case nir_intrinsic_ssbo_atomic_and:
285 case nir_intrinsic_ssbo_atomic_or:
286 case nir_intrinsic_ssbo_atomic_xor:
287 case nir_intrinsic_ssbo_atomic_exchange:
288 case nir_intrinsic_ssbo_atomic_comp_swap:
289 if (nir->info.stage == MESA_SHADER_FRAGMENT)
290 info->ps.writes_memory = true;
291 break;
292 case nir_intrinsic_load_deref:
293 gather_intrinsic_load_deref_info(nir, instr, info);
294 break;
295 case nir_intrinsic_store_deref:
296 gather_intrinsic_store_deref_info(nir, instr, info);
297 break;
298 default:
299 break;
300 }
301 }
302
303 static void
304 gather_tex_info(const nir_shader *nir, const nir_tex_instr *instr,
305 struct radv_shader_info *info)
306 {
307 for (unsigned i = 0; i < instr->num_srcs; i++) {
308 switch (instr->src[i].src_type) {
309 case nir_tex_src_texture_deref:
310 mark_sampler_desc(nir_deref_instr_get_variable(nir_src_as_deref(instr->src[i].src)), info);
311 break;
312 case nir_tex_src_sampler_deref:
313 mark_sampler_desc(nir_deref_instr_get_variable(nir_src_as_deref(instr->src[i].src)), info);
314 break;
315 default:
316 break;
317 }
318 }
319 }
320
321 static void
322 gather_info_block(const nir_shader *nir, const nir_block *block,
323 struct radv_shader_info *info)
324 {
325 nir_foreach_instr(instr, block) {
326 switch (instr->type) {
327 case nir_instr_type_intrinsic:
328 gather_intrinsic_info(nir, nir_instr_as_intrinsic(instr), info);
329 break;
330 case nir_instr_type_tex:
331 gather_tex_info(nir, nir_instr_as_tex(instr), info);
332 break;
333 default:
334 break;
335 }
336 }
337 }
338
339 static void
340 gather_info_input_decl_vs(const nir_shader *nir, const nir_variable *var,
341 struct radv_shader_info *info)
342 {
343 int idx = var->data.location;
344
345 if (idx >= VERT_ATTRIB_GENERIC0 && idx <= VERT_ATTRIB_GENERIC15)
346 info->vs.has_vertex_buffers = true;
347 }
348
349 static void
350 gather_info_input_decl_ps(const nir_shader *nir, const nir_variable *var,
351 struct radv_shader_info *info)
352 {
353 unsigned attrib_count = glsl_count_attribute_slots(var->type, false);
354 const struct glsl_type *type = glsl_without_array(var->type);
355 int idx = var->data.location;
356
357 switch (idx) {
358 case VARYING_SLOT_PNTC:
359 info->ps.has_pcoord = true;
360 break;
361 case VARYING_SLOT_PRIMITIVE_ID:
362 info->ps.prim_id_input = true;
363 break;
364 case VARYING_SLOT_LAYER:
365 info->ps.layer_input = true;
366 break;
367 case VARYING_SLOT_CLIP_DIST0:
368 info->ps.num_input_clips_culls = attrib_count;
369 break;
370 default:
371 break;
372 }
373
374 if (glsl_get_base_type(type) == GLSL_TYPE_FLOAT) {
375 if (var->data.sample)
376 info->ps.force_persample = true;
377 }
378 }
379
380 static void
381 gather_info_input_decl(const nir_shader *nir, const nir_variable *var,
382 struct radv_shader_info *info)
383 {
384 switch (nir->info.stage) {
385 case MESA_SHADER_VERTEX:
386 gather_info_input_decl_vs(nir, var, info);
387 break;
388 case MESA_SHADER_FRAGMENT:
389 gather_info_input_decl_ps(nir, var, info);
390 break;
391 default:
392 break;
393 }
394 }
395
396 static void
397 gather_info_output_decl_ls(const nir_shader *nir, const nir_variable *var,
398 struct radv_shader_info *info)
399 {
400 int idx = var->data.location;
401 unsigned param = shader_io_get_unique_index(idx);
402 int num_slots = glsl_count_attribute_slots(var->type, false);
403 if (idx == VARYING_SLOT_CLIP_DIST0)
404 num_slots = (nir->info.clip_distance_array_size + nir->info.cull_distance_array_size > 4) ? 2 : 1;
405 mark_ls_output(info, param, num_slots);
406 }
407
408 static void
409 gather_info_output_decl_ps(const nir_shader *nir, const nir_variable *var,
410 struct radv_shader_info *info)
411 {
412 int idx = var->data.location;
413
414 switch (idx) {
415 case FRAG_RESULT_DEPTH:
416 info->ps.writes_z = true;
417 break;
418 case FRAG_RESULT_STENCIL:
419 info->ps.writes_stencil = true;
420 break;
421 case FRAG_RESULT_SAMPLE_MASK:
422 info->ps.writes_sample_mask = true;
423 break;
424 default:
425 break;
426 }
427 }
428
429 static void
430 gather_info_output_decl(const nir_shader *nir, const nir_variable *var,
431 struct radv_shader_info *info,
432 const struct radv_nir_compiler_options *options)
433 {
434 switch (nir->info.stage) {
435 case MESA_SHADER_FRAGMENT:
436 gather_info_output_decl_ps(nir, var, info);
437 break;
438 case MESA_SHADER_VERTEX:
439 if (options->key.vs.as_ls)
440 gather_info_output_decl_ls(nir, var, info);
441 break;
442 default:
443 break;
444 }
445 }
446
447 void
448 radv_nir_shader_info_pass(const struct nir_shader *nir,
449 const struct radv_nir_compiler_options *options,
450 struct radv_shader_info *info)
451 {
452 struct nir_function *func =
453 (struct nir_function *)exec_list_get_head_const(&nir->functions);
454
455 if (options->layout && options->layout->dynamic_offset_count)
456 info->loads_push_constants = true;
457
458 nir_foreach_variable(variable, &nir->inputs)
459 gather_info_input_decl(nir, variable, info);
460
461 nir_foreach_block(block, func->impl) {
462 gather_info_block(nir, block, info);
463 }
464
465 nir_foreach_variable(variable, &nir->outputs)
466 gather_info_output_decl(nir, variable, info, options);
467 }