radv: gather the output usage mask for clip/cull distances correctly
[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 if (idx == VARYING_SLOT_CLIP_DIST0) {
132 /* Special case for clip/cull distances because there are
133 * combined into a single array that contains both.
134 */
135 output_usage_mask[idx] |= 1 << const_offset;
136 return;
137 }
138
139 for (unsigned i = 0; i < attrib_count; i++) {
140 output_usage_mask[idx + i + const_offset] |=
141 instr->const_index[0] << comp;
142 }
143 }
144
145 static void
146 gather_intrinsic_store_deref_info(const nir_shader *nir,
147 const nir_intrinsic_instr *instr,
148 struct radv_shader_info *info)
149 {
150 nir_variable *var = nir_deref_instr_get_variable(nir_instr_as_deref(instr->src[0].ssa->parent_instr));
151
152 if (var->data.mode == nir_var_shader_out) {
153 unsigned idx = var->data.location;
154
155 switch (nir->info.stage) {
156 case MESA_SHADER_VERTEX:
157 set_output_usage_mask(nir, instr,
158 info->vs.output_usage_mask);
159 break;
160 case MESA_SHADER_GEOMETRY:
161 set_output_usage_mask(nir, instr,
162 info->gs.output_usage_mask);
163 break;
164 case MESA_SHADER_TESS_EVAL:
165 set_output_usage_mask(nir, instr,
166 info->tes.output_usage_mask);
167 break;
168 case MESA_SHADER_TESS_CTRL: {
169 unsigned param = shader_io_get_unique_index(idx);
170 const struct glsl_type *type = var->type;
171
172 if (!var->data.patch)
173 type = glsl_get_array_element(var->type);
174
175 unsigned slots =
176 var->data.compact ? DIV_ROUND_UP(glsl_get_length(type), 4)
177 : glsl_count_attribute_slots(type, false);
178
179 if (idx == VARYING_SLOT_CLIP_DIST0)
180 slots = (nir->info.clip_distance_array_size +
181 nir->info.cull_distance_array_size > 4) ? 2 : 1;
182
183 mark_tess_output(info, var->data.patch, param, slots);
184 break;
185 }
186 default:
187 break;
188 }
189 }
190 }
191
192 static void
193 gather_intrinsic_info(const nir_shader *nir, const nir_intrinsic_instr *instr,
194 struct radv_shader_info *info)
195 {
196 switch (instr->intrinsic) {
197 case nir_intrinsic_interp_deref_at_sample:
198 info->ps.needs_sample_positions = true;
199 break;
200 case nir_intrinsic_load_draw_id:
201 info->vs.needs_draw_id = true;
202 break;
203 case nir_intrinsic_load_instance_id:
204 info->vs.needs_instance_id = true;
205 break;
206 case nir_intrinsic_load_num_work_groups:
207 info->cs.uses_grid_size = true;
208 break;
209 case nir_intrinsic_load_local_invocation_id:
210 case nir_intrinsic_load_work_group_id: {
211 unsigned mask = nir_ssa_def_components_read(&instr->dest.ssa);
212 while (mask) {
213 unsigned i = u_bit_scan(&mask);
214
215 if (instr->intrinsic == nir_intrinsic_load_work_group_id)
216 info->cs.uses_block_id[i] = true;
217 else
218 info->cs.uses_thread_id[i] = true;
219 }
220 break;
221 }
222 case nir_intrinsic_load_local_invocation_index:
223 case nir_intrinsic_load_subgroup_id:
224 case nir_intrinsic_load_num_subgroups:
225 info->cs.uses_local_invocation_idx = true;
226 break;
227 case nir_intrinsic_load_sample_id:
228 info->ps.force_persample = true;
229 break;
230 case nir_intrinsic_load_sample_pos:
231 info->ps.force_persample = true;
232 break;
233 case nir_intrinsic_load_view_index:
234 info->needs_multiview_view_index = true;
235 if (nir->info.stage == MESA_SHADER_FRAGMENT)
236 info->ps.layer_input = true;
237 break;
238 case nir_intrinsic_load_invocation_id:
239 info->uses_invocation_id = true;
240 break;
241 case nir_intrinsic_load_primitive_id:
242 info->uses_prim_id = true;
243 break;
244 case nir_intrinsic_load_push_constant:
245 info->loads_push_constants = true;
246 break;
247 case nir_intrinsic_vulkan_resource_index:
248 info->desc_set_used_mask |= (1 << nir_intrinsic_desc_set(instr));
249 break;
250 case nir_intrinsic_image_deref_load:
251 case nir_intrinsic_image_deref_store:
252 case nir_intrinsic_image_deref_atomic_add:
253 case nir_intrinsic_image_deref_atomic_min:
254 case nir_intrinsic_image_deref_atomic_max:
255 case nir_intrinsic_image_deref_atomic_and:
256 case nir_intrinsic_image_deref_atomic_or:
257 case nir_intrinsic_image_deref_atomic_xor:
258 case nir_intrinsic_image_deref_atomic_exchange:
259 case nir_intrinsic_image_deref_atomic_comp_swap:
260 case nir_intrinsic_image_deref_size: {
261 nir_variable *var = nir_deref_instr_get_variable(nir_instr_as_deref(instr->src[0].ssa->parent_instr));
262 const struct glsl_type *type = glsl_without_array(var->type);
263
264 enum glsl_sampler_dim dim = glsl_get_sampler_dim(type);
265 if (dim == GLSL_SAMPLER_DIM_SUBPASS ||
266 dim == GLSL_SAMPLER_DIM_SUBPASS_MS) {
267 info->ps.layer_input = true;
268 info->ps.uses_input_attachments = true;
269 }
270 mark_sampler_desc(var, info);
271
272 if (nir_intrinsic_image_deref_store ||
273 nir_intrinsic_image_deref_atomic_add ||
274 nir_intrinsic_image_deref_atomic_min ||
275 nir_intrinsic_image_deref_atomic_max ||
276 nir_intrinsic_image_deref_atomic_and ||
277 nir_intrinsic_image_deref_atomic_or ||
278 nir_intrinsic_image_deref_atomic_xor ||
279 nir_intrinsic_image_deref_atomic_exchange ||
280 nir_intrinsic_image_deref_atomic_comp_swap) {
281 if (nir->info.stage == MESA_SHADER_FRAGMENT)
282 info->ps.writes_memory = true;
283 }
284 break;
285 }
286 case nir_intrinsic_store_ssbo:
287 case nir_intrinsic_ssbo_atomic_add:
288 case nir_intrinsic_ssbo_atomic_imin:
289 case nir_intrinsic_ssbo_atomic_umin:
290 case nir_intrinsic_ssbo_atomic_imax:
291 case nir_intrinsic_ssbo_atomic_umax:
292 case nir_intrinsic_ssbo_atomic_and:
293 case nir_intrinsic_ssbo_atomic_or:
294 case nir_intrinsic_ssbo_atomic_xor:
295 case nir_intrinsic_ssbo_atomic_exchange:
296 case nir_intrinsic_ssbo_atomic_comp_swap:
297 if (nir->info.stage == MESA_SHADER_FRAGMENT)
298 info->ps.writes_memory = true;
299 break;
300 case nir_intrinsic_load_deref:
301 gather_intrinsic_load_deref_info(nir, instr, info);
302 break;
303 case nir_intrinsic_store_deref:
304 gather_intrinsic_store_deref_info(nir, instr, info);
305 break;
306 default:
307 break;
308 }
309 }
310
311 static void
312 gather_tex_info(const nir_shader *nir, const nir_tex_instr *instr,
313 struct radv_shader_info *info)
314 {
315 for (unsigned i = 0; i < instr->num_srcs; i++) {
316 switch (instr->src[i].src_type) {
317 case nir_tex_src_texture_deref:
318 mark_sampler_desc(nir_deref_instr_get_variable(nir_src_as_deref(instr->src[i].src)), info);
319 break;
320 case nir_tex_src_sampler_deref:
321 mark_sampler_desc(nir_deref_instr_get_variable(nir_src_as_deref(instr->src[i].src)), info);
322 break;
323 default:
324 break;
325 }
326 }
327 }
328
329 static void
330 gather_info_block(const nir_shader *nir, const nir_block *block,
331 struct radv_shader_info *info)
332 {
333 nir_foreach_instr(instr, block) {
334 switch (instr->type) {
335 case nir_instr_type_intrinsic:
336 gather_intrinsic_info(nir, nir_instr_as_intrinsic(instr), info);
337 break;
338 case nir_instr_type_tex:
339 gather_tex_info(nir, nir_instr_as_tex(instr), info);
340 break;
341 default:
342 break;
343 }
344 }
345 }
346
347 static void
348 gather_info_input_decl_vs(const nir_shader *nir, const nir_variable *var,
349 struct radv_shader_info *info)
350 {
351 int idx = var->data.location;
352
353 if (idx >= VERT_ATTRIB_GENERIC0 && idx <= VERT_ATTRIB_GENERIC15)
354 info->vs.has_vertex_buffers = true;
355 }
356
357 static void
358 gather_info_input_decl_ps(const nir_shader *nir, const nir_variable *var,
359 struct radv_shader_info *info)
360 {
361 unsigned attrib_count = glsl_count_attribute_slots(var->type, false);
362 const struct glsl_type *type = glsl_without_array(var->type);
363 int idx = var->data.location;
364
365 switch (idx) {
366 case VARYING_SLOT_PNTC:
367 info->ps.has_pcoord = true;
368 break;
369 case VARYING_SLOT_PRIMITIVE_ID:
370 info->ps.prim_id_input = true;
371 break;
372 case VARYING_SLOT_LAYER:
373 info->ps.layer_input = true;
374 break;
375 case VARYING_SLOT_CLIP_DIST0:
376 info->ps.num_input_clips_culls = attrib_count;
377 break;
378 default:
379 break;
380 }
381
382 if (glsl_get_base_type(type) == GLSL_TYPE_FLOAT) {
383 if (var->data.sample)
384 info->ps.force_persample = true;
385 }
386 }
387
388 static void
389 gather_info_input_decl(const nir_shader *nir, const nir_variable *var,
390 struct radv_shader_info *info)
391 {
392 switch (nir->info.stage) {
393 case MESA_SHADER_VERTEX:
394 gather_info_input_decl_vs(nir, var, info);
395 break;
396 case MESA_SHADER_FRAGMENT:
397 gather_info_input_decl_ps(nir, var, info);
398 break;
399 default:
400 break;
401 }
402 }
403
404 static void
405 gather_info_output_decl_ls(const nir_shader *nir, const nir_variable *var,
406 struct radv_shader_info *info)
407 {
408 int idx = var->data.location;
409 unsigned param = shader_io_get_unique_index(idx);
410 int num_slots = glsl_count_attribute_slots(var->type, false);
411 if (idx == VARYING_SLOT_CLIP_DIST0)
412 num_slots = (nir->info.clip_distance_array_size + nir->info.cull_distance_array_size > 4) ? 2 : 1;
413 mark_ls_output(info, param, num_slots);
414 }
415
416 static void
417 gather_info_output_decl_ps(const nir_shader *nir, const nir_variable *var,
418 struct radv_shader_info *info)
419 {
420 int idx = var->data.location;
421
422 switch (idx) {
423 case FRAG_RESULT_DEPTH:
424 info->ps.writes_z = true;
425 break;
426 case FRAG_RESULT_STENCIL:
427 info->ps.writes_stencil = true;
428 break;
429 case FRAG_RESULT_SAMPLE_MASK:
430 info->ps.writes_sample_mask = true;
431 break;
432 default:
433 break;
434 }
435 }
436
437 static void
438 gather_info_output_decl(const nir_shader *nir, const nir_variable *var,
439 struct radv_shader_info *info,
440 const struct radv_nir_compiler_options *options)
441 {
442 switch (nir->info.stage) {
443 case MESA_SHADER_FRAGMENT:
444 gather_info_output_decl_ps(nir, var, info);
445 break;
446 case MESA_SHADER_VERTEX:
447 if (options->key.vs.as_ls)
448 gather_info_output_decl_ls(nir, var, info);
449 break;
450 default:
451 break;
452 }
453 }
454
455 void
456 radv_nir_shader_info_pass(const struct nir_shader *nir,
457 const struct radv_nir_compiler_options *options,
458 struct radv_shader_info *info)
459 {
460 struct nir_function *func =
461 (struct nir_function *)exec_list_get_head_const(&nir->functions);
462
463 if (options->layout && options->layout->dynamic_offset_count)
464 info->loads_push_constants = true;
465
466 nir_foreach_variable(variable, &nir->inputs)
467 gather_info_input_decl(nir, variable, info);
468
469 nir_foreach_block(block, func->impl) {
470 gather_info_block(nir, block, info);
471 }
472
473 nir_foreach_variable(variable, &nir->outputs)
474 gather_info_output_decl(nir, variable, info, options);
475 }