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