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