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