• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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