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