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 const char *sysvalue_name;
47 };
48
49
50 static bool
is_depth_output(enum dxil_semantic_kind kind)51 is_depth_output(enum dxil_semantic_kind kind)
52 {
53 return kind == DXIL_SEM_DEPTH || kind == DXIL_SEM_DEPTH_GE ||
54 kind == DXIL_SEM_DEPTH_LE || kind == DXIL_SEM_STENCIL_REF;
55 }
56
57 static uint8_t
get_interpolation(nir_variable * var)58 get_interpolation(nir_variable *var)
59 {
60 if (unlikely(var->data.centroid)) {
61 switch (var->data.interpolation) {
62 case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR_CENTROID;
63 case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
64 case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE_CENTROID;
65 case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR_CENTROID;
66
67 }
68 } else {
69 switch (var->data.interpolation) {
70 case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR;
71 case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
72 case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE;
73 case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR;
74 }
75 }
76
77 return DXIL_INTERP_LINEAR;
78 }
79
80 static const char *
in_sysvalue_name(nir_variable * var)81 in_sysvalue_name(nir_variable *var)
82 {
83 switch (var->data.location) {
84 case VARYING_SLOT_POS:
85 return "POS";
86 case VARYING_SLOT_FACE:
87 return "FACE";
88 default:
89 return "NONE";
90 }
91 }
92
93 /*
94 * The signatures are written into the stream in two pieces:
95 * DxilProgramSignatureElement is a fixes size structure that gets dumped
96 * to the stream in order of the registers and each contains an offset
97 * to the semantic name string. Then these strings are dumped into the stream.
98 */
99 static unsigned
get_additional_semantic_info(nir_shader * s,nir_variable * var,struct semantic_info * info,unsigned next_row,bool is_gs_shader)100 get_additional_semantic_info(nir_shader *s, nir_variable *var, struct semantic_info *info,
101 unsigned next_row, bool is_gs_shader)
102 {
103 const struct glsl_type *type = var->type;
104
105 info->comp_type =
106 dxil_get_prog_sig_comp_type(var->type);
107
108 bool is_depth = is_depth_output(info->kind);
109 info->sig_comp_type = dxil_get_comp_type(var->type);
110
111 info->rows = 1;
112 if (info->kind == DXIL_SEM_TARGET) {
113 info->start_row = info->index;
114 } else if (is_depth ||
115 (info->kind == DXIL_SEM_PRIMITIVE_ID && is_gs_shader) ||
116 info->kind == DXIL_SEM_COVERAGE ||
117 info->kind == DXIL_SEM_SAMPLE_INDEX) {
118 // This turns into a 'N/A' mask in the disassembly
119 info->start_row = -1;
120 } else if (var->data.compact) {
121 if (var->data.location_frac) {
122 info->start_row = next_row - 1;
123 } else {
124 info->start_row = next_row;
125 next_row++;
126 }
127
128 assert(glsl_type_is_array(type) && info->kind == DXIL_SEM_CLIP_DISTANCE);
129 unsigned num_floats = glsl_get_aoa_size(type);
130 unsigned start_offset = (var->data.location - VARYING_SLOT_CLIP_DIST0) * 4 +
131 var->data.location_frac;
132
133 if (start_offset >= s->info.clip_distance_array_size) {
134 info->kind = DXIL_SEM_CULL_DISTANCE;
135 snprintf(info->name, 64, "SV_CullDistance");
136 }
137 info->cols = num_floats;
138 } else {
139 info->start_row = next_row;
140 if (glsl_type_is_array(type) && is_gs_shader)
141 type = glsl_without_array(type);
142
143 if (glsl_type_is_array(type)) {
144 info->rows = glsl_get_aoa_size(type);
145 type = glsl_get_array_element(type);
146 assert(info->rows);
147 }
148 next_row += info->rows;
149 }
150 info->start_col = (uint8_t)var->data.location_frac;
151 if (!info->cols) {
152 if (glsl_type_is_array(type))
153 type = glsl_get_array_element(type);
154 info->cols = (uint8_t)glsl_get_components(type);
155 }
156
157 return next_row;
158 }
159
160 typedef void (*semantic_info_proc)(nir_variable *var, struct semantic_info *info, bool vulkan);
161
162 static void
get_semantic_vs_in_name(nir_variable * var,struct semantic_info * info,bool vulkan)163 get_semantic_vs_in_name(nir_variable *var, struct semantic_info *info, bool vulkan)
164 {
165 strcpy(info->name, "TEXCOORD");
166 if (vulkan) {
167 info->index = var->data.location >= VERT_ATTRIB_GENERIC0 ?
168 var->data.location - VERT_ATTRIB_GENERIC0 :
169 var->data.location;
170 } else {
171 info->index = var->data.driver_location;
172 }
173 info->kind = DXIL_SEM_ARBITRARY;
174 }
175
176 static void
get_semantic_sv_name(nir_variable * var,struct semantic_info * info,bool _vulkan)177 get_semantic_sv_name(nir_variable *var, struct semantic_info *info, bool _vulkan)
178 {
179 switch (var->data.location) {
180 case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE:
181 info->kind = DXIL_SEM_VERTEX_ID;
182 break;
183 case SYSTEM_VALUE_FRONT_FACE:
184 info->kind = DXIL_SEM_IS_FRONT_FACE;
185 break;
186 case SYSTEM_VALUE_INSTANCE_ID:
187 info->kind = DXIL_SEM_INSTANCE_ID;
188 break;
189 case SYSTEM_VALUE_PRIMITIVE_ID:
190 info->kind = DXIL_SEM_PRIMITIVE_ID;
191 break;
192 case SYSTEM_VALUE_SAMPLE_ID:
193 info->kind = DXIL_SEM_SAMPLE_INDEX;
194 info->interpolation = get_interpolation(var);
195 break;
196 default:
197 unreachable("unsupported system value");
198 }
199 strncpy(info->name, var->name, ARRAY_SIZE(info->name) - 1);
200 }
201
202 static void
get_semantic_ps_outname(nir_variable * var,struct semantic_info * info)203 get_semantic_ps_outname(nir_variable *var, struct semantic_info *info)
204 {
205 info->kind = DXIL_SEM_INVALID;
206 switch (var->data.location) {
207 case FRAG_RESULT_COLOR:
208 snprintf(info->name, 64, "%s", "SV_Target");
209 info->index = var->data.index;
210 info->kind = DXIL_SEM_TARGET;
211 break;
212 case FRAG_RESULT_DATA0:
213 case FRAG_RESULT_DATA1:
214 case FRAG_RESULT_DATA2:
215 case FRAG_RESULT_DATA3:
216 case FRAG_RESULT_DATA4:
217 case FRAG_RESULT_DATA5:
218 case FRAG_RESULT_DATA6:
219 case FRAG_RESULT_DATA7:
220 snprintf(info->name, 64, "%s", "SV_Target");
221 info->index = var->data.location - FRAG_RESULT_DATA0;
222 if (var->data.location == FRAG_RESULT_DATA0 &&
223 var->data.index > 0)
224 info->index = var->data.index;
225 info->kind = DXIL_SEM_TARGET;
226 break;
227 case FRAG_RESULT_DEPTH:
228 snprintf(info->name, 64, "%s", "SV_Depth");
229 info->kind = DXIL_SEM_DEPTH;
230 break;
231 case FRAG_RESULT_STENCIL:
232 snprintf(info->name, 64, "%s", "SV_StencilRef");
233 info->kind = DXIL_SEM_STENCIL_REF; //??
234 break;
235 case FRAG_RESULT_SAMPLE_MASK:
236 snprintf(info->name, 64, "%s", "SV_Coverage");
237 info->kind = DXIL_SEM_COVERAGE; //??
238 break;
239 default:
240 snprintf(info->name, 64, "%s", "UNDEFINED");
241 break;
242 }
243 }
244
245 static void
get_semantic_name(nir_variable * var,struct semantic_info * info,const struct glsl_type * type,bool vulkan)246 get_semantic_name(nir_variable *var, struct semantic_info *info,
247 const struct glsl_type *type, bool vulkan)
248 {
249 info->kind = DXIL_SEM_INVALID;
250 info->interpolation = get_interpolation(var);
251 switch (var->data.location) {
252
253 case VARYING_SLOT_POS:
254 assert(glsl_get_components(type) == 4);
255 snprintf(info->name, 64, "%s", "SV_Position");
256 info->kind = DXIL_SEM_POSITION;
257 break;
258
259 case VARYING_SLOT_FACE:
260 assert(glsl_get_components(var->type) == 1);
261 snprintf(info->name, 64, "%s", "SV_IsFrontFace");
262 info->kind = DXIL_SEM_IS_FRONT_FACE;
263 break;
264
265 case VARYING_SLOT_PRIMITIVE_ID:
266 assert(glsl_get_components(var->type) == 1);
267 snprintf(info->name, 64, "%s", "SV_PrimitiveID");
268 info->kind = DXIL_SEM_PRIMITIVE_ID;
269 break;
270
271 case VARYING_SLOT_CLIP_DIST1:
272 info->index = 1;
273 FALLTHROUGH;
274 case VARYING_SLOT_CLIP_DIST0:
275 assert(var->data.location == VARYING_SLOT_CLIP_DIST1 || info->index == 0);
276 snprintf(info->name, 64, "%s", "SV_ClipDistance");
277 info->kind = DXIL_SEM_CLIP_DISTANCE;
278 break;
279
280 default: {
281 info->index = var->data.location -
282 (vulkan ? VARYING_SLOT_VAR0 : VARYING_SLOT_POS);
283 strcpy(info->name, "TEXCOORD");
284 info->kind = DXIL_SEM_ARBITRARY;
285 }
286 }
287 }
288
289 static void
get_semantic_in_name(nir_variable * var,struct semantic_info * info,bool vulkan)290 get_semantic_in_name(nir_variable *var, struct semantic_info *info, bool vulkan)
291 {
292 get_semantic_name(var, info, var->type, vulkan);
293 info->sysvalue_name = in_sysvalue_name(var);
294 }
295
296 static void
get_semantic_gs_in_name(nir_variable * var,struct semantic_info * info,bool vulkan)297 get_semantic_gs_in_name(nir_variable *var, struct semantic_info *info, bool vulkan)
298 {
299 /* geometry shader input varyings come as arrays, but we want to use
300 * the element type */
301 const struct glsl_type *type =
302 glsl_type_is_array(var->type) ? glsl_without_array(var->type) : var->type;
303
304 get_semantic_name(var, info, type, vulkan);
305 info->sysvalue_name = in_sysvalue_name(var);
306 }
307
308
309 static enum dxil_prog_sig_semantic
prog_semantic_from_kind(enum dxil_semantic_kind kind)310 prog_semantic_from_kind(enum dxil_semantic_kind kind)
311 {
312 switch (kind) {
313 case DXIL_SEM_ARBITRARY: return DXIL_PROG_SEM_UNDEFINED;
314 case DXIL_SEM_VERTEX_ID: return DXIL_PROG_SEM_VERTEX_ID;
315 case DXIL_SEM_INSTANCE_ID: return DXIL_PROG_SEM_INSTANCE_ID;
316 case DXIL_SEM_POSITION: return DXIL_PROG_SEM_POSITION;
317 case DXIL_SEM_COVERAGE: return DXIL_PROG_SEM_COVERAGE;
318 case DXIL_SEM_INNER_COVERAGE: return DXIL_PROG_SEM_INNER_COVERAGE;
319 case DXIL_SEM_PRIMITIVE_ID: return DXIL_PROG_SEM_PRIMITIVE_ID;
320 case DXIL_SEM_SAMPLE_INDEX: return DXIL_PROG_SEM_SAMPLE_INDEX;
321 case DXIL_SEM_IS_FRONT_FACE: return DXIL_PROG_SEM_IS_FRONTFACE;
322 case DXIL_SEM_RENDERTARGET_ARRAY_INDEX: return DXIL_PROG_SEM_RENDERTARGET_ARRAY_INDEX;
323 case DXIL_SEM_VIEWPORT_ARRAY_INDEX: return DXIL_PROG_SEM_VIEWPORT_ARRAY_INDEX;
324 case DXIL_SEM_CLIP_DISTANCE: return DXIL_PROG_SEM_CLIP_DISTANCE;
325 case DXIL_SEM_CULL_DISTANCE: return DXIL_PROG_SEM_CULL_DISTANCE;
326 case DXIL_SEM_BARYCENTRICS: return DXIL_PROG_SEM_BARYCENTRICS;
327 case DXIL_SEM_SHADING_RATE: return DXIL_PROG_SEM_SHADING_RATE;
328 case DXIL_SEM_CULL_PRIMITIVE: return DXIL_PROG_SEM_CULL_PRIMITIVE;
329 case DXIL_SEM_TARGET: return DXIL_PROG_SEM_TARGET;
330 case DXIL_SEM_DEPTH: return DXIL_PROG_SEM_DEPTH;
331 case DXIL_SEM_DEPTH_LE: return DXIL_PROG_SEM_DEPTH_LE;
332 case DXIL_SEM_DEPTH_GE: return DXIL_PROG_SEM_DEPTH_GE;
333 case DXIL_SEM_STENCIL_REF: return DXIL_PROG_SEM_STENCIL_REF;
334 default:
335 return DXIL_PROG_SEM_UNDEFINED;
336 }
337 }
338
339 static
340 uint32_t
copy_semantic_name_to_string(struct _mesa_string_buffer * string_out,const char * name)341 copy_semantic_name_to_string(struct _mesa_string_buffer *string_out, const char *name)
342 {
343 /* copy the semantic name */
344 uint32_t retval = string_out->length;
345 size_t name_len = strlen(name) + 1;
346 _mesa_string_buffer_append_len(string_out, name, name_len);
347 return retval;
348 }
349
350 static
351 uint32_t
append_semantic_index_to_table(struct dxil_psv_sem_index_table * table,uint32_t index,uint32_t num_rows)352 append_semantic_index_to_table(struct dxil_psv_sem_index_table *table, uint32_t index,
353 uint32_t num_rows)
354 {
355 if (num_rows == 1) {
356 for (unsigned i = 0; i < table->size; ++i) {
357 if (table->data[i] == index)
358 return i;
359 }
360 }
361 uint32_t retval = table->size;
362 assert(table->size + num_rows <= 80);
363 for (unsigned i = 0; i < num_rows; ++i)
364 table->data[table->size++] = index + i;
365 return retval;
366 }
367
368 static const struct dxil_mdnode *
fill_SV_param_nodes(struct dxil_module * mod,unsigned record_id,struct semantic_info * semantic)369 fill_SV_param_nodes(struct dxil_module *mod, unsigned record_id,
370 struct semantic_info *semantic) {
371
372 const struct dxil_mdnode *SV_params_nodes[11];
373 /* For this to always work we should use vectorize_io, but for FS out and VS in
374 * this is not implemented globally */
375 const struct dxil_mdnode *flattened_semantics[256];
376
377 for (unsigned i = 0; i < semantic->rows; ++i)
378 flattened_semantics[i] = dxil_get_metadata_int32(mod, semantic->index + i);
379
380 SV_params_nodes[0] = dxil_get_metadata_int32(mod, (int)record_id); // Unique element ID
381 SV_params_nodes[1] = dxil_get_metadata_string(mod, semantic->name); // Element name
382 SV_params_nodes[2] = dxil_get_metadata_int8(mod, semantic->sig_comp_type); // Element type
383 SV_params_nodes[3] = dxil_get_metadata_int8(mod, (int8_t)semantic->kind); // Effective system value
384 SV_params_nodes[4] = dxil_get_metadata_node(mod, flattened_semantics,
385 semantic->rows); // Semantic index vector
386 SV_params_nodes[5] = dxil_get_metadata_int8(mod, semantic->interpolation); // Interpolation mode
387 SV_params_nodes[6] = dxil_get_metadata_int32(mod, semantic->rows); // Number of rows
388 SV_params_nodes[7] = dxil_get_metadata_int8(mod, semantic->cols); // Number of columns
389 SV_params_nodes[8] = dxil_get_metadata_int32(mod, semantic->start_row); // Element packing start row
390 SV_params_nodes[9] = dxil_get_metadata_int8(mod, semantic->start_col); // Element packing start column
391 SV_params_nodes[10] = 0; // optional Metadata
392
393 return dxil_get_metadata_node(mod, SV_params_nodes, ARRAY_SIZE(SV_params_nodes));
394 }
395
396 static void
fill_signature_element(struct dxil_signature_element * elm,struct semantic_info * semantic,unsigned row)397 fill_signature_element(struct dxil_signature_element *elm,
398 struct semantic_info *semantic,
399 unsigned row)
400 {
401 memset(elm, 0, sizeof(struct dxil_signature_element));
402 // elm->stream = 0;
403 // elm->semantic_name_offset = 0; // Offset needs to be filled out when writing
404 elm->semantic_index = semantic->index + row;
405 elm->system_value = (uint32_t) prog_semantic_from_kind(semantic->kind);
406 elm->comp_type = (uint32_t) semantic->comp_type;
407 elm->reg = semantic->start_row + row;
408
409 assert(semantic->cols + semantic->start_col <= 4);
410 elm->mask = (uint8_t) (((1 << semantic->cols) - 1) << semantic->start_col);
411 // elm->never_writes_mask = 0;
412 elm->min_precision = DXIL_MIN_PREC_DEFAULT;
413 }
414
415 static bool
fill_psv_signature_element(struct dxil_psv_signature_element * psv_elm,struct semantic_info * semantic,struct dxil_module * mod)416 fill_psv_signature_element(struct dxil_psv_signature_element *psv_elm,
417 struct semantic_info *semantic, struct dxil_module *mod)
418 {
419 memset(psv_elm, 0, sizeof(struct dxil_psv_signature_element));
420 psv_elm->rows = semantic->rows;
421 if (semantic->start_row >= 0) {
422 assert(semantic->start_row < 256);
423 psv_elm->start_row = semantic->start_row;
424 psv_elm->cols_and_start = (1u << 6) | (semantic->start_col << 4) | semantic->cols;
425 } else {
426 /* The validation expects that the the start row is not egative
427 * and apparently the extra bit in the cols_and_start indicates that the
428 * row is meant literally, so don't set it in this case.
429 * (Source of information: Comparing with the validation structures
430 * created by dxcompiler)
431 */
432 psv_elm->start_row = 0;
433 psv_elm->cols_and_start = (semantic->start_col << 4) | semantic->cols;
434 }
435 psv_elm->semantic_kind = (uint8_t)semantic->kind;
436 psv_elm->component_type = semantic->comp_type; //`??
437 psv_elm->interpolation_mode = semantic->interpolation;
438 /* to be filled later
439 psv_elm->dynamic_mask_and_stream = 0;
440 */
441 if (semantic->kind == DXIL_SEM_ARBITRARY && strlen(semantic->name)) {
442 psv_elm->semantic_name_offset =
443 copy_semantic_name_to_string(mod->sem_string_table, semantic->name);
444
445 /* TODO: clean up memory */
446 if (psv_elm->semantic_name_offset == (uint32_t)-1)
447 return false;
448 }
449
450 psv_elm->semantic_indexes_offset =
451 append_semantic_index_to_table(&mod->sem_index_table, semantic->index, semantic->rows);
452
453 return true;
454 }
455
456 static bool
fill_io_signature(struct dxil_module * mod,int id,struct semantic_info * semantic,const struct dxil_mdnode ** io,struct dxil_signature_element * elm,struct dxil_psv_signature_element * psv_elm)457 fill_io_signature(struct dxil_module *mod, int id,
458 struct semantic_info *semantic,
459 const struct dxil_mdnode **io,
460 struct dxil_signature_element *elm,
461 struct dxil_psv_signature_element *psv_elm)
462 {
463
464 *io = fill_SV_param_nodes(mod, id, semantic);
465 for (unsigned i = 0; i < semantic->rows; ++i)
466 fill_signature_element(&elm[i], semantic, i);
467 return fill_psv_signature_element(psv_elm, semantic, mod);
468 }
469
470 static unsigned
get_input_signature_group(struct dxil_module * mod,const struct dxil_mdnode ** inputs,unsigned num_inputs,nir_shader * s,nir_variable_mode modes,semantic_info_proc get_semantics,unsigned * row_iter,bool is_gs_shader,bool vulkan)471 get_input_signature_group(struct dxil_module *mod, const struct dxil_mdnode **inputs,
472 unsigned num_inputs,
473 nir_shader *s, nir_variable_mode modes,
474 semantic_info_proc get_semantics, unsigned *row_iter,
475 bool is_gs_shader, bool vulkan)
476 {
477 nir_foreach_variable_with_modes(var, s, modes) {
478 struct semantic_info semantic = {0};
479 get_semantics(var, &semantic, vulkan);
480 mod->inputs[num_inputs].sysvalue = semantic.sysvalue_name;
481 *row_iter = get_additional_semantic_info(s, var, &semantic, *row_iter, is_gs_shader);
482
483 mod->inputs[num_inputs].name = ralloc_strdup(mod->ralloc_ctx,
484 semantic.name);
485 mod->inputs[num_inputs].num_elements = semantic.rows;
486 struct dxil_signature_element *elm = mod->inputs[num_inputs].elements;
487 struct dxil_psv_signature_element *psv_elm = &mod->psv_inputs[num_inputs];
488
489 if (!fill_io_signature(mod, num_inputs, &semantic,
490 &inputs[num_inputs], elm, psv_elm))
491 return 0;
492
493 mod->num_psv_inputs = MAX2(mod->num_psv_inputs,
494 semantic.start_row + semantic.rows);
495
496 mod->info.has_per_sample_input |=
497 semantic.kind == DXIL_SEM_SAMPLE_INDEX ||
498 semantic.interpolation == DXIL_INTERP_LINEAR_SAMPLE ||
499 semantic.interpolation == DXIL_INTERP_LINEAR_NOPERSPECTIVE_SAMPLE;
500
501 ++num_inputs;
502 assert(num_inputs < VARYING_SLOT_MAX);
503 }
504 return num_inputs;
505 }
506
507 static const struct dxil_mdnode *
get_input_signature(struct dxil_module * mod,nir_shader * s,bool vulkan)508 get_input_signature(struct dxil_module *mod, nir_shader *s, bool vulkan)
509 {
510 if (s->info.stage == MESA_SHADER_KERNEL)
511 return NULL;
512
513 const struct dxil_mdnode *inputs[VARYING_SLOT_MAX];
514 unsigned next_row = 0;
515 bool is_gs_shader = s->info.stage == MESA_SHADER_GEOMETRY;
516
517 mod->num_sig_inputs = get_input_signature_group(mod, inputs, 0,
518 s, nir_var_shader_in,
519 s->info.stage == MESA_SHADER_VERTEX ?
520 get_semantic_vs_in_name :
521 (s->info.stage == MESA_SHADER_GEOMETRY ?
522 get_semantic_gs_in_name : get_semantic_in_name),
523 &next_row, is_gs_shader,
524 vulkan);
525
526 mod->num_sig_inputs = get_input_signature_group(mod, inputs, mod->num_sig_inputs,
527 s, nir_var_system_value,
528 get_semantic_sv_name,
529 &next_row, is_gs_shader,
530 vulkan);
531
532 if (!mod->num_sig_inputs && !mod->num_sig_inputs)
533 return NULL;
534
535 const struct dxil_mdnode *retval = mod->num_sig_inputs ?
536 dxil_get_metadata_node(mod, inputs, mod->num_sig_inputs) : NULL;
537
538 return retval;
539 }
540
out_sysvalue_name(nir_variable * var)541 static const char *out_sysvalue_name(nir_variable *var)
542 {
543 switch (var->data.location) {
544 case VARYING_SLOT_FACE:
545 return "FACE";
546 case VARYING_SLOT_POS:
547 return "POS";
548 case VARYING_SLOT_CLIP_DIST0:
549 case VARYING_SLOT_CLIP_DIST1:
550 return "CLIPDST";
551 case VARYING_SLOT_PRIMITIVE_ID:
552 return "PRIMID";
553 default:
554 return "NO";
555 }
556 }
557
558 static const struct dxil_mdnode *
get_output_signature(struct dxil_module * mod,nir_shader * s,bool vulkan)559 get_output_signature(struct dxil_module *mod, nir_shader *s, bool vulkan)
560 {
561 const struct dxil_mdnode *outputs[VARYING_SLOT_MAX];
562 unsigned num_outputs = 0;
563 unsigned next_row = 0;
564 nir_foreach_variable_with_modes(var, s, nir_var_shader_out) {
565 struct semantic_info semantic = {0};
566
567 if (s->info.stage == MESA_SHADER_FRAGMENT) {
568 get_semantic_ps_outname(var, &semantic);
569 mod->outputs[num_outputs].sysvalue = "TARGET";
570 } else {
571 get_semantic_name(var, &semantic, var->type, vulkan);
572 mod->outputs[num_outputs].sysvalue = out_sysvalue_name(var);
573 }
574 next_row = get_additional_semantic_info(s, var, &semantic, next_row, false);
575
576 mod->info.has_out_position |= semantic.kind== DXIL_SEM_POSITION;
577 mod->info.has_out_depth |= semantic.kind == DXIL_SEM_DEPTH;
578
579 mod->outputs[num_outputs].name = ralloc_strdup(mod->ralloc_ctx,
580 semantic.name);
581 mod->outputs[num_outputs].num_elements = semantic.rows;
582 struct dxil_signature_element *elm = mod->outputs[num_outputs].elements;
583
584 struct dxil_psv_signature_element *psv_elm = &mod->psv_outputs[num_outputs];
585
586 if (!fill_io_signature(mod, num_outputs, &semantic,
587 &outputs[num_outputs], elm, psv_elm))
588 return NULL;
589
590 /* This is fishy, logic suggests that the LHS should be 0xf, but from the
591 * validation it needs to be 0xff */
592 elm->never_writes_mask = 0xff & ~elm->mask;
593
594 ++num_outputs;
595
596 mod->num_psv_outputs = MAX2(mod->num_psv_outputs,
597 semantic.start_row + semantic.rows);
598
599 assert(num_outputs < ARRAY_SIZE(outputs));
600 }
601
602 if (!num_outputs)
603 return NULL;
604
605 const struct dxil_mdnode *retval = dxil_get_metadata_node(mod, outputs, num_outputs);
606 mod->num_sig_outputs = num_outputs;
607 return retval;
608 }
609
610 const struct dxil_mdnode *
get_signatures(struct dxil_module * mod,nir_shader * s,bool vulkan)611 get_signatures(struct dxil_module *mod, nir_shader *s, bool vulkan)
612 {
613 /* DXC does the same: Add an empty string before everything else */
614 mod->sem_string_table = _mesa_string_buffer_create(mod->ralloc_ctx, 1024);
615 copy_semantic_name_to_string(mod->sem_string_table, "");
616
617 const struct dxil_mdnode *input_signature = get_input_signature(mod, s, vulkan);
618 const struct dxil_mdnode *output_signature = get_output_signature(mod, s, vulkan);
619
620 const struct dxil_mdnode *SV_nodes[3] = {
621 input_signature,
622 output_signature,
623 NULL
624 };
625 if (output_signature || input_signature)
626 return dxil_get_metadata_node(mod, SV_nodes, ARRAY_SIZE(SV_nodes));
627 else
628 return NULL;
629 }
630