1 /*
2 * Copyright © Microsoft Corporation
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
24 #include "dxil_signature.h"
25 #include "dxil_enums.h"
26 #include "dxil_module.h"
27
28 #include "glsl_types.h"
29 #include "nir_to_dxil.h"
30 #include "util/u_debug.h"
31
32 #include <string.h>
33
34
35 struct semantic_info {
36 enum dxil_semantic_kind kind;
37 char name[64];
38 int index;
39 enum dxil_prog_sig_comp_type comp_type;
40 uint8_t sig_comp_type;
41 int32_t start_row;
42 int32_t rows;
43 uint8_t start_col;
44 uint8_t cols;
45 uint8_t interpolation;
46 uint8_t stream;
47 const char *sysvalue_name;
48 };
49
50
51 static bool
is_depth_output(enum dxil_semantic_kind kind)52 is_depth_output(enum dxil_semantic_kind kind)
53 {
54 return kind == DXIL_SEM_DEPTH || kind == DXIL_SEM_DEPTH_GE ||
55 kind == DXIL_SEM_DEPTH_LE || kind == DXIL_SEM_STENCIL_REF;
56 }
57
58 static uint8_t
get_interpolation(nir_variable * var)59 get_interpolation(nir_variable *var)
60 {
61 if (var->data.patch)
62 return DXIL_INTERP_UNDEFINED;
63
64 if (glsl_type_is_integer(glsl_without_array_or_matrix(var->type)) ||
65 glsl_type_is_64bit(glsl_without_array_or_matrix(var->type)))
66 return DXIL_INTERP_CONSTANT;
67
68 if (var->data.sample) {
69 if (var->data.location == VARYING_SLOT_POS)
70 return DXIL_INTERP_LINEAR_NOPERSPECTIVE_SAMPLE;
71 switch (var->data.interpolation) {
72 case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR_SAMPLE;
73 case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
74 case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE_SAMPLE;
75 case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR_SAMPLE;
76 }
77 } else if (unlikely(var->data.centroid)) {
78 if (var->data.location == VARYING_SLOT_POS)
79 return DXIL_INTERP_LINEAR_NOPERSPECTIVE_CENTROID;
80 switch (var->data.interpolation) {
81 case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR_CENTROID;
82 case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
83 case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE_CENTROID;
84 case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR_CENTROID;
85 }
86 } else {
87 if (var->data.location == VARYING_SLOT_POS)
88 return DXIL_INTERP_LINEAR_NOPERSPECTIVE;
89 switch (var->data.interpolation) {
90 case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR;
91 case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
92 case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE;
93 case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR;
94 }
95 }
96
97 return DXIL_INTERP_LINEAR;
98 }
99
100 static const char *
in_sysvalue_name(nir_variable * var)101 in_sysvalue_name(nir_variable *var)
102 {
103 switch (var->data.location) {
104 case VARYING_SLOT_POS:
105 return "POS";
106 case VARYING_SLOT_FACE:
107 return "FACE";
108 case VARYING_SLOT_LAYER:
109 return "RTINDEX";
110 default:
111 return "NONE";
112 }
113 }
114
115 /*
116 * The signatures are written into the stream in two pieces:
117 * DxilProgramSignatureElement is a fixes size structure that gets dumped
118 * to the stream in order of the registers and each contains an offset
119 * to the semantic name string. Then these strings are dumped into the stream.
120 */
121 static unsigned
get_additional_semantic_info(nir_shader * s,nir_variable * var,struct semantic_info * info,unsigned next_row,unsigned clip_size)122 get_additional_semantic_info(nir_shader *s, nir_variable *var, struct semantic_info *info,
123 unsigned next_row, unsigned clip_size)
124 {
125 const struct glsl_type *type = var->type;
126 if (nir_is_arrayed_io(var, s->info.stage))
127 type = glsl_get_array_element(type);
128
129 info->comp_type = dxil_get_prog_sig_comp_type(type);
130 info->sig_comp_type = dxil_get_comp_type_from_prog_sig_type(info->comp_type);
131
132 bool is_depth = is_depth_output(info->kind);
133
134 bool is_gs_input = s->info.stage == MESA_SHADER_GEOMETRY &&
135 (var->data.mode & (nir_var_shader_in | nir_var_system_value));
136
137 info->stream = var->data.stream;
138 info->rows = 1;
139 if (info->kind == DXIL_SEM_TARGET) {
140 info->start_row = info->index;
141 info->cols = 4;
142 } else if (is_depth ||
143 (info->kind == DXIL_SEM_PRIMITIVE_ID && is_gs_input) ||
144 info->kind == DXIL_SEM_COVERAGE ||
145 info->kind == DXIL_SEM_SAMPLE_INDEX) {
146 // This turns into a 'N/A' mask in the disassembly
147 info->start_row = -1;
148 info->cols = 1;
149 } else if (info->kind == DXIL_SEM_TESS_FACTOR ||
150 info->kind == DXIL_SEM_INSIDE_TESS_FACTOR) {
151 assert(var->data.compact);
152 info->start_row = next_row;
153 info->rows = glsl_get_aoa_size(type);
154 info->cols = 1;
155 next_row += info->rows;
156 } else if (var->data.compact) {
157 info->start_row = next_row;
158 next_row++;
159
160 assert(glsl_type_is_array(type) && info->kind == DXIL_SEM_CLIP_DISTANCE);
161 unsigned num_floats = glsl_get_aoa_size(type);
162 unsigned start_offset = (var->data.location - VARYING_SLOT_CLIP_DIST0) * 4 +
163 var->data.location_frac;
164
165 if (start_offset >= clip_size) {
166 info->kind = DXIL_SEM_CULL_DISTANCE;
167 snprintf(info->name, 64, "SV_CullDistance");
168 }
169 info->cols = num_floats;
170 info->start_col = (uint8_t)var->data.location_frac;
171 } else {
172 info->start_row = next_row;
173 info->rows = glsl_count_vec4_slots(type, false, false);
174 if (glsl_type_is_array(type))
175 type = glsl_get_array_element(type);
176 next_row += info->rows;
177 info->start_col = (uint8_t)var->data.location_frac;
178 info->cols = MIN2(glsl_get_component_slots(type), 4);
179 }
180
181 return next_row;
182 }
183
184 typedef void (*semantic_info_proc)(nir_variable *var, struct semantic_info *info, gl_shader_stage stage);
185
186 static void
get_semantic_vs_in_name(nir_variable * var,struct semantic_info * info,gl_shader_stage stage)187 get_semantic_vs_in_name(nir_variable *var, struct semantic_info *info, gl_shader_stage stage)
188 {
189 strcpy(info->name, "TEXCOORD");
190 info->index = var->data.driver_location;
191 info->kind = DXIL_SEM_ARBITRARY;
192 }
193
194 static void
get_semantic_sv_name(nir_variable * var,struct semantic_info * info,gl_shader_stage stage)195 get_semantic_sv_name(nir_variable *var, struct semantic_info *info, gl_shader_stage stage)
196 {
197 if (stage != MESA_SHADER_VERTEX)
198 info->interpolation = get_interpolation(var);
199
200 switch (var->data.location) {
201 case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE:
202 info->kind = DXIL_SEM_VERTEX_ID;
203 break;
204 case SYSTEM_VALUE_INSTANCE_ID:
205 info->kind = DXIL_SEM_INSTANCE_ID;
206 break;
207 case SYSTEM_VALUE_PRIMITIVE_ID:
208 info->kind = DXIL_SEM_PRIMITIVE_ID;
209 break;
210 case SYSTEM_VALUE_SAMPLE_ID:
211 info->kind = DXIL_SEM_SAMPLE_INDEX;
212 break;
213 default:
214 unreachable("unsupported system value");
215 }
216 strncpy(info->name, var->name, ARRAY_SIZE(info->name) - 1);
217 }
218
219 static void
get_semantic_ps_outname(nir_variable * var,struct semantic_info * info)220 get_semantic_ps_outname(nir_variable *var, struct semantic_info *info)
221 {
222 info->kind = DXIL_SEM_INVALID;
223 switch (var->data.location) {
224 case FRAG_RESULT_COLOR:
225 snprintf(info->name, 64, "%s", "SV_Target");
226 info->index = var->data.index;
227 info->kind = DXIL_SEM_TARGET;
228 break;
229 case FRAG_RESULT_DATA0:
230 case FRAG_RESULT_DATA1:
231 case FRAG_RESULT_DATA2:
232 case FRAG_RESULT_DATA3:
233 case FRAG_RESULT_DATA4:
234 case FRAG_RESULT_DATA5:
235 case FRAG_RESULT_DATA6:
236 case FRAG_RESULT_DATA7:
237 snprintf(info->name, 64, "%s", "SV_Target");
238 info->index = var->data.location - FRAG_RESULT_DATA0;
239 if (var->data.location == FRAG_RESULT_DATA0 &&
240 var->data.index > 0)
241 info->index = var->data.index;
242 info->kind = DXIL_SEM_TARGET;
243 break;
244 case FRAG_RESULT_DEPTH:
245 snprintf(info->name, 64, "%s", "SV_Depth");
246 info->kind = DXIL_SEM_DEPTH;
247 break;
248 case FRAG_RESULT_STENCIL:
249 snprintf(info->name, 64, "%s", "SV_StencilRef");
250 info->kind = DXIL_SEM_STENCIL_REF; //??
251 break;
252 case FRAG_RESULT_SAMPLE_MASK:
253 snprintf(info->name, 64, "%s", "SV_Coverage");
254 info->kind = DXIL_SEM_COVERAGE; //??
255 break;
256 default:
257 snprintf(info->name, 64, "%s", "UNDEFINED");
258 break;
259 }
260 }
261
262 static void
get_semantic_name(nir_variable * var,struct semantic_info * info,const struct glsl_type * type)263 get_semantic_name(nir_variable *var, struct semantic_info *info,
264 const struct glsl_type *type)
265 {
266 info->kind = DXIL_SEM_INVALID;
267 info->interpolation = get_interpolation(var);
268 switch (var->data.location) {
269
270 case VARYING_SLOT_POS:
271 assert(glsl_get_components(type) == 4);
272 snprintf(info->name, 64, "%s", "SV_Position");
273 info->kind = DXIL_SEM_POSITION;
274 break;
275
276 case VARYING_SLOT_FACE:
277 assert(glsl_get_components(type) == 1);
278 snprintf(info->name, 64, "%s", "SV_IsFrontFace");
279 info->kind = DXIL_SEM_IS_FRONT_FACE;
280 break;
281
282 case VARYING_SLOT_PRIMITIVE_ID:
283 assert(glsl_get_components(type) == 1);
284 snprintf(info->name, 64, "%s", "SV_PrimitiveID");
285 info->kind = DXIL_SEM_PRIMITIVE_ID;
286 break;
287
288 case VARYING_SLOT_CLIP_DIST1:
289 info->index = 1;
290 FALLTHROUGH;
291 case VARYING_SLOT_CLIP_DIST0:
292 assert(var->data.location == VARYING_SLOT_CLIP_DIST1 || info->index == 0);
293 snprintf(info->name, 64, "%s", "SV_ClipDistance");
294 info->kind = DXIL_SEM_CLIP_DISTANCE;
295 break;
296
297 case VARYING_SLOT_TESS_LEVEL_INNER:
298 assert(glsl_get_components(type) <= 2);
299 snprintf(info->name, 64, "%s", "SV_InsideTessFactor");
300 info->kind = DXIL_SEM_INSIDE_TESS_FACTOR;
301 break;
302
303 case VARYING_SLOT_TESS_LEVEL_OUTER:
304 assert(glsl_get_components(type) <= 4);
305 snprintf(info->name, 64, "%s", "SV_TessFactor");
306 info->kind = DXIL_SEM_TESS_FACTOR;
307 break;
308
309 case VARYING_SLOT_VIEWPORT:
310 assert(glsl_get_components(type) == 1);
311 snprintf(info->name, 64, "%s", "SV_ViewportArrayIndex");
312 info->kind = DXIL_SEM_VIEWPORT_ARRAY_INDEX;
313 break;
314
315 case VARYING_SLOT_LAYER:
316 assert(glsl_get_components(type) == 1);
317 snprintf(info->name, 64, "%s", "SV_RenderTargetArrayIndex");
318 info->kind = DXIL_SEM_RENDERTARGET_ARRAY_INDEX;
319 break;
320
321 default: {
322 info->index = var->data.driver_location;
323 strcpy(info->name, "TEXCOORD");
324 info->kind = DXIL_SEM_ARBITRARY;
325 }
326 }
327 }
328
329 static void
get_semantic_in_name(nir_variable * var,struct semantic_info * info,gl_shader_stage stage)330 get_semantic_in_name(nir_variable *var, struct semantic_info *info, gl_shader_stage stage)
331 {
332 const struct glsl_type *type = var->type;
333 if (nir_is_arrayed_io(var, stage) &&
334 glsl_type_is_array(type))
335 type = glsl_get_array_element(type);
336
337 get_semantic_name(var, info, type);
338 info->sysvalue_name = in_sysvalue_name(var);
339 }
340
341
342 static enum dxil_prog_sig_semantic
prog_semantic_from_kind(enum dxil_semantic_kind kind,unsigned num_vals,unsigned start_val)343 prog_semantic_from_kind(enum dxil_semantic_kind kind, unsigned num_vals, unsigned start_val)
344 {
345 switch (kind) {
346 case DXIL_SEM_ARBITRARY: return DXIL_PROG_SEM_UNDEFINED;
347 case DXIL_SEM_VERTEX_ID: return DXIL_PROG_SEM_VERTEX_ID;
348 case DXIL_SEM_INSTANCE_ID: return DXIL_PROG_SEM_INSTANCE_ID;
349 case DXIL_SEM_POSITION: return DXIL_PROG_SEM_POSITION;
350 case DXIL_SEM_COVERAGE: return DXIL_PROG_SEM_COVERAGE;
351 case DXIL_SEM_INNER_COVERAGE: return DXIL_PROG_SEM_INNER_COVERAGE;
352 case DXIL_SEM_PRIMITIVE_ID: return DXIL_PROG_SEM_PRIMITIVE_ID;
353 case DXIL_SEM_SAMPLE_INDEX: return DXIL_PROG_SEM_SAMPLE_INDEX;
354 case DXIL_SEM_IS_FRONT_FACE: return DXIL_PROG_SEM_IS_FRONTFACE;
355 case DXIL_SEM_RENDERTARGET_ARRAY_INDEX: return DXIL_PROG_SEM_RENDERTARGET_ARRAY_INDEX;
356 case DXIL_SEM_VIEWPORT_ARRAY_INDEX: return DXIL_PROG_SEM_VIEWPORT_ARRAY_INDEX;
357 case DXIL_SEM_CLIP_DISTANCE: return DXIL_PROG_SEM_CLIP_DISTANCE;
358 case DXIL_SEM_CULL_DISTANCE: return DXIL_PROG_SEM_CULL_DISTANCE;
359 case DXIL_SEM_BARYCENTRICS: return DXIL_PROG_SEM_BARYCENTRICS;
360 case DXIL_SEM_SHADING_RATE: return DXIL_PROG_SEM_SHADING_RATE;
361 case DXIL_SEM_CULL_PRIMITIVE: return DXIL_PROG_SEM_CULL_PRIMITIVE;
362 case DXIL_SEM_TARGET: return DXIL_PROG_SEM_TARGET;
363 case DXIL_SEM_DEPTH: return DXIL_PROG_SEM_DEPTH;
364 case DXIL_SEM_DEPTH_LE: return DXIL_PROG_SEM_DEPTH_LE;
365 case DXIL_SEM_DEPTH_GE: return DXIL_PROG_SEM_DEPTH_GE;
366 case DXIL_SEM_STENCIL_REF: return DXIL_PROG_SEM_STENCIL_REF;
367 case DXIL_SEM_TESS_FACTOR:
368 switch (num_vals) {
369 case 4: return DXIL_PROG_SEM_FINAL_QUAD_EDGE_TESSFACTOR;
370 case 3: return DXIL_PROG_SEM_FINAL_TRI_EDGE_TESSFACTOR;
371 case 2: return start_val == 0 ?
372 DXIL_PROG_SEM_FINAL_LINE_DENSITY_TESSFACTOR :
373 DXIL_PROG_SEM_FINAL_LINE_DETAIL_TESSFACTOR;
374 default:
375 unreachable("Invalid row count for tess factor");
376 }
377 case DXIL_SEM_INSIDE_TESS_FACTOR:
378 switch (num_vals) {
379 case 2: return DXIL_PROG_SEM_FINAL_QUAD_INSIDE_EDGE_TESSFACTOR;
380 case 1: return DXIL_PROG_SEM_FINAL_TRI_INSIDE_EDGE_TESSFACTOR;
381 default:
382 unreachable("Invalid row count for inner tess factor");
383 }
384 default:
385 return DXIL_PROG_SEM_UNDEFINED;
386 }
387 }
388
389 static
390 uint32_t
copy_semantic_name_to_string(struct _mesa_string_buffer * string_out,const char * name)391 copy_semantic_name_to_string(struct _mesa_string_buffer *string_out, const char *name)
392 {
393 /* copy the semantic name */
394 uint32_t retval = string_out->length;
395 size_t name_len = strlen(name) + 1;
396 _mesa_string_buffer_append_len(string_out, name, name_len);
397 return retval;
398 }
399
400 static
401 uint32_t
append_semantic_index_to_table(struct dxil_psv_sem_index_table * table,uint32_t index,uint32_t num_rows)402 append_semantic_index_to_table(struct dxil_psv_sem_index_table *table, uint32_t index,
403 uint32_t num_rows)
404 {
405 for (unsigned i = 0; i < table->size; ++i) {
406 unsigned j = 0;
407 for (; j < num_rows && i + j < table->size; ++j)
408 if (table->data[i + j] != index + j)
409 break;
410 if (j == num_rows)
411 return i;
412 else if (j > 0)
413 i += j - 1;
414 }
415 uint32_t retval = table->size;
416 assert(table->size + num_rows <= ARRAY_SIZE(table->data));
417 for (unsigned i = 0; i < num_rows; ++i)
418 table->data[table->size++] = index + i;
419 return retval;
420 }
421
422 static const struct dxil_mdnode *
fill_SV_param_nodes(struct dxil_module * mod,unsigned record_id,const struct dxil_signature_record * rec,const struct dxil_psv_signature_element * psv,bool is_input)423 fill_SV_param_nodes(struct dxil_module *mod, unsigned record_id,
424 const struct dxil_signature_record *rec,
425 const struct dxil_psv_signature_element *psv,
426 bool is_input) {
427
428 const struct dxil_mdnode *SV_params_nodes[11];
429 /* For this to always work we should use vectorize_io, but for FS out and VS in
430 * this is not implemented globally */
431 const struct dxil_mdnode *flattened_semantics[256];
432
433 for (unsigned i = 0; i < rec->num_elements; ++i)
434 flattened_semantics[i] = dxil_get_metadata_int32(mod, rec->elements[i].semantic_index);
435
436 SV_params_nodes[0] = dxil_get_metadata_int32(mod, (int)record_id); // Unique element ID
437 SV_params_nodes[1] = dxil_get_metadata_string(mod, rec->name); // Element name
438 SV_params_nodes[2] = dxil_get_metadata_int8(mod, rec->sig_comp_type); // Element type
439 SV_params_nodes[3] = dxil_get_metadata_int8(mod, (int8_t)psv->semantic_kind); // Effective system value
440 SV_params_nodes[4] = dxil_get_metadata_node(mod, flattened_semantics,
441 rec->num_elements); // Semantic index vector
442 SV_params_nodes[5] = dxil_get_metadata_int8(mod, psv->interpolation_mode); // Interpolation mode
443 SV_params_nodes[6] = dxil_get_metadata_int32(mod, psv->rows); // Number of rows
444 SV_params_nodes[7] = dxil_get_metadata_int8(mod, psv->cols_and_start & 0xf); // Number of columns
445 SV_params_nodes[8] = dxil_get_metadata_int32(mod, rec->elements[0].reg); // Element packing start row
446 SV_params_nodes[9] = dxil_get_metadata_int8(mod, (psv->cols_and_start >> 4) & 0x3); // Element packing start column
447
448 const struct dxil_mdnode *SV_metadata[6];
449 unsigned num_metadata_nodes = 0;
450 if (rec->elements[0].stream != 0) {
451 SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int32(mod, DXIL_SIGNATURE_ELEMENT_OUTPUT_STREAM);
452 SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int32(mod, rec->elements[0].stream);
453 }
454 uint8_t usage_mask = rec->elements[0].always_reads_mask;
455 if (!is_input)
456 usage_mask = 0xf & ~rec->elements[0].never_writes_mask;
457 if (usage_mask && mod->minor_validator >= 5) {
458 usage_mask >>= (psv->cols_and_start >> 4) & 0x3;
459 SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int32(mod, DXIL_SIGNATURE_ELEMENT_USAGE_COMPONENT_MASK);
460 SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int8(mod, usage_mask);
461 }
462
463 uint8_t dynamic_index_mask = psv->dynamic_mask_and_stream & 0xf;
464 if (dynamic_index_mask) {
465 SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int32(mod, DXIL_SIGNATURE_ELEMENT_DYNAMIC_INDEX_COMPONENT_MASK);
466 SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int8(mod, dynamic_index_mask);
467 }
468
469 SV_params_nodes[10] = num_metadata_nodes ? dxil_get_metadata_node(mod, SV_metadata, num_metadata_nodes) : NULL;
470
471 return dxil_get_metadata_node(mod, SV_params_nodes, ARRAY_SIZE(SV_params_nodes));
472 }
473
474 static void
fill_signature_element(struct dxil_signature_element * elm,struct semantic_info * semantic,unsigned row)475 fill_signature_element(struct dxil_signature_element *elm,
476 struct semantic_info *semantic,
477 unsigned row)
478 {
479 memset(elm, 0, sizeof(struct dxil_signature_element));
480 elm->stream = semantic->stream;
481 // elm->semantic_name_offset = 0; // Offset needs to be filled out when writing
482 elm->semantic_index = semantic->index + row;
483 elm->system_value = (uint32_t) prog_semantic_from_kind(semantic->kind, semantic->rows, row);
484 elm->comp_type = (uint32_t) semantic->comp_type;
485 elm->reg = semantic->start_row + row;
486
487 assert(semantic->cols + semantic->start_col <= 4);
488 elm->mask = (uint8_t) (((1 << semantic->cols) - 1) << semantic->start_col);
489 elm->min_precision = DXIL_MIN_PREC_DEFAULT;
490 }
491
492 static bool
fill_psv_signature_element(struct dxil_psv_signature_element * psv_elm,struct semantic_info * semantic,struct dxil_module * mod)493 fill_psv_signature_element(struct dxil_psv_signature_element *psv_elm,
494 struct semantic_info *semantic, struct dxil_module *mod)
495 {
496 memset(psv_elm, 0, sizeof(struct dxil_psv_signature_element));
497 psv_elm->rows = semantic->rows;
498 if (semantic->start_row >= 0) {
499 assert(semantic->start_row < 256);
500 psv_elm->start_row = semantic->start_row;
501 psv_elm->cols_and_start = (1u << 6) | (semantic->start_col << 4) | semantic->cols;
502 } else {
503 /* The validation expects that the the start row is not egative
504 * and apparently the extra bit in the cols_and_start indicates that the
505 * row is meant literally, so don't set it in this case.
506 * (Source of information: Comparing with the validation structures
507 * created by dxcompiler)
508 */
509 psv_elm->start_row = 0;
510 psv_elm->cols_and_start = (semantic->start_col << 4) | semantic->cols;
511 }
512 psv_elm->semantic_kind = (uint8_t)semantic->kind;
513 psv_elm->component_type = semantic->comp_type;
514 psv_elm->interpolation_mode = semantic->interpolation;
515 psv_elm->dynamic_mask_and_stream = (semantic->stream) << 4;
516 if (semantic->kind == DXIL_SEM_ARBITRARY && strlen(semantic->name)) {
517 psv_elm->semantic_name_offset =
518 copy_semantic_name_to_string(mod->sem_string_table, semantic->name);
519
520 /* TODO: clean up memory */
521 if (psv_elm->semantic_name_offset == (uint32_t)-1)
522 return false;
523 }
524
525 psv_elm->semantic_indexes_offset =
526 append_semantic_index_to_table(&mod->sem_index_table, semantic->index, semantic->rows);
527
528 return true;
529 }
530
531 static bool
fill_io_signature(struct dxil_module * mod,int id,struct semantic_info * semantic,struct dxil_signature_record * rec,struct dxil_psv_signature_element * psv_elm)532 fill_io_signature(struct dxil_module *mod, int id,
533 struct semantic_info *semantic,
534 struct dxil_signature_record *rec,
535 struct dxil_psv_signature_element *psv_elm)
536 {
537 rec->name = ralloc_strdup(mod->ralloc_ctx, semantic->name);
538 rec->num_elements = semantic->rows;
539 rec->sig_comp_type = semantic->sig_comp_type;
540
541 for (unsigned i = 0; i < semantic->rows; ++i)
542 fill_signature_element(&rec->elements[i], semantic, i);
543 return fill_psv_signature_element(psv_elm, semantic, mod);
544 }
545
546 static unsigned
get_input_signature_group(struct dxil_module * mod,unsigned num_inputs,nir_shader * s,nir_variable_mode modes,semantic_info_proc get_semantics,unsigned * row_iter,unsigned input_clip_size)547 get_input_signature_group(struct dxil_module *mod,
548 unsigned num_inputs,
549 nir_shader *s, nir_variable_mode modes,
550 semantic_info_proc get_semantics, unsigned *row_iter,
551 unsigned input_clip_size)
552 {
553 nir_foreach_variable_with_modes(var, s, modes) {
554 if (var->data.patch)
555 continue;
556
557 struct semantic_info semantic = {0};
558 get_semantics(var, &semantic, s->info.stage);
559 mod->inputs[num_inputs].sysvalue = semantic.sysvalue_name;
560 nir_variable *base_var = var;
561 if (var->data.location_frac) {
562 /* Note: Specifically search for a variable that has space for these additional components */
563 nir_foreach_variable_with_modes(test_var, s, modes) {
564 if (var->data.location == test_var->data.location) {
565 /* Variables should be sorted such that we're only looking for an already-emitted variable */
566 if (test_var == var)
567 break;
568 base_var = test_var;
569 if (test_var->data.location_frac == 0 &&
570 glsl_get_component_slots(
571 nir_is_arrayed_io(test_var, s->info.stage) ?
572 glsl_get_array_element(test_var->type) : test_var->type) <= var->data.location_frac)
573 break;
574 }
575 }
576 }
577 if (base_var != var)
578 /* Combine fractional vars into any already existing row */
579 get_additional_semantic_info(s, var, &semantic,
580 mod->psv_inputs[mod->input_mappings[base_var->data.driver_location]].start_row,
581 input_clip_size);
582 else
583 *row_iter = get_additional_semantic_info(s, var, &semantic, *row_iter, input_clip_size);
584
585 mod->input_mappings[var->data.driver_location] = num_inputs;
586 struct dxil_psv_signature_element *psv_elm = &mod->psv_inputs[num_inputs];
587
588 if (!fill_io_signature(mod, num_inputs, &semantic,
589 &mod->inputs[num_inputs], psv_elm))
590 return 0;
591
592 mod->num_psv_inputs = MAX2(mod->num_psv_inputs,
593 semantic.start_row + semantic.rows);
594
595 ++num_inputs;
596 assert(num_inputs < VARYING_SLOT_MAX * 4);
597 }
598 return num_inputs;
599 }
600
601 static void
process_input_signature(struct dxil_module * mod,nir_shader * s,unsigned input_clip_size)602 process_input_signature(struct dxil_module *mod, nir_shader *s, unsigned input_clip_size)
603 {
604 if (s->info.stage == MESA_SHADER_KERNEL)
605 return;
606 unsigned next_row = 0;
607
608 mod->num_sig_inputs = get_input_signature_group(mod, 0,
609 s, nir_var_shader_in,
610 s->info.stage == MESA_SHADER_VERTEX ?
611 get_semantic_vs_in_name : get_semantic_in_name,
612 &next_row, input_clip_size);
613
614 mod->num_sig_inputs = get_input_signature_group(mod, mod->num_sig_inputs,
615 s, nir_var_system_value,
616 get_semantic_sv_name,
617 &next_row, input_clip_size);
618
619 }
620
out_sysvalue_name(nir_variable * var)621 static const char *out_sysvalue_name(nir_variable *var)
622 {
623 switch (var->data.location) {
624 case VARYING_SLOT_FACE:
625 return "FACE";
626 case VARYING_SLOT_POS:
627 return "POS";
628 case VARYING_SLOT_CLIP_DIST0:
629 case VARYING_SLOT_CLIP_DIST1:
630 return "CLIPDST";
631 case VARYING_SLOT_PRIMITIVE_ID:
632 return "PRIMID";
633 default:
634 return "NO";
635 }
636 }
637
638 static void
process_output_signature(struct dxil_module * mod,nir_shader * s)639 process_output_signature(struct dxil_module *mod, nir_shader *s)
640 {
641 unsigned num_outputs = 0;
642 unsigned next_row = 0;
643 nir_foreach_variable_with_modes(var, s, nir_var_shader_out) {
644 struct semantic_info semantic = {0};
645 if (var->data.patch)
646 continue;
647
648 if (s->info.stage == MESA_SHADER_FRAGMENT) {
649 get_semantic_ps_outname(var, &semantic);
650 mod->outputs[num_outputs].sysvalue = "TARGET";
651 } else {
652 const struct glsl_type *type = var->type;
653 if (nir_is_arrayed_io(var, s->info.stage))
654 type = glsl_get_array_element(type);
655 get_semantic_name(var, &semantic, type);
656 mod->outputs[num_outputs].sysvalue = out_sysvalue_name(var);
657 }
658 nir_variable *base_var = var;
659 if (var->data.location_frac) {
660 if (s->info.stage == MESA_SHADER_FRAGMENT) {
661 /* Fragment shader outputs are all either scalars, or must be declared as a single 4-component vector.
662 * Any attempt to declare partial vectors split across multiple variables is ignored.
663 */
664 continue;
665 }
666 base_var = nir_find_variable_with_location(s, nir_var_shader_out, var->data.location);
667 }
668 if (base_var != var &&
669 base_var->data.stream == var->data.stream)
670 /* Combine fractional vars into any already existing row */
671 get_additional_semantic_info(s, var, &semantic,
672 mod->psv_outputs[base_var->data.driver_location].start_row,
673 s->info.clip_distance_array_size);
674 else
675 next_row = get_additional_semantic_info(s, var, &semantic, next_row, s->info.clip_distance_array_size);
676
677 mod->info.has_out_position |= semantic.kind== DXIL_SEM_POSITION;
678 mod->info.has_out_depth |= semantic.kind == DXIL_SEM_DEPTH;
679
680 struct dxil_psv_signature_element *psv_elm = &mod->psv_outputs[num_outputs];
681
682 if (!fill_io_signature(mod, num_outputs, &semantic,
683 &mod->outputs[num_outputs], psv_elm))
684 return;
685
686 for (unsigned i = 0; i < mod->outputs[num_outputs].num_elements; ++i) {
687 struct dxil_signature_element *elm = &mod->outputs[num_outputs].elements[i];
688 if (mod->minor_validator <= 4)
689 elm->never_writes_mask = 0xff & ~elm->mask;
690 else
691 /* This will be updated by the module processing */
692 elm->never_writes_mask = 0xf & ~elm->mask;
693 }
694
695 ++num_outputs;
696
697 mod->num_psv_outputs[semantic.stream] = MAX2(mod->num_psv_outputs[semantic.stream],
698 semantic.start_row + semantic.rows);
699 }
700 mod->num_sig_outputs = num_outputs;
701 }
702
703 static const char *
patch_sysvalue_name(nir_variable * var)704 patch_sysvalue_name(nir_variable *var)
705 {
706 switch (var->data.location) {
707 case VARYING_SLOT_TESS_LEVEL_OUTER:
708 switch (glsl_get_aoa_size(var->type)) {
709 case 4:
710 return "QUADEDGE";
711 case 3:
712 return "TRIEDGE";
713 case 2:
714 return var->data.location_frac == 0 ?
715 "LINEDET" : "LINEDEN";
716 default:
717 unreachable("Unexpected outer tess factor array size");
718 }
719 break;
720 case VARYING_SLOT_TESS_LEVEL_INNER:
721 switch (glsl_get_aoa_size(var->type)) {
722 case 2:
723 return "QUADINT";
724 case 1:
725 return "TRIINT";
726 default:
727 unreachable("Unexpected inner tess factory array size");
728 }
729 break;
730 default:
731 return "NO";
732 }
733 }
734
735 static void
process_patch_const_signature(struct dxil_module * mod,nir_shader * s)736 process_patch_const_signature(struct dxil_module *mod, nir_shader *s)
737 {
738 if (s->info.stage != MESA_SHADER_TESS_CTRL &&
739 s->info.stage != MESA_SHADER_TESS_EVAL)
740 return;
741
742 nir_variable_mode mode = s->info.stage == MESA_SHADER_TESS_CTRL ?
743 nir_var_shader_out : nir_var_shader_in;
744 unsigned num_consts = 0;
745 unsigned next_row = 0;
746 nir_foreach_variable_with_modes(var, s, mode) {
747 struct semantic_info semantic = {0};
748 if (!var->data.patch)
749 continue;
750
751 const struct glsl_type *type = var->type;
752 get_semantic_name(var, &semantic, type);
753
754 mod->patch_consts[num_consts].sysvalue = patch_sysvalue_name(var);
755 next_row = get_additional_semantic_info(s, var, &semantic, next_row, 0);
756
757 struct dxil_psv_signature_element *psv_elm = &mod->psv_patch_consts[num_consts];
758
759 if (!fill_io_signature(mod, num_consts, &semantic,
760 &mod->patch_consts[num_consts], psv_elm))
761 return;
762
763 if (mode == nir_var_shader_out) {
764 for (unsigned i = 0; i < mod->patch_consts[num_consts].num_elements; ++i) {
765 struct dxil_signature_element *elm = &mod->patch_consts[num_consts].elements[i];
766 if (mod->minor_validator <= 4)
767 elm->never_writes_mask = 0xff & ~elm->mask;
768 else
769 /* This will be updated by the module processing */
770 elm->never_writes_mask = 0xf & ~elm->mask;
771 }
772 }
773
774 ++num_consts;
775
776 mod->num_psv_patch_consts = MAX2(mod->num_psv_patch_consts,
777 semantic.start_row + semantic.rows);
778 }
779 mod->num_sig_patch_consts = num_consts;
780 }
781
782 static void
prepare_dependency_tables(struct dxil_module * mod,nir_shader * s)783 prepare_dependency_tables(struct dxil_module *mod, nir_shader *s)
784 {
785 bool uses_view_id = BITSET_TEST(s->info.system_values_read, SYSTEM_VALUE_VIEW_INDEX);
786 uint32_t num_output_streams = s->info.stage == MESA_SHADER_GEOMETRY ? 4 : 1;
787 uint32_t num_tables = s->info.stage == MESA_SHADER_TESS_CTRL || s->info.stage == MESA_SHADER_TESS_EVAL ? 2 : num_output_streams;
788
789 const uint32_t output_vecs_per_dword = 32 /* bits per dword */ / 4 /* components per vec */;
790 const uint32_t masks_per_input_vec = 4 /* components per vec */;
791
792 for (uint32_t i = 0; i < num_output_streams; ++i)
793 mod->dependency_table_dwords_per_input[i] = DIV_ROUND_UP(mod->num_psv_outputs[i], output_vecs_per_dword);
794 if (s->info.stage == MESA_SHADER_TESS_CTRL)
795 mod->dependency_table_dwords_per_input[1] = DIV_ROUND_UP(mod->num_psv_patch_consts, output_vecs_per_dword);
796
797 uint32_t view_id_table_sizes[4] = { 0 };
798 if (uses_view_id) {
799 for (uint32_t i = 0; i < 4; ++i)
800 view_id_table_sizes[i] = mod->dependency_table_dwords_per_input[i];
801 }
802
803 for (uint32_t i = 0; i < num_output_streams; ++i)
804 mod->io_dependency_table_size[i] = mod->dependency_table_dwords_per_input[i] * mod->num_psv_inputs * masks_per_input_vec;
805 if (s->info.stage == MESA_SHADER_TESS_CTRL)
806 mod->io_dependency_table_size[1] = mod->dependency_table_dwords_per_input[1] * mod->num_psv_inputs * masks_per_input_vec;
807 else if (s->info.stage == MESA_SHADER_TESS_EVAL)
808 mod->io_dependency_table_size[1] = mod->dependency_table_dwords_per_input[0] * mod->num_psv_patch_consts * masks_per_input_vec;
809
810 mod->serialized_dependency_table_size = num_tables + 1;
811 for (uint32_t i = 0; i < num_tables; ++i) {
812 mod->serialized_dependency_table_size += view_id_table_sizes[i] + mod->io_dependency_table_size[i];
813 }
814
815 uint32_t *table = calloc(mod->serialized_dependency_table_size, sizeof(uint32_t));
816 mod->serialized_dependency_table = table;
817
818 *(table++) = mod->num_psv_inputs * 4;
819 for (uint32_t i = 0; i < num_output_streams; ++i) {
820 *(table++) = mod->num_psv_outputs[i] * 4;
821 mod->viewid_dependency_table[i] = table;
822 table += view_id_table_sizes[i];
823 mod->io_dependency_table[i] = table;
824 table += mod->io_dependency_table_size[i];
825 }
826 if (s->info.stage == MESA_SHADER_TESS_CTRL || s->info.stage == MESA_SHADER_TESS_EVAL) {
827 *(table++) = mod->num_psv_patch_consts * 4;
828 if (s->info.stage == MESA_SHADER_TESS_CTRL) {
829 mod->viewid_dependency_table[1] = table;
830 table += view_id_table_sizes[1];
831 }
832 mod->io_dependency_table[1] = table;
833 table += mod->io_dependency_table_size[1];
834 }
835 }
836
837 void
preprocess_signatures(struct dxil_module * mod,nir_shader * s,unsigned input_clip_size)838 preprocess_signatures(struct dxil_module *mod, nir_shader *s, unsigned input_clip_size)
839 {
840 /* DXC does the same: Add an empty string before everything else */
841 mod->sem_string_table = _mesa_string_buffer_create(mod->ralloc_ctx, 1024);
842 copy_semantic_name_to_string(mod->sem_string_table, "");
843
844 process_input_signature(mod, s, input_clip_size);
845 process_output_signature(mod, s);
846 process_patch_const_signature(mod, s);
847
848 prepare_dependency_tables(mod, s);
849 }
850
851 static const struct dxil_mdnode *
get_signature_metadata(struct dxil_module * mod,const struct dxil_signature_record * recs,const struct dxil_psv_signature_element * psvs,unsigned num_elements,bool is_input)852 get_signature_metadata(struct dxil_module *mod,
853 const struct dxil_signature_record *recs,
854 const struct dxil_psv_signature_element *psvs,
855 unsigned num_elements,
856 bool is_input)
857 {
858 if (num_elements == 0)
859 return NULL;
860
861 const struct dxil_mdnode *nodes[VARYING_SLOT_MAX * 4];
862 for (unsigned i = 0; i < num_elements; ++i) {
863 nodes[i] = fill_SV_param_nodes(mod, i, &recs[i], &psvs[i], is_input);
864 }
865
866 return dxil_get_metadata_node(mod, nodes, num_elements);
867 }
868
869 const struct dxil_mdnode *
get_signatures(struct dxil_module * mod)870 get_signatures(struct dxil_module *mod)
871 {
872 const struct dxil_mdnode *input_signature = get_signature_metadata(mod, mod->inputs, mod->psv_inputs, mod->num_sig_inputs, true);
873 const struct dxil_mdnode *output_signature = get_signature_metadata(mod, mod->outputs, mod->psv_outputs, mod->num_sig_outputs, false);
874 const struct dxil_mdnode *patch_const_signature = get_signature_metadata(mod, mod->patch_consts, mod->psv_patch_consts, mod->num_sig_patch_consts,
875 mod->shader_kind == DXIL_DOMAIN_SHADER);
876
877 const struct dxil_mdnode *SV_nodes[3] = {
878 input_signature,
879 output_signature,
880 patch_const_signature
881 };
882 if (output_signature || input_signature || patch_const_signature)
883 return dxil_get_metadata_node(mod, SV_nodes, ARRAY_SIZE(SV_nodes));
884 else
885 return NULL;
886 }
887