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