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 35struct semantic_info { 36 enum dxil_semantic_kind kind; 37 char name[64]; 38 int index; 39 enum dxil_prog_sig_comp_type comp_type; 40 uint8_t sig_comp_type; 41 int32_t start_row; 42 int32_t rows; 43 uint8_t start_col; 44 uint8_t cols; 45 uint8_t interpolation; 46 const char *sysvalue_name; 47}; 48 49 50static bool 51is_depth_output(enum dxil_semantic_kind kind) 52{ 53 return kind == DXIL_SEM_DEPTH || kind == DXIL_SEM_DEPTH_GE || 54 kind == DXIL_SEM_DEPTH_LE || kind == DXIL_SEM_STENCIL_REF; 55} 56 57static uint8_t 58get_interpolation(nir_variable *var) 59{ 60 if (unlikely(var->data.centroid)) { 61 switch (var->data.interpolation) { 62 case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR_CENTROID; 63 case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT; 64 case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE_CENTROID; 65 case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR_CENTROID; 66 67 } 68 } else { 69 switch (var->data.interpolation) { 70 case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR; 71 case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT; 72 case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE; 73 case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR; 74 } 75 } 76 77 return DXIL_INTERP_LINEAR; 78} 79 80static const char * 81in_sysvalue_name(nir_variable *var) 82{ 83 switch (var->data.location) { 84 case VARYING_SLOT_POS: 85 return "POS"; 86 case VARYING_SLOT_FACE: 87 return "FACE"; 88 default: 89 return "NONE"; 90 } 91} 92 93/* 94 * The signatures are written into the stream in two pieces: 95 * DxilProgramSignatureElement is a fixes size structure that gets dumped 96 * to the stream in order of the registers and each contains an offset 97 * to the semantic name string. Then these strings are dumped into the stream. 98 */ 99static unsigned 100get_additional_semantic_info(nir_shader *s, nir_variable *var, struct semantic_info *info, 101 unsigned next_row, bool is_gs_shader) 102{ 103 const struct glsl_type *type = var->type; 104 105 info->comp_type = 106 dxil_get_prog_sig_comp_type(var->type); 107 108 bool is_depth = is_depth_output(info->kind); 109 info->sig_comp_type = dxil_get_comp_type(var->type); 110 111 info->rows = 1; 112 if (info->kind == DXIL_SEM_TARGET) { 113 info->start_row = info->index; 114 } else if (is_depth || 115 (info->kind == DXIL_SEM_PRIMITIVE_ID && is_gs_shader) || 116 info->kind == DXIL_SEM_COVERAGE || 117 info->kind == DXIL_SEM_SAMPLE_INDEX) { 118 // This turns into a 'N/A' mask in the disassembly 119 info->start_row = -1; 120 } else if (var->data.compact) { 121 if (var->data.location_frac) { 122 info->start_row = next_row - 1; 123 } else { 124 info->start_row = next_row; 125 next_row++; 126 } 127 128 assert(glsl_type_is_array(type) && info->kind == DXIL_SEM_CLIP_DISTANCE); 129 unsigned num_floats = glsl_get_aoa_size(type); 130 unsigned start_offset = (var->data.location - VARYING_SLOT_CLIP_DIST0) * 4 + 131 var->data.location_frac; 132 133 if (start_offset >= s->info.clip_distance_array_size) { 134 info->kind = DXIL_SEM_CULL_DISTANCE; 135 snprintf(info->name, 64, "SV_CullDistance"); 136 } 137 info->cols = num_floats; 138 } else { 139 info->start_row = next_row; 140 if (glsl_type_is_array(type) && is_gs_shader) 141 type = glsl_without_array(type); 142 143 if (glsl_type_is_array(type)) { 144 info->rows = glsl_get_aoa_size(type); 145 type = glsl_get_array_element(type); 146 assert(info->rows); 147 } 148 next_row += info->rows; 149 } 150 info->start_col = (uint8_t)var->data.location_frac; 151 if (!info->cols) { 152 if (glsl_type_is_array(type)) 153 type = glsl_get_array_element(type); 154 info->cols = (uint8_t)glsl_get_components(type); 155 } 156 157 return next_row; 158} 159 160typedef void (*semantic_info_proc)(nir_variable *var, struct semantic_info *info, bool vulkan); 161 162static void 163get_semantic_vs_in_name(nir_variable *var, struct semantic_info *info, bool vulkan) 164{ 165 strcpy(info->name, "TEXCOORD"); 166 if (vulkan) { 167 info->index = var->data.location >= VERT_ATTRIB_GENERIC0 ? 168 var->data.location - VERT_ATTRIB_GENERIC0 : 169 var->data.location; 170 } else { 171 info->index = var->data.driver_location; 172 } 173 info->kind = DXIL_SEM_ARBITRARY; 174} 175 176static void 177get_semantic_sv_name(nir_variable *var, struct semantic_info *info, bool _vulkan) 178{ 179 switch (var->data.location) { 180 case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE: 181 info->kind = DXIL_SEM_VERTEX_ID; 182 break; 183 case SYSTEM_VALUE_FRONT_FACE: 184 info->kind = DXIL_SEM_IS_FRONT_FACE; 185 break; 186 case SYSTEM_VALUE_INSTANCE_ID: 187 info->kind = DXIL_SEM_INSTANCE_ID; 188 break; 189 case SYSTEM_VALUE_PRIMITIVE_ID: 190 info->kind = DXIL_SEM_PRIMITIVE_ID; 191 break; 192 case SYSTEM_VALUE_SAMPLE_ID: 193 info->kind = DXIL_SEM_SAMPLE_INDEX; 194 info->interpolation = get_interpolation(var); 195 break; 196 default: 197 unreachable("unsupported system value"); 198 } 199 strncpy(info->name, var->name, ARRAY_SIZE(info->name) - 1); 200} 201 202static void 203get_semantic_ps_outname(nir_variable *var, struct semantic_info *info) 204{ 205 info->kind = DXIL_SEM_INVALID; 206 switch (var->data.location) { 207 case FRAG_RESULT_COLOR: 208 snprintf(info->name, 64, "%s", "SV_Target"); 209 info->index = var->data.index; 210 info->kind = DXIL_SEM_TARGET; 211 break; 212 case FRAG_RESULT_DATA0: 213 case FRAG_RESULT_DATA1: 214 case FRAG_RESULT_DATA2: 215 case FRAG_RESULT_DATA3: 216 case FRAG_RESULT_DATA4: 217 case FRAG_RESULT_DATA5: 218 case FRAG_RESULT_DATA6: 219 case FRAG_RESULT_DATA7: 220 snprintf(info->name, 64, "%s", "SV_Target"); 221 info->index = var->data.location - FRAG_RESULT_DATA0; 222 if (var->data.location == FRAG_RESULT_DATA0 && 223 var->data.index > 0) 224 info->index = var->data.index; 225 info->kind = DXIL_SEM_TARGET; 226 break; 227 case FRAG_RESULT_DEPTH: 228 snprintf(info->name, 64, "%s", "SV_Depth"); 229 info->kind = DXIL_SEM_DEPTH; 230 break; 231 case FRAG_RESULT_STENCIL: 232 snprintf(info->name, 64, "%s", "SV_StencilRef"); 233 info->kind = DXIL_SEM_STENCIL_REF; //?? 234 break; 235 case FRAG_RESULT_SAMPLE_MASK: 236 snprintf(info->name, 64, "%s", "SV_Coverage"); 237 info->kind = DXIL_SEM_COVERAGE; //?? 238 break; 239 default: 240 snprintf(info->name, 64, "%s", "UNDEFINED"); 241 break; 242 } 243} 244 245static void 246get_semantic_name(nir_variable *var, struct semantic_info *info, 247 const struct glsl_type *type, bool vulkan) 248{ 249 info->kind = DXIL_SEM_INVALID; 250 info->interpolation = get_interpolation(var); 251 switch (var->data.location) { 252 253 case VARYING_SLOT_POS: 254 assert(glsl_get_components(type) == 4); 255 snprintf(info->name, 64, "%s", "SV_Position"); 256 info->kind = DXIL_SEM_POSITION; 257 break; 258 259 case VARYING_SLOT_FACE: 260 assert(glsl_get_components(var->type) == 1); 261 snprintf(info->name, 64, "%s", "SV_IsFrontFace"); 262 info->kind = DXIL_SEM_IS_FRONT_FACE; 263 break; 264 265 case VARYING_SLOT_PRIMITIVE_ID: 266 assert(glsl_get_components(var->type) == 1); 267 snprintf(info->name, 64, "%s", "SV_PrimitiveID"); 268 info->kind = DXIL_SEM_PRIMITIVE_ID; 269 break; 270 271 case VARYING_SLOT_CLIP_DIST1: 272 info->index = 1; 273 FALLTHROUGH; 274 case VARYING_SLOT_CLIP_DIST0: 275 assert(var->data.location == VARYING_SLOT_CLIP_DIST1 || info->index == 0); 276 snprintf(info->name, 64, "%s", "SV_ClipDistance"); 277 info->kind = DXIL_SEM_CLIP_DISTANCE; 278 break; 279 280 default: { 281 info->index = var->data.location - 282 (vulkan ? VARYING_SLOT_VAR0 : VARYING_SLOT_POS); 283 strcpy(info->name, "TEXCOORD"); 284 info->kind = DXIL_SEM_ARBITRARY; 285 } 286 } 287} 288 289static void 290get_semantic_in_name(nir_variable *var, struct semantic_info *info, bool vulkan) 291{ 292 get_semantic_name(var, info, var->type, vulkan); 293 info->sysvalue_name = in_sysvalue_name(var); 294} 295 296static void 297get_semantic_gs_in_name(nir_variable *var, struct semantic_info *info, bool vulkan) 298{ 299 /* geometry shader input varyings come as arrays, but we want to use 300 * the element type */ 301 const struct glsl_type *type = 302 glsl_type_is_array(var->type) ? glsl_without_array(var->type) : var->type; 303 304 get_semantic_name(var, info, type, vulkan); 305 info->sysvalue_name = in_sysvalue_name(var); 306} 307 308 309static enum dxil_prog_sig_semantic 310prog_semantic_from_kind(enum dxil_semantic_kind kind) 311{ 312 switch (kind) { 313 case DXIL_SEM_ARBITRARY: return DXIL_PROG_SEM_UNDEFINED; 314 case DXIL_SEM_VERTEX_ID: return DXIL_PROG_SEM_VERTEX_ID; 315 case DXIL_SEM_INSTANCE_ID: return DXIL_PROG_SEM_INSTANCE_ID; 316 case DXIL_SEM_POSITION: return DXIL_PROG_SEM_POSITION; 317 case DXIL_SEM_COVERAGE: return DXIL_PROG_SEM_COVERAGE; 318 case DXIL_SEM_INNER_COVERAGE: return DXIL_PROG_SEM_INNER_COVERAGE; 319 case DXIL_SEM_PRIMITIVE_ID: return DXIL_PROG_SEM_PRIMITIVE_ID; 320 case DXIL_SEM_SAMPLE_INDEX: return DXIL_PROG_SEM_SAMPLE_INDEX; 321 case DXIL_SEM_IS_FRONT_FACE: return DXIL_PROG_SEM_IS_FRONTFACE; 322 case DXIL_SEM_RENDERTARGET_ARRAY_INDEX: return DXIL_PROG_SEM_RENDERTARGET_ARRAY_INDEX; 323 case DXIL_SEM_VIEWPORT_ARRAY_INDEX: return DXIL_PROG_SEM_VIEWPORT_ARRAY_INDEX; 324 case DXIL_SEM_CLIP_DISTANCE: return DXIL_PROG_SEM_CLIP_DISTANCE; 325 case DXIL_SEM_CULL_DISTANCE: return DXIL_PROG_SEM_CULL_DISTANCE; 326 case DXIL_SEM_BARYCENTRICS: return DXIL_PROG_SEM_BARYCENTRICS; 327 case DXIL_SEM_SHADING_RATE: return DXIL_PROG_SEM_SHADING_RATE; 328 case DXIL_SEM_CULL_PRIMITIVE: return DXIL_PROG_SEM_CULL_PRIMITIVE; 329 case DXIL_SEM_TARGET: return DXIL_PROG_SEM_TARGET; 330 case DXIL_SEM_DEPTH: return DXIL_PROG_SEM_DEPTH; 331 case DXIL_SEM_DEPTH_LE: return DXIL_PROG_SEM_DEPTH_LE; 332 case DXIL_SEM_DEPTH_GE: return DXIL_PROG_SEM_DEPTH_GE; 333 case DXIL_SEM_STENCIL_REF: return DXIL_PROG_SEM_STENCIL_REF; 334 default: 335 return DXIL_PROG_SEM_UNDEFINED; 336 } 337} 338 339static 340uint32_t 341copy_semantic_name_to_string(struct _mesa_string_buffer *string_out, const char *name) 342{ 343 /* copy the semantic name */ 344 uint32_t retval = string_out->length; 345 size_t name_len = strlen(name) + 1; 346 _mesa_string_buffer_append_len(string_out, name, name_len); 347 return retval; 348} 349 350static 351uint32_t 352append_semantic_index_to_table(struct dxil_psv_sem_index_table *table, uint32_t index, 353 uint32_t num_rows) 354{ 355 if (num_rows == 1) { 356 for (unsigned i = 0; i < table->size; ++i) { 357 if (table->data[i] == index) 358 return i; 359 } 360 } 361 uint32_t retval = table->size; 362 assert(table->size + num_rows <= 80); 363 for (unsigned i = 0; i < num_rows; ++i) 364 table->data[table->size++] = index + i; 365 return retval; 366} 367 368static const struct dxil_mdnode * 369fill_SV_param_nodes(struct dxil_module *mod, unsigned record_id, 370 struct semantic_info *semantic) { 371 372 const struct dxil_mdnode *SV_params_nodes[11]; 373 /* For this to always work we should use vectorize_io, but for FS out and VS in 374 * this is not implemented globally */ 375 const struct dxil_mdnode *flattened_semantics[256]; 376 377 for (unsigned i = 0; i < semantic->rows; ++i) 378 flattened_semantics[i] = dxil_get_metadata_int32(mod, semantic->index + i); 379 380 SV_params_nodes[0] = dxil_get_metadata_int32(mod, (int)record_id); // Unique element ID 381 SV_params_nodes[1] = dxil_get_metadata_string(mod, semantic->name); // Element name 382 SV_params_nodes[2] = dxil_get_metadata_int8(mod, semantic->sig_comp_type); // Element type 383 SV_params_nodes[3] = dxil_get_metadata_int8(mod, (int8_t)semantic->kind); // Effective system value 384 SV_params_nodes[4] = dxil_get_metadata_node(mod, flattened_semantics, 385 semantic->rows); // Semantic index vector 386 SV_params_nodes[5] = dxil_get_metadata_int8(mod, semantic->interpolation); // Interpolation mode 387 SV_params_nodes[6] = dxil_get_metadata_int32(mod, semantic->rows); // Number of rows 388 SV_params_nodes[7] = dxil_get_metadata_int8(mod, semantic->cols); // Number of columns 389 SV_params_nodes[8] = dxil_get_metadata_int32(mod, semantic->start_row); // Element packing start row 390 SV_params_nodes[9] = dxil_get_metadata_int8(mod, semantic->start_col); // Element packing start column 391 SV_params_nodes[10] = 0; // optional Metadata 392 393 return dxil_get_metadata_node(mod, SV_params_nodes, ARRAY_SIZE(SV_params_nodes)); 394} 395 396static void 397fill_signature_element(struct dxil_signature_element *elm, 398 struct semantic_info *semantic, 399 unsigned row) 400{ 401 memset(elm, 0, sizeof(struct dxil_signature_element)); 402 // elm->stream = 0; 403 // elm->semantic_name_offset = 0; // Offset needs to be filled out when writing 404 elm->semantic_index = semantic->index + row; 405 elm->system_value = (uint32_t) prog_semantic_from_kind(semantic->kind); 406 elm->comp_type = (uint32_t) semantic->comp_type; 407 elm->reg = semantic->start_row + row; 408 409 assert(semantic->cols + semantic->start_col <= 4); 410 elm->mask = (uint8_t) (((1 << semantic->cols) - 1) << semantic->start_col); 411 // elm->never_writes_mask = 0; 412 elm->min_precision = DXIL_MIN_PREC_DEFAULT; 413} 414 415static bool 416fill_psv_signature_element(struct dxil_psv_signature_element *psv_elm, 417 struct semantic_info *semantic, struct dxil_module *mod) 418{ 419 memset(psv_elm, 0, sizeof(struct dxil_psv_signature_element)); 420 psv_elm->rows = semantic->rows; 421 if (semantic->start_row >= 0) { 422 assert(semantic->start_row < 256); 423 psv_elm->start_row = semantic->start_row; 424 psv_elm->cols_and_start = (1u << 6) | (semantic->start_col << 4) | semantic->cols; 425 } else { 426 /* The validation expects that the the start row is not egative 427 * and apparently the extra bit in the cols_and_start indicates that the 428 * row is meant literally, so don't set it in this case. 429 * (Source of information: Comparing with the validation structures 430 * created by dxcompiler) 431 */ 432 psv_elm->start_row = 0; 433 psv_elm->cols_and_start = (semantic->start_col << 4) | semantic->cols; 434 } 435 psv_elm->semantic_kind = (uint8_t)semantic->kind; 436 psv_elm->component_type = semantic->comp_type; //`?? 437 psv_elm->interpolation_mode = semantic->interpolation; 438 /* to be filled later 439 psv_elm->dynamic_mask_and_stream = 0; 440 */ 441 if (semantic->kind == DXIL_SEM_ARBITRARY && strlen(semantic->name)) { 442 psv_elm->semantic_name_offset = 443 copy_semantic_name_to_string(mod->sem_string_table, semantic->name); 444 445 /* TODO: clean up memory */ 446 if (psv_elm->semantic_name_offset == (uint32_t)-1) 447 return false; 448 } 449 450 psv_elm->semantic_indexes_offset = 451 append_semantic_index_to_table(&mod->sem_index_table, semantic->index, semantic->rows); 452 453 return true; 454} 455 456static bool 457fill_io_signature(struct dxil_module *mod, int id, 458 struct semantic_info *semantic, 459 const struct dxil_mdnode **io, 460 struct dxil_signature_element *elm, 461 struct dxil_psv_signature_element *psv_elm) 462{ 463 464 *io = fill_SV_param_nodes(mod, id, semantic); 465 for (unsigned i = 0; i < semantic->rows; ++i) 466 fill_signature_element(&elm[i], semantic, i); 467 return fill_psv_signature_element(psv_elm, semantic, mod); 468} 469 470static unsigned 471get_input_signature_group(struct dxil_module *mod, const struct dxil_mdnode **inputs, 472 unsigned num_inputs, 473 nir_shader *s, nir_variable_mode modes, 474 semantic_info_proc get_semantics, unsigned *row_iter, 475 bool is_gs_shader, bool vulkan) 476{ 477 nir_foreach_variable_with_modes(var, s, modes) { 478 struct semantic_info semantic = {0}; 479 get_semantics(var, &semantic, vulkan); 480 mod->inputs[num_inputs].sysvalue = semantic.sysvalue_name; 481 *row_iter = get_additional_semantic_info(s, var, &semantic, *row_iter, is_gs_shader); 482 483 mod->inputs[num_inputs].name = ralloc_strdup(mod->ralloc_ctx, 484 semantic.name); 485 mod->inputs[num_inputs].num_elements = semantic.rows; 486 struct dxil_signature_element *elm = mod->inputs[num_inputs].elements; 487 struct dxil_psv_signature_element *psv_elm = &mod->psv_inputs[num_inputs]; 488 489 if (!fill_io_signature(mod, num_inputs, &semantic, 490 &inputs[num_inputs], elm, psv_elm)) 491 return 0; 492 493 mod->num_psv_inputs = MAX2(mod->num_psv_inputs, 494 semantic.start_row + semantic.rows); 495 496 mod->info.has_per_sample_input |= 497 semantic.kind == DXIL_SEM_SAMPLE_INDEX || 498 semantic.interpolation == DXIL_INTERP_LINEAR_SAMPLE || 499 semantic.interpolation == DXIL_INTERP_LINEAR_NOPERSPECTIVE_SAMPLE; 500 501 ++num_inputs; 502 assert(num_inputs < VARYING_SLOT_MAX); 503 } 504 return num_inputs; 505} 506 507static const struct dxil_mdnode * 508get_input_signature(struct dxil_module *mod, nir_shader *s, bool vulkan) 509{ 510 if (s->info.stage == MESA_SHADER_KERNEL) 511 return NULL; 512 513 const struct dxil_mdnode *inputs[VARYING_SLOT_MAX]; 514 unsigned next_row = 0; 515 bool is_gs_shader = s->info.stage == MESA_SHADER_GEOMETRY; 516 517 mod->num_sig_inputs = get_input_signature_group(mod, inputs, 0, 518 s, nir_var_shader_in, 519 s->info.stage == MESA_SHADER_VERTEX ? 520 get_semantic_vs_in_name : 521 (s->info.stage == MESA_SHADER_GEOMETRY ? 522 get_semantic_gs_in_name : get_semantic_in_name), 523 &next_row, is_gs_shader, 524 vulkan); 525 526 mod->num_sig_inputs = get_input_signature_group(mod, inputs, mod->num_sig_inputs, 527 s, nir_var_system_value, 528 get_semantic_sv_name, 529 &next_row, is_gs_shader, 530 vulkan); 531 532 if (!mod->num_sig_inputs && !mod->num_sig_inputs) 533 return NULL; 534 535 const struct dxil_mdnode *retval = mod->num_sig_inputs ? 536 dxil_get_metadata_node(mod, inputs, mod->num_sig_inputs) : NULL; 537 538 return retval; 539} 540 541static const char *out_sysvalue_name(nir_variable *var) 542{ 543 switch (var->data.location) { 544 case VARYING_SLOT_FACE: 545 return "FACE"; 546 case VARYING_SLOT_POS: 547 return "POS"; 548 case VARYING_SLOT_CLIP_DIST0: 549 case VARYING_SLOT_CLIP_DIST1: 550 return "CLIPDST"; 551 case VARYING_SLOT_PRIMITIVE_ID: 552 return "PRIMID"; 553 default: 554 return "NO"; 555 } 556} 557 558static const struct dxil_mdnode * 559get_output_signature(struct dxil_module *mod, nir_shader *s, bool vulkan) 560{ 561 const struct dxil_mdnode *outputs[VARYING_SLOT_MAX]; 562 unsigned num_outputs = 0; 563 unsigned next_row = 0; 564 nir_foreach_variable_with_modes(var, s, nir_var_shader_out) { 565 struct semantic_info semantic = {0}; 566 567 if (s->info.stage == MESA_SHADER_FRAGMENT) { 568 get_semantic_ps_outname(var, &semantic); 569 mod->outputs[num_outputs].sysvalue = "TARGET"; 570 } else { 571 get_semantic_name(var, &semantic, var->type, vulkan); 572 mod->outputs[num_outputs].sysvalue = out_sysvalue_name(var); 573 } 574 next_row = get_additional_semantic_info(s, var, &semantic, next_row, false); 575 576 mod->info.has_out_position |= semantic.kind== DXIL_SEM_POSITION; 577 mod->info.has_out_depth |= semantic.kind == DXIL_SEM_DEPTH; 578 579 mod->outputs[num_outputs].name = ralloc_strdup(mod->ralloc_ctx, 580 semantic.name); 581 mod->outputs[num_outputs].num_elements = semantic.rows; 582 struct dxil_signature_element *elm = mod->outputs[num_outputs].elements; 583 584 struct dxil_psv_signature_element *psv_elm = &mod->psv_outputs[num_outputs]; 585 586 if (!fill_io_signature(mod, num_outputs, &semantic, 587 &outputs[num_outputs], elm, psv_elm)) 588 return NULL; 589 590 /* This is fishy, logic suggests that the LHS should be 0xf, but from the 591 * validation it needs to be 0xff */ 592 elm->never_writes_mask = 0xff & ~elm->mask; 593 594 ++num_outputs; 595 596 mod->num_psv_outputs = MAX2(mod->num_psv_outputs, 597 semantic.start_row + semantic.rows); 598 599 assert(num_outputs < ARRAY_SIZE(outputs)); 600 } 601 602 if (!num_outputs) 603 return NULL; 604 605 const struct dxil_mdnode *retval = dxil_get_metadata_node(mod, outputs, num_outputs); 606 mod->num_sig_outputs = num_outputs; 607 return retval; 608} 609 610const struct dxil_mdnode * 611get_signatures(struct dxil_module *mod, nir_shader *s, bool vulkan) 612{ 613 /* DXC does the same: Add an empty string before everything else */ 614 mod->sem_string_table = _mesa_string_buffer_create(mod->ralloc_ctx, 1024); 615 copy_semantic_name_to_string(mod->sem_string_table, ""); 616 617 const struct dxil_mdnode *input_signature = get_input_signature(mod, s, vulkan); 618 const struct dxil_mdnode *output_signature = get_output_signature(mod, s, vulkan); 619 620 const struct dxil_mdnode *SV_nodes[3] = { 621 input_signature, 622 output_signature, 623 NULL 624 }; 625 if (output_signature || input_signature) 626 return dxil_get_metadata_node(mod, SV_nodes, ARRAY_SIZE(SV_nodes)); 627 else 628 return NULL; 629} 630