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 "d3d12_compiler.h" 25#include "d3d12_context.h" 26#include "d3d12_debug.h" 27#include "d3d12_screen.h" 28#include "d3d12_nir_passes.h" 29#include "nir_to_dxil.h" 30#include "dxil_nir.h" 31 32#include "pipe/p_state.h" 33 34#include "nir.h" 35#include "nir/nir_draw_helpers.h" 36#include "nir/tgsi_to_nir.h" 37#include "compiler/nir/nir_builder.h" 38#include "tgsi/tgsi_from_mesa.h" 39#include "tgsi/tgsi_ureg.h" 40 41#include "util/u_memory.h" 42#include "util/u_prim.h" 43#include "util/u_simple_shaders.h" 44#include "util/u_dl.h" 45 46#include <directx/d3d12.h> 47#include <dxguids/dxguids.h> 48 49#include <dxcapi.h> 50#include <wrl/client.h> 51 52extern "C" { 53#include "tgsi/tgsi_parse.h" 54#include "tgsi/tgsi_point_sprite.h" 55} 56 57using Microsoft::WRL::ComPtr; 58 59struct d3d12_validation_tools 60{ 61 d3d12_validation_tools(); 62 63 bool validate_and_sign(struct blob *dxil); 64 65 void disassemble(struct blob *dxil); 66 67 void load_dxil_dll(); 68 69 struct HModule { 70 HModule(); 71 ~HModule(); 72 73 bool load(LPCSTR file_name); 74 operator util_dl_library *() const; 75 private: 76 util_dl_library *module; 77 }; 78 79 HModule dxil_module; 80 HModule dxc_compiler_module; 81 ComPtr<IDxcCompiler> compiler; 82 ComPtr<IDxcValidator> validator; 83 ComPtr<IDxcLibrary> library; 84}; 85 86struct d3d12_validation_tools *d3d12_validator_create() 87{ 88 d3d12_validation_tools *tools = new d3d12_validation_tools(); 89 if (tools->validator) 90 return tools; 91 delete tools; 92 return nullptr; 93} 94 95void d3d12_validator_destroy(struct d3d12_validation_tools *validator) 96{ 97 delete validator; 98} 99 100 101const void * 102d3d12_get_compiler_options(struct pipe_screen *screen, 103 enum pipe_shader_ir ir, 104 enum pipe_shader_type shader) 105{ 106 assert(ir == PIPE_SHADER_IR_NIR); 107 return dxil_get_nir_compiler_options(); 108} 109 110static uint32_t 111resource_dimension(enum glsl_sampler_dim dim) 112{ 113 switch (dim) { 114 case GLSL_SAMPLER_DIM_1D: 115 return RESOURCE_DIMENSION_TEXTURE1D; 116 case GLSL_SAMPLER_DIM_2D: 117 return RESOURCE_DIMENSION_TEXTURE2D; 118 case GLSL_SAMPLER_DIM_3D: 119 return RESOURCE_DIMENSION_TEXTURE3D; 120 case GLSL_SAMPLER_DIM_CUBE: 121 return RESOURCE_DIMENSION_TEXTURECUBE; 122 default: 123 return RESOURCE_DIMENSION_UNKNOWN; 124 } 125} 126 127static struct d3d12_shader * 128compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel, 129 struct d3d12_shader_key *key, struct nir_shader *nir) 130{ 131 struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 132 struct d3d12_shader *shader = rzalloc(sel, d3d12_shader); 133 shader->key = *key; 134 shader->nir = nir; 135 sel->current = shader; 136 137 NIR_PASS_V(nir, nir_lower_samplers); 138 NIR_PASS_V(nir, dxil_nir_create_bare_samplers); 139 140 if (key->samples_int_textures) 141 NIR_PASS_V(nir, dxil_lower_sample_to_txf_for_integer_tex, 142 key->tex_wrap_states, key->swizzle_state, 143 screen->base.get_paramf(&screen->base, PIPE_CAPF_MAX_TEXTURE_LOD_BIAS)); 144 145 if (key->vs.needs_format_emulation) 146 d3d12_nir_lower_vs_vertex_conversion(nir, key->vs.format_conversion); 147 148 uint32_t num_ubos_before_lower_to_ubo = nir->info.num_ubos; 149 uint32_t num_uniforms_before_lower_to_ubo = nir->num_uniforms; 150 NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, false, false); 151 shader->has_default_ubo0 = num_uniforms_before_lower_to_ubo > 0 && 152 nir->info.num_ubos > num_ubos_before_lower_to_ubo; 153 154 if (key->last_vertex_processing_stage) { 155 if (key->invert_depth) 156 NIR_PASS_V(nir, d3d12_nir_invert_depth); 157 NIR_PASS_V(nir, nir_lower_clip_halfz); 158 NIR_PASS_V(nir, d3d12_lower_yflip); 159 } 160 NIR_PASS_V(nir, nir_lower_packed_ubo_loads); 161 NIR_PASS_V(nir, d3d12_lower_load_first_vertex); 162 NIR_PASS_V(nir, d3d12_lower_state_vars, shader); 163 NIR_PASS_V(nir, dxil_nir_lower_bool_input); 164 165 struct nir_to_dxil_options opts = {}; 166 opts.interpolate_at_vertex = screen->have_load_at_vertex; 167 opts.lower_int16 = !screen->opts4.Native16BitShaderOpsSupported; 168 opts.ubo_binding_offset = shader->has_default_ubo0 ? 0 : 1; 169 opts.provoking_vertex = key->fs.provoking_vertex; 170 171 struct blob tmp; 172 if (!nir_to_dxil(nir, &opts, &tmp)) { 173 debug_printf("D3D12: nir_to_dxil failed\n"); 174 return NULL; 175 } 176 177 // Non-ubo variables 178 shader->begin_srv_binding = (UINT_MAX); 179 nir_foreach_variable_with_modes(var, nir, nir_var_uniform) { 180 auto type = glsl_without_array(var->type); 181 if (glsl_type_is_sampler(type) && glsl_get_sampler_result_type(type) != GLSL_TYPE_VOID) { 182 unsigned count = glsl_type_is_array(var->type) ? glsl_get_aoa_size(var->type) : 1; 183 for (unsigned i = 0; i < count; ++i) { 184 shader->srv_bindings[var->data.binding + i].binding = var->data.binding; 185 shader->srv_bindings[var->data.binding + i].dimension = resource_dimension(glsl_get_sampler_dim(type)); 186 } 187 shader->begin_srv_binding = MIN2(var->data.binding, shader->begin_srv_binding); 188 shader->end_srv_binding = MAX2(var->data.binding + count, shader->end_srv_binding); 189 } 190 } 191 192 // Ubo variables 193 if(nir->info.num_ubos) { 194 // Ignore state_vars ubo as it is bound as root constants 195 unsigned num_ubo_bindings = nir->info.num_ubos - (shader->state_vars_used ? 1 : 0); 196 for(unsigned i = opts.ubo_binding_offset; i < num_ubo_bindings; ++i) { 197 shader->cb_bindings[shader->num_cb_bindings++].binding = i; 198 } 199 } 200 if (ctx->validation_tools) { 201 ctx->validation_tools->validate_and_sign(&tmp); 202 203 if (d3d12_debug & D3D12_DEBUG_DISASS) { 204 ctx->validation_tools->disassemble(&tmp); 205 } 206 } 207 208 blob_finish_get_buffer(&tmp, &shader->bytecode, &shader->bytecode_length); 209 210 if (d3d12_debug & D3D12_DEBUG_DXIL) { 211 char buf[256]; 212 static int i; 213 snprintf(buf, sizeof(buf), "dump%02d.dxil", i++); 214 FILE *fp = fopen(buf, "wb"); 215 fwrite(shader->bytecode, sizeof(char), shader->bytecode_length, fp); 216 fclose(fp); 217 fprintf(stderr, "wrote '%s'...\n", buf); 218 } 219 return shader; 220} 221 222struct d3d12_selection_context { 223 struct d3d12_context *ctx; 224 const struct pipe_draw_info *dinfo; 225 bool needs_point_sprite_lowering; 226 bool needs_vertex_reordering; 227 unsigned provoking_vertex; 228 bool alternate_tri; 229 unsigned fill_mode_lowered; 230 unsigned cull_mode_lowered; 231 bool manual_depth_range; 232 unsigned missing_dual_src_outputs; 233 unsigned frag_result_color_lowering; 234}; 235 236static unsigned 237missing_dual_src_outputs(struct d3d12_context *ctx) 238{ 239 if (!ctx->gfx_pipeline_state.blend->is_dual_src) 240 return 0; 241 242 struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 243 nir_shader *s = fs->initial; 244 245 unsigned indices_seen = 0; 246 nir_foreach_function(function, s) { 247 if (function->impl) { 248 nir_foreach_block(block, function->impl) { 249 nir_foreach_instr(instr, block) { 250 if (instr->type != nir_instr_type_intrinsic) 251 continue; 252 253 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); 254 if (intr->intrinsic != nir_intrinsic_store_deref) 255 continue; 256 257 nir_variable *var = nir_intrinsic_get_var(intr, 0); 258 if (var->data.mode != nir_var_shader_out || 259 (var->data.location != FRAG_RESULT_COLOR && 260 var->data.location != FRAG_RESULT_DATA0)) 261 continue; 262 263 indices_seen |= 1u << var->data.index; 264 if ((indices_seen & 3) == 3) 265 return 0; 266 } 267 } 268 } 269 } 270 271 return 3 & ~indices_seen; 272} 273 274static unsigned 275frag_result_color_lowering(struct d3d12_context *ctx) 276{ 277 struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 278 assert(fs); 279 280 if (fs->initial->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_COLOR)) 281 return ctx->fb.nr_cbufs > 1 ? ctx->fb.nr_cbufs : 0; 282 283 return 0; 284} 285 286static bool 287manual_depth_range(struct d3d12_context *ctx) 288{ 289 if (!d3d12_need_zero_one_depth_range(ctx)) 290 return false; 291 292 /** 293 * If we can't use the D3D12 zero-one depth-range, we might have to apply 294 * depth-range ourselves. 295 * 296 * Because we only need to override the depth-range to zero-one range in 297 * the case where we write frag-depth, we only need to apply manual 298 * depth-range to gl_FragCoord.z. 299 * 300 * No extra care is needed to be taken in the case where gl_FragDepth is 301 * written conditionally, because the GLSL 4.60 spec states: 302 * 303 * If a shader statically assigns a value to gl_FragDepth, and there 304 * is an execution path through the shader that does not set 305 * gl_FragDepth, then the value of the fragment’s depth may be 306 * undefined for executions of the shader that take that path. That 307 * is, if the set of linked fragment shaders statically contain a 308 * write to gl_FragDepth, then it is responsible for always writing 309 * it. 310 */ 311 312 struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 313 return fs && fs->initial->info.inputs_read & VARYING_BIT_POS; 314} 315 316static bool 317needs_edge_flag_fix(enum pipe_prim_type mode) 318{ 319 return (mode == PIPE_PRIM_QUADS || 320 mode == PIPE_PRIM_QUAD_STRIP || 321 mode == PIPE_PRIM_POLYGON); 322} 323 324static unsigned 325fill_mode_lowered(struct d3d12_context *ctx, const struct pipe_draw_info *dinfo) 326{ 327 struct d3d12_shader_selector *vs = ctx->gfx_stages[PIPE_SHADER_VERTEX]; 328 329 if ((ctx->gfx_stages[PIPE_SHADER_GEOMETRY] != NULL && 330 !ctx->gfx_stages[PIPE_SHADER_GEOMETRY]->is_gs_variant) || 331 ctx->gfx_pipeline_state.rast == NULL || 332 (dinfo->mode != PIPE_PRIM_TRIANGLES && 333 dinfo->mode != PIPE_PRIM_TRIANGLE_STRIP)) 334 return PIPE_POLYGON_MODE_FILL; 335 336 /* D3D12 supports line mode (wireframe) but doesn't support edge flags */ 337 if (((ctx->gfx_pipeline_state.rast->base.fill_front == PIPE_POLYGON_MODE_LINE && 338 ctx->gfx_pipeline_state.rast->base.cull_face != PIPE_FACE_FRONT) || 339 (ctx->gfx_pipeline_state.rast->base.fill_back == PIPE_POLYGON_MODE_LINE && 340 ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_FRONT)) && 341 (vs->initial->info.outputs_written & VARYING_BIT_EDGE || 342 needs_edge_flag_fix(ctx->initial_api_prim))) 343 return PIPE_POLYGON_MODE_LINE; 344 345 if (ctx->gfx_pipeline_state.rast->base.fill_front == PIPE_POLYGON_MODE_POINT) 346 return PIPE_POLYGON_MODE_POINT; 347 348 return PIPE_POLYGON_MODE_FILL; 349} 350 351static bool 352needs_point_sprite_lowering(struct d3d12_context *ctx, const struct pipe_draw_info *dinfo) 353{ 354 struct d3d12_shader_selector *vs = ctx->gfx_stages[PIPE_SHADER_VERTEX]; 355 struct d3d12_shader_selector *gs = ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 356 357 if (gs != NULL && !gs->is_gs_variant) { 358 /* There is an user GS; Check if it outputs points with PSIZE */ 359 return (gs->initial->info.gs.output_primitive == GL_POINTS && 360 gs->initial->info.outputs_written & VARYING_BIT_PSIZ); 361 } else { 362 /* No user GS; check if we are drawing wide points */ 363 return ((dinfo->mode == PIPE_PRIM_POINTS || 364 fill_mode_lowered(ctx, dinfo) == PIPE_POLYGON_MODE_POINT) && 365 (ctx->gfx_pipeline_state.rast->base.point_size > 1.0 || 366 ctx->gfx_pipeline_state.rast->base.offset_point || 367 (ctx->gfx_pipeline_state.rast->base.point_size_per_vertex && 368 vs->initial->info.outputs_written & VARYING_BIT_PSIZ)) && 369 (vs->initial->info.outputs_written & VARYING_BIT_POS)); 370 } 371} 372 373static unsigned 374cull_mode_lowered(struct d3d12_context *ctx, unsigned fill_mode) 375{ 376 if ((ctx->gfx_stages[PIPE_SHADER_GEOMETRY] != NULL && 377 !ctx->gfx_stages[PIPE_SHADER_GEOMETRY]->is_gs_variant) || 378 ctx->gfx_pipeline_state.rast == NULL || 379 ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_NONE) 380 return PIPE_FACE_NONE; 381 382 return ctx->gfx_pipeline_state.rast->base.cull_face; 383} 384 385static unsigned 386get_provoking_vertex(struct d3d12_selection_context *sel_ctx, bool *alternate) 387{ 388 struct d3d12_shader_selector *vs = sel_ctx->ctx->gfx_stages[PIPE_SHADER_VERTEX]; 389 struct d3d12_shader_selector *gs = sel_ctx->ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 390 struct d3d12_shader_selector *last_vertex_stage = gs && !gs->is_gs_variant ? gs : vs; 391 392 /* Make sure GL prims match Gallium prims */ 393 STATIC_ASSERT(GL_POINTS == PIPE_PRIM_POINTS); 394 STATIC_ASSERT(GL_LINES == PIPE_PRIM_LINES); 395 STATIC_ASSERT(GL_LINE_STRIP == PIPE_PRIM_LINE_STRIP); 396 397 enum pipe_prim_type mode; 398 switch (last_vertex_stage->stage) { 399 case PIPE_SHADER_GEOMETRY: 400 mode = (enum pipe_prim_type)last_vertex_stage->current->nir->info.gs.output_primitive; 401 break; 402 case PIPE_SHADER_VERTEX: 403 mode = sel_ctx->dinfo ? (enum pipe_prim_type)sel_ctx->dinfo->mode : PIPE_PRIM_TRIANGLES; 404 break; 405 default: 406 unreachable("Tesselation shaders are not supported"); 407 } 408 409 bool flatshade_first = sel_ctx->ctx->gfx_pipeline_state.rast && 410 sel_ctx->ctx->gfx_pipeline_state.rast->base.flatshade_first; 411 *alternate = (mode == GL_TRIANGLE_STRIP || mode == GL_TRIANGLE_STRIP_ADJACENCY) && 412 (!gs || gs->is_gs_variant || 413 gs->initial->info.gs.vertices_out > u_prim_vertex_count(mode)->min); 414 return flatshade_first ? 0 : u_prim_vertex_count(mode)->min - 1; 415} 416 417static bool 418has_flat_varyings(struct d3d12_context *ctx) 419{ 420 struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 421 422 if (!fs || !fs->current) 423 return false; 424 425 nir_foreach_variable_with_modes(input, fs->current->nir, 426 nir_var_shader_in) { 427 if (input->data.interpolation == INTERP_MODE_FLAT) 428 return true; 429 } 430 431 return false; 432} 433 434static bool 435needs_vertex_reordering(struct d3d12_selection_context *sel_ctx) 436{ 437 struct d3d12_context *ctx = sel_ctx->ctx; 438 bool flat = has_flat_varyings(ctx); 439 bool xfb = ctx->gfx_pipeline_state.num_so_targets > 0; 440 441 if (fill_mode_lowered(ctx, sel_ctx->dinfo) != PIPE_POLYGON_MODE_FILL) 442 return false; 443 444 /* TODO add support for line primitives */ 445 446 /* When flat shading a triangle and provoking vertex is not the first one, we use load_at_vertex. 447 If not available for this adapter, or if it's a triangle strip, we need to reorder the vertices */ 448 if (flat && sel_ctx->provoking_vertex >= 2 && (!d3d12_screen(ctx->base.screen)->have_load_at_vertex || 449 sel_ctx->alternate_tri)) 450 return true; 451 452 /* When transform feedback is enabled and the output is alternating (triangle strip or triangle 453 strip with adjacency), we need to reorder vertices to get the order expected by OpenGL. This 454 only works when there is no flat shading involved. In that scenario, we don't care about 455 the provoking vertex. */ 456 if (xfb && !flat && sel_ctx->alternate_tri) { 457 sel_ctx->provoking_vertex = 0; 458 return true; 459 } 460 461 return false; 462} 463 464static nir_variable * 465create_varying_from_info(nir_shader *nir, struct d3d12_varying_info *info, 466 unsigned slot, nir_variable_mode mode) 467{ 468 nir_variable *var; 469 char tmp[100]; 470 471 snprintf(tmp, ARRAY_SIZE(tmp), 472 mode == nir_var_shader_in ? "in_%d" : "out_%d", 473 info->vars[slot].driver_location); 474 var = nir_variable_create(nir, mode, info->vars[slot].type, tmp); 475 var->data.location = slot; 476 var->data.driver_location = info->vars[slot].driver_location; 477 var->data.interpolation = info->vars[slot].interpolation; 478 479 return var; 480} 481 482static void 483fill_varyings(struct d3d12_varying_info *info, nir_shader *s, 484 nir_variable_mode modes, uint64_t mask) 485{ 486 nir_foreach_variable_with_modes(var, s, modes) { 487 unsigned slot = var->data.location; 488 uint64_t slot_bit = BITFIELD64_BIT(slot); 489 490 if (!(mask & slot_bit)) 491 continue; 492 info->vars[slot].driver_location = var->data.driver_location; 493 info->vars[slot].type = var->type; 494 info->vars[slot].interpolation = var->data.interpolation; 495 info->mask |= slot_bit; 496 } 497} 498 499static void 500fill_flat_varyings(struct d3d12_gs_variant_key *key, d3d12_shader_selector *fs) 501{ 502 if (!fs || !fs->current) 503 return; 504 505 nir_foreach_variable_with_modes(input, fs->current->nir, 506 nir_var_shader_in) { 507 if (input->data.interpolation == INTERP_MODE_FLAT) 508 key->flat_varyings |= BITFIELD64_BIT(input->data.location); 509 } 510} 511 512static void 513validate_geometry_shader_variant(struct d3d12_selection_context *sel_ctx) 514{ 515 struct d3d12_context *ctx = sel_ctx->ctx; 516 d3d12_shader_selector *vs = ctx->gfx_stages[PIPE_SHADER_VERTEX]; 517 d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 518 struct d3d12_gs_variant_key key = {0}; 519 bool variant_needed = false; 520 521 d3d12_shader_selector *gs = ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 522 523 /* Nothing to do if there is a user geometry shader bound */ 524 if (gs != NULL && !gs->is_gs_variant) 525 return; 526 527 /* Fill the geometry shader variant key */ 528 if (sel_ctx->fill_mode_lowered != PIPE_POLYGON_MODE_FILL) { 529 key.fill_mode = sel_ctx->fill_mode_lowered; 530 key.cull_mode = sel_ctx->cull_mode_lowered; 531 key.has_front_face = BITSET_TEST(fs->initial->info.system_values_read, SYSTEM_VALUE_FRONT_FACE); 532 if (key.cull_mode != PIPE_FACE_NONE || key.has_front_face) 533 key.front_ccw = ctx->gfx_pipeline_state.rast->base.front_ccw ^ (ctx->flip_y < 0); 534 key.edge_flag_fix = needs_edge_flag_fix(ctx->initial_api_prim); 535 fill_flat_varyings(&key, fs); 536 if (key.flat_varyings != 0) 537 key.flatshade_first = ctx->gfx_pipeline_state.rast->base.flatshade_first; 538 variant_needed = true; 539 } else if (sel_ctx->needs_point_sprite_lowering) { 540 key.passthrough = true; 541 variant_needed = true; 542 } else if (sel_ctx->needs_vertex_reordering) { 543 /* TODO support cases where flat shading (pv != 0) and xfb are enabled */ 544 key.provoking_vertex = sel_ctx->provoking_vertex; 545 key.alternate_tri = sel_ctx->alternate_tri; 546 variant_needed = true; 547 } 548 549 if (variant_needed) { 550 fill_varyings(&key.varyings, vs->initial, nir_var_shader_out, 551 vs->initial->info.outputs_written); 552 } 553 554 /* Check if the currently bound geometry shader variant is correct */ 555 if (gs && memcmp(&gs->gs_key, &key, sizeof(key)) == 0) 556 return; 557 558 /* Find/create the proper variant and bind it */ 559 gs = variant_needed ? d3d12_get_gs_variant(ctx, &key) : NULL; 560 ctx->gfx_stages[PIPE_SHADER_GEOMETRY] = gs; 561} 562 563static bool 564d3d12_compare_shader_keys(const d3d12_shader_key *expect, const d3d12_shader_key *have) 565{ 566 assert(expect->stage == have->stage); 567 assert(expect); 568 assert(have); 569 570 /* Because we only add varyings we check that a shader has at least the expected in- 571 * and outputs. */ 572 if (memcmp(&expect->required_varying_inputs, &have->required_varying_inputs, 573 sizeof(struct d3d12_varying_info)) || 574 memcmp(&expect->required_varying_outputs, &have->required_varying_outputs, 575 sizeof(struct d3d12_varying_info)) || 576 (expect->next_varying_inputs != have->next_varying_inputs) || 577 (expect->prev_varying_outputs != have->prev_varying_outputs)) 578 return false; 579 580 if (expect->stage == PIPE_SHADER_GEOMETRY) { 581 if (expect->gs.writes_psize) { 582 if (!have->gs.writes_psize || 583 expect->gs.point_pos_stream_out != have->gs.point_pos_stream_out || 584 expect->gs.sprite_coord_enable != have->gs.sprite_coord_enable || 585 expect->gs.sprite_origin_upper_left != have->gs.sprite_origin_upper_left || 586 expect->gs.point_size_per_vertex != have->gs.point_size_per_vertex) 587 return false; 588 } else if (have->gs.writes_psize) { 589 return false; 590 } 591 if (expect->gs.primitive_id != have->gs.primitive_id || 592 expect->gs.triangle_strip != have->gs.triangle_strip) 593 return false; 594 } else if (expect->stage == PIPE_SHADER_FRAGMENT) { 595 if (expect->fs.frag_result_color_lowering != have->fs.frag_result_color_lowering || 596 expect->fs.manual_depth_range != have->fs.manual_depth_range || 597 expect->fs.polygon_stipple != have->fs.polygon_stipple || 598 expect->fs.cast_to_uint != have->fs.cast_to_uint || 599 expect->fs.cast_to_int != have->fs.cast_to_int) 600 return false; 601 } 602 603 if (expect->tex_saturate_s != have->tex_saturate_s || 604 expect->tex_saturate_r != have->tex_saturate_r || 605 expect->tex_saturate_t != have->tex_saturate_t) 606 return false; 607 608 if (expect->samples_int_textures != have->samples_int_textures) 609 return false; 610 611 if (expect->n_texture_states != have->n_texture_states) 612 return false; 613 614 if (memcmp(expect->tex_wrap_states, have->tex_wrap_states, 615 expect->n_texture_states * sizeof(dxil_wrap_sampler_state))) 616 return false; 617 618 if (memcmp(expect->swizzle_state, have->swizzle_state, 619 expect->n_texture_states * sizeof(dxil_texture_swizzle_state))) 620 return false; 621 622 if (memcmp(expect->sampler_compare_funcs, have->sampler_compare_funcs, 623 expect->n_texture_states * sizeof(enum compare_func))) 624 return false; 625 626 if (expect->invert_depth != have->invert_depth) 627 return false; 628 629 if (expect->stage == PIPE_SHADER_VERTEX) { 630 if (expect->vs.needs_format_emulation != have->vs.needs_format_emulation) 631 return false; 632 633 if (expect->vs.needs_format_emulation) { 634 if (memcmp(expect->vs.format_conversion, have->vs.format_conversion, 635 PIPE_MAX_ATTRIBS * sizeof (enum pipe_format))) 636 return false; 637 } 638 } 639 640 if (expect->fs.provoking_vertex != have->fs.provoking_vertex) 641 return false; 642 643 return true; 644} 645 646static void 647d3d12_fill_shader_key(struct d3d12_selection_context *sel_ctx, 648 d3d12_shader_key *key, d3d12_shader_selector *sel, 649 d3d12_shader_selector *prev, d3d12_shader_selector *next) 650{ 651 pipe_shader_type stage = sel->stage; 652 653 uint64_t system_generated_in_values = 654 VARYING_BIT_PNTC | 655 VARYING_BIT_PRIMITIVE_ID; 656 657 uint64_t system_out_values = 658 VARYING_BIT_CLIP_DIST0 | 659 VARYING_BIT_CLIP_DIST1; 660 661 memset(key, 0, sizeof(d3d12_shader_key)); 662 key->stage = stage; 663 664 if (prev) { 665 /* We require as inputs what the previous stage has written, 666 * except certain system values */ 667 if (stage == PIPE_SHADER_FRAGMENT || stage == PIPE_SHADER_GEOMETRY) 668 system_out_values |= VARYING_BIT_POS; 669 if (stage == PIPE_SHADER_FRAGMENT) 670 system_out_values |= VARYING_BIT_PSIZ; 671 uint64_t mask = prev->current->nir->info.outputs_written & ~system_out_values; 672 fill_varyings(&key->required_varying_inputs, prev->current->nir, 673 nir_var_shader_out, mask); 674 key->prev_varying_outputs = prev->current->nir->info.outputs_written; 675 676 /* Set the provoking vertex based on the previous shader output. Only set the 677 * key value if the driver actually supports changing the provoking vertex though */ 678 if (stage == PIPE_SHADER_FRAGMENT && sel_ctx->ctx->gfx_pipeline_state.rast && 679 !sel_ctx->needs_vertex_reordering && 680 d3d12_screen(sel_ctx->ctx->base.screen)->have_load_at_vertex) 681 key->fs.provoking_vertex = sel_ctx->provoking_vertex; 682 } 683 684 /* We require as outputs what the next stage reads, 685 * except certain system values */ 686 if (next) { 687 if (!next->is_gs_variant) { 688 if (stage == PIPE_SHADER_VERTEX) 689 system_generated_in_values |= VARYING_BIT_POS; 690 uint64_t mask = next->current->nir->info.inputs_read & ~system_generated_in_values; 691 fill_varyings(&key->required_varying_outputs, next->current->nir, 692 nir_var_shader_in, mask); 693 } 694 key->next_varying_inputs = next->current->nir->info.inputs_read; 695 } 696 697 if (stage == PIPE_SHADER_GEOMETRY || 698 (stage == PIPE_SHADER_VERTEX && (!next || next->stage != PIPE_SHADER_GEOMETRY))) { 699 key->last_vertex_processing_stage = 1; 700 key->invert_depth = sel_ctx->ctx->reverse_depth_range; 701 if (sel_ctx->ctx->pstipple.enabled) 702 key->next_varying_inputs |= VARYING_BIT_POS; 703 } 704 705 if (stage == PIPE_SHADER_GEOMETRY && sel_ctx->ctx->gfx_pipeline_state.rast) { 706 struct pipe_rasterizer_state *rast = &sel_ctx->ctx->gfx_pipeline_state.rast->base; 707 if (sel_ctx->needs_point_sprite_lowering) { 708 key->gs.writes_psize = 1; 709 key->gs.point_size_per_vertex = rast->point_size_per_vertex; 710 key->gs.sprite_coord_enable = rast->sprite_coord_enable; 711 key->gs.sprite_origin_upper_left = (rast->sprite_coord_mode != PIPE_SPRITE_COORD_LOWER_LEFT); 712 if (sel_ctx->ctx->flip_y < 0) 713 key->gs.sprite_origin_upper_left = !key->gs.sprite_origin_upper_left; 714 key->gs.aa_point = rast->point_smooth; 715 key->gs.stream_output_factor = 6; 716 } else if (sel_ctx->fill_mode_lowered == PIPE_POLYGON_MODE_LINE) { 717 key->gs.stream_output_factor = 2; 718 } else if (sel_ctx->needs_vertex_reordering && !sel->is_gs_variant) { 719 key->gs.triangle_strip = 1; 720 } 721 722 if (sel->is_gs_variant && next && next->initial->info.inputs_read & VARYING_BIT_PRIMITIVE_ID) 723 key->gs.primitive_id = 1; 724 } else if (stage == PIPE_SHADER_FRAGMENT) { 725 key->fs.missing_dual_src_outputs = sel_ctx->missing_dual_src_outputs; 726 key->fs.frag_result_color_lowering = sel_ctx->frag_result_color_lowering; 727 key->fs.manual_depth_range = sel_ctx->manual_depth_range; 728 key->fs.polygon_stipple = sel_ctx->ctx->pstipple.enabled; 729 if (sel_ctx->ctx->gfx_pipeline_state.blend && 730 sel_ctx->ctx->gfx_pipeline_state.blend->desc.RenderTarget[0].LogicOpEnable && 731 !sel_ctx->ctx->gfx_pipeline_state.has_float_rtv) { 732 key->fs.cast_to_uint = util_format_is_unorm(sel_ctx->ctx->fb.cbufs[0]->format); 733 key->fs.cast_to_int = !key->fs.cast_to_uint; 734 } 735 } 736 737 if (sel->samples_int_textures) { 738 key->samples_int_textures = sel->samples_int_textures; 739 key->n_texture_states = sel_ctx->ctx->num_sampler_views[stage]; 740 /* Copy only states with integer textures */ 741 for(int i = 0; i < key->n_texture_states; ++i) { 742 auto& wrap_state = sel_ctx->ctx->tex_wrap_states[stage][i]; 743 if (wrap_state.is_int_sampler) { 744 memcpy(&key->tex_wrap_states[i], &wrap_state, sizeof(wrap_state)); 745 key->swizzle_state[i] = sel_ctx->ctx->tex_swizzle_state[stage][i]; 746 } 747 } 748 } 749 750 for (unsigned i = 0; i < sel_ctx->ctx->num_samplers[stage]; ++i) { 751 if (!sel_ctx->ctx->samplers[stage][i] || 752 sel_ctx->ctx->samplers[stage][i]->filter == PIPE_TEX_FILTER_NEAREST) 753 continue; 754 755 if (sel_ctx->ctx->samplers[stage][i]->wrap_r == PIPE_TEX_WRAP_CLAMP) 756 key->tex_saturate_r |= 1 << i; 757 if (sel_ctx->ctx->samplers[stage][i]->wrap_s == PIPE_TEX_WRAP_CLAMP) 758 key->tex_saturate_s |= 1 << i; 759 if (sel_ctx->ctx->samplers[stage][i]->wrap_t == PIPE_TEX_WRAP_CLAMP) 760 key->tex_saturate_t |= 1 << i; 761 } 762 763 if (sel->compare_with_lod_bias_grad) { 764 key->n_texture_states = sel_ctx->ctx->num_sampler_views[stage]; 765 memcpy(key->sampler_compare_funcs, sel_ctx->ctx->tex_compare_func[stage], 766 key->n_texture_states * sizeof(enum compare_func)); 767 memcpy(key->swizzle_state, sel_ctx->ctx->tex_swizzle_state[stage], 768 key->n_texture_states * sizeof(dxil_texture_swizzle_state)); 769 } 770 771 if (stage == PIPE_SHADER_VERTEX && sel_ctx->ctx->gfx_pipeline_state.ves) { 772 key->vs.needs_format_emulation = sel_ctx->ctx->gfx_pipeline_state.ves->needs_format_emulation; 773 if (key->vs.needs_format_emulation) { 774 memcpy(key->vs.format_conversion, sel_ctx->ctx->gfx_pipeline_state.ves->format_conversion, 775 sel_ctx->ctx->gfx_pipeline_state.ves->num_elements * sizeof(enum pipe_format)); 776 } 777 } 778 779 if (stage == PIPE_SHADER_FRAGMENT && 780 sel_ctx->ctx->gfx_stages[PIPE_SHADER_GEOMETRY] && 781 sel_ctx->ctx->gfx_stages[PIPE_SHADER_GEOMETRY]->is_gs_variant && 782 sel_ctx->ctx->gfx_stages[PIPE_SHADER_GEOMETRY]->gs_key.has_front_face) { 783 key->fs.remap_front_facing = 1; 784 } 785} 786 787static void 788select_shader_variant(struct d3d12_selection_context *sel_ctx, d3d12_shader_selector *sel, 789 d3d12_shader_selector *prev, d3d12_shader_selector *next) 790{ 791 struct d3d12_context *ctx = sel_ctx->ctx; 792 d3d12_shader_key key; 793 nir_shader *new_nir_variant; 794 unsigned pstipple_binding = UINT32_MAX; 795 796 d3d12_fill_shader_key(sel_ctx, &key, sel, prev, next); 797 798 /* Check for an existing variant */ 799 for (d3d12_shader *variant = sel->first; variant; 800 variant = variant->next_variant) { 801 802 if (d3d12_compare_shader_keys(&key, &variant->key)) { 803 sel->current = variant; 804 return; 805 } 806 } 807 808 /* Clone the NIR shader */ 809 new_nir_variant = nir_shader_clone(sel, sel->initial); 810 811 /* Apply any needed lowering passes */ 812 if (key.gs.writes_psize) { 813 NIR_PASS_V(new_nir_variant, d3d12_lower_point_sprite, 814 !key.gs.sprite_origin_upper_left, 815 key.gs.point_size_per_vertex, 816 key.gs.sprite_coord_enable, 817 key.next_varying_inputs); 818 819 nir_function_impl *impl = nir_shader_get_entrypoint(new_nir_variant); 820 nir_shader_gather_info(new_nir_variant, impl); 821 } 822 823 if (key.gs.primitive_id) { 824 NIR_PASS_V(new_nir_variant, d3d12_lower_primitive_id); 825 826 nir_function_impl *impl = nir_shader_get_entrypoint(new_nir_variant); 827 nir_shader_gather_info(new_nir_variant, impl); 828 } 829 830 if (key.gs.triangle_strip) 831 NIR_PASS_V(new_nir_variant, d3d12_lower_triangle_strip); 832 833 if (key.fs.polygon_stipple) { 834 NIR_PASS_V(new_nir_variant, nir_lower_pstipple_fs, 835 &pstipple_binding, 0, false); 836 837 nir_function_impl *impl = nir_shader_get_entrypoint(new_nir_variant); 838 nir_shader_gather_info(new_nir_variant, impl); 839 } 840 841 if (key.fs.remap_front_facing) { 842 d3d12_forward_front_face(new_nir_variant); 843 844 nir_function_impl *impl = nir_shader_get_entrypoint(new_nir_variant); 845 nir_shader_gather_info(new_nir_variant, impl); 846 } 847 848 if (key.fs.missing_dual_src_outputs) { 849 NIR_PASS_V(new_nir_variant, d3d12_add_missing_dual_src_target, 850 key.fs.missing_dual_src_outputs); 851 } else if (key.fs.frag_result_color_lowering) { 852 NIR_PASS_V(new_nir_variant, nir_lower_fragcolor, 853 key.fs.frag_result_color_lowering); 854 } 855 856 if (key.fs.manual_depth_range) 857 NIR_PASS_V(new_nir_variant, d3d12_lower_depth_range); 858 859 if (sel->compare_with_lod_bias_grad) 860 NIR_PASS_V(new_nir_variant, d3d12_lower_sample_tex_compare, key.n_texture_states, 861 key.sampler_compare_funcs, key.swizzle_state); 862 863 if (key.fs.cast_to_uint) 864 NIR_PASS_V(new_nir_variant, d3d12_lower_uint_cast, false); 865 if (key.fs.cast_to_int) 866 NIR_PASS_V(new_nir_variant, d3d12_lower_uint_cast, true); 867 868 { 869 struct nir_lower_tex_options tex_options = { }; 870 tex_options.lower_txp = ~0u; /* No equivalent for textureProj */ 871 tex_options.lower_rect = true; 872 tex_options.lower_rect_offset = true; 873 tex_options.saturate_s = key.tex_saturate_s; 874 tex_options.saturate_r = key.tex_saturate_r; 875 tex_options.saturate_t = key.tex_saturate_t; 876 877 NIR_PASS_V(new_nir_variant, nir_lower_tex, &tex_options); 878 } 879 880 /* Add the needed in and outputs, and re-sort */ 881 uint64_t mask = key.required_varying_inputs.mask & ~new_nir_variant->info.inputs_read; 882 883 if (prev) { 884 while (mask) { 885 int slot = u_bit_scan64(&mask); 886 create_varying_from_info(new_nir_variant, &key.required_varying_inputs, slot, nir_var_shader_in); 887 } 888 dxil_reassign_driver_locations(new_nir_variant, nir_var_shader_in, 889 key.prev_varying_outputs); 890 } 891 892 mask = key.required_varying_outputs.mask & ~new_nir_variant->info.outputs_written; 893 894 if (next) { 895 while (mask) { 896 int slot = u_bit_scan64(&mask); 897 create_varying_from_info(new_nir_variant, &key.required_varying_outputs, slot, nir_var_shader_out); 898 } 899 dxil_reassign_driver_locations(new_nir_variant, nir_var_shader_out, 900 key.next_varying_inputs); 901 } 902 903 d3d12_shader *new_variant = compile_nir(ctx, sel, &key, new_nir_variant); 904 assert(new_variant); 905 906 /* keep track of polygon stipple texture binding */ 907 new_variant->pstipple_binding = pstipple_binding; 908 909 /* prepend the new shader in the selector chain and pick it */ 910 new_variant->next_variant = sel->first; 911 sel->current = sel->first = new_variant; 912} 913 914static d3d12_shader_selector * 915get_prev_shader(struct d3d12_context *ctx, pipe_shader_type current) 916{ 917 /* No TESS_CTRL or TESS_EVAL yet */ 918 919 switch (current) { 920 case PIPE_SHADER_VERTEX: 921 return NULL; 922 case PIPE_SHADER_FRAGMENT: 923 if (ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) 924 return ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 925 FALLTHROUGH; 926 case PIPE_SHADER_GEOMETRY: 927 return ctx->gfx_stages[PIPE_SHADER_VERTEX]; 928 default: 929 unreachable("shader type not supported"); 930 } 931} 932 933static d3d12_shader_selector * 934get_next_shader(struct d3d12_context *ctx, pipe_shader_type current) 935{ 936 /* No TESS_CTRL or TESS_EVAL yet */ 937 938 switch (current) { 939 case PIPE_SHADER_VERTEX: 940 if (ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) 941 return ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 942 FALLTHROUGH; 943 case PIPE_SHADER_GEOMETRY: 944 return ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 945 case PIPE_SHADER_FRAGMENT: 946 return NULL; 947 default: 948 unreachable("shader type not supported"); 949 } 950} 951 952enum tex_scan_flags { 953 TEX_SAMPLE_INTEGER_TEXTURE = 1 << 0, 954 TEX_CMP_WITH_LOD_BIAS_GRAD = 1 << 1, 955 TEX_SCAN_ALL_FLAGS = (1 << 2) - 1 956}; 957 958static unsigned 959scan_texture_use(nir_shader *nir) 960{ 961 unsigned result = 0; 962 nir_foreach_function(func, nir) { 963 nir_foreach_block(block, func->impl) { 964 nir_foreach_instr(instr, block) { 965 if (instr->type == nir_instr_type_tex) { 966 auto tex = nir_instr_as_tex(instr); 967 switch (tex->op) { 968 case nir_texop_txb: 969 case nir_texop_txl: 970 case nir_texop_txd: 971 if (tex->is_shadow) 972 result |= TEX_CMP_WITH_LOD_BIAS_GRAD; 973 FALLTHROUGH; 974 case nir_texop_tex: 975 if (tex->dest_type & (nir_type_int | nir_type_uint)) 976 result |= TEX_SAMPLE_INTEGER_TEXTURE; 977 default: 978 ; 979 } 980 } 981 if (TEX_SCAN_ALL_FLAGS == result) 982 return result; 983 } 984 } 985 } 986 return result; 987} 988 989static uint64_t 990update_so_info(struct pipe_stream_output_info *so_info, 991 uint64_t outputs_written) 992{ 993 uint64_t so_outputs = 0; 994 uint8_t reverse_map[64] = {0}; 995 unsigned slot = 0; 996 997 while (outputs_written) 998 reverse_map[slot++] = u_bit_scan64(&outputs_written); 999 1000 for (unsigned i = 0; i < so_info->num_outputs; i++) { 1001 struct pipe_stream_output *output = &so_info->output[i]; 1002 1003 /* Map Gallium's condensed "slots" back to real VARYING_SLOT_* enums */ 1004 output->register_index = reverse_map[output->register_index]; 1005 1006 so_outputs |= 1ull << output->register_index; 1007 } 1008 1009 return so_outputs; 1010} 1011 1012struct d3d12_shader_selector * 1013d3d12_create_shader(struct d3d12_context *ctx, 1014 pipe_shader_type stage, 1015 const struct pipe_shader_state *shader) 1016{ 1017 struct d3d12_shader_selector *sel = rzalloc(nullptr, d3d12_shader_selector); 1018 sel->stage = stage; 1019 1020 struct nir_shader *nir = NULL; 1021 1022 if (shader->type == PIPE_SHADER_IR_NIR) { 1023 nir = (nir_shader *)shader->ir.nir; 1024 } else { 1025 assert(shader->type == PIPE_SHADER_IR_TGSI); 1026 nir = tgsi_to_nir(shader->tokens, ctx->base.screen, false); 1027 } 1028 1029 nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir)); 1030 1031 unsigned tex_scan_result = scan_texture_use(nir); 1032 sel->samples_int_textures = (tex_scan_result & TEX_SAMPLE_INTEGER_TEXTURE) != 0; 1033 sel->compare_with_lod_bias_grad = (tex_scan_result & TEX_CMP_WITH_LOD_BIAS_GRAD) != 0; 1034 1035 memcpy(&sel->so_info, &shader->stream_output, sizeof(sel->so_info)); 1036 update_so_info(&sel->so_info, nir->info.outputs_written); 1037 1038 assert(nir != NULL); 1039 d3d12_shader_selector *prev = get_prev_shader(ctx, sel->stage); 1040 d3d12_shader_selector *next = get_next_shader(ctx, sel->stage); 1041 1042 uint64_t in_mask = nir->info.stage == MESA_SHADER_VERTEX ? 1043 0 : VARYING_BIT_PRIMITIVE_ID; 1044 1045 uint64_t out_mask = nir->info.stage == MESA_SHADER_FRAGMENT ? 1046 (1ull << FRAG_RESULT_STENCIL) : 1047 VARYING_BIT_PRIMITIVE_ID; 1048 1049 d3d12_fix_io_uint_type(nir, in_mask, out_mask); 1050 NIR_PASS_V(nir, dxil_nir_split_clip_cull_distance); 1051 1052 if (nir->info.stage != MESA_SHADER_VERTEX) 1053 nir->info.inputs_read = 1054 dxil_reassign_driver_locations(nir, nir_var_shader_in, 1055 prev ? prev->current->nir->info.outputs_written : 0); 1056 else 1057 nir->info.inputs_read = dxil_sort_by_driver_location(nir, nir_var_shader_in); 1058 1059 if (nir->info.stage != MESA_SHADER_FRAGMENT) { 1060 nir->info.outputs_written = 1061 dxil_reassign_driver_locations(nir, nir_var_shader_out, 1062 next ? next->current->nir->info.inputs_read : 0); 1063 } else { 1064 NIR_PASS_V(nir, nir_lower_fragcoord_wtrans); 1065 dxil_sort_ps_outputs(nir); 1066 } 1067 1068 /* Integer cube maps are not supported in DirectX because sampling is not supported 1069 * on integer textures and TextureLoad is not supported for cube maps, so we have to 1070 * lower integer cube maps to be handled like 2D textures arrays*/ 1071 NIR_PASS_V(nir, d3d12_lower_int_cubmap_to_array); 1072 1073 /* Keep this initial shader as the blue print for possible variants */ 1074 sel->initial = nir; 1075 1076 /* 1077 * We must compile some shader here, because if the previous or a next shaders exists later 1078 * when the shaders are bound, then the key evaluation in the shader selector will access 1079 * the current variant of these prev and next shader, and we can only assign 1080 * a current variant when it has been successfully compiled. 1081 * 1082 * For shaders that require lowering because certain instructions are not available 1083 * and their emulation is state depended (like sampling an integer texture that must be 1084 * emulated and needs handling of boundary conditions, or shadow compare sampling with LOD), 1085 * we must go through the shader selector here to create a compilable variant. 1086 * For shaders that are not depended on the state this is just compiling the original 1087 * shader. 1088 * 1089 * TODO: get rid of having to compiling the shader here if it can be forseen that it will 1090 * be thrown away (i.e. it depends on states that are likely to change before the shader is 1091 * used for the first time) 1092 */ 1093 struct d3d12_selection_context sel_ctx = {0}; 1094 sel_ctx.ctx = ctx; 1095 select_shader_variant(&sel_ctx, sel, prev, next); 1096 1097 if (!sel->current) { 1098 ralloc_free(sel); 1099 return NULL; 1100 } 1101 1102 return sel; 1103} 1104 1105void 1106d3d12_select_shader_variants(struct d3d12_context *ctx, const struct pipe_draw_info *dinfo) 1107{ 1108 static unsigned order[] = {PIPE_SHADER_VERTEX, PIPE_SHADER_GEOMETRY, PIPE_SHADER_FRAGMENT}; 1109 struct d3d12_selection_context sel_ctx; 1110 1111 sel_ctx.ctx = ctx; 1112 sel_ctx.dinfo = dinfo; 1113 sel_ctx.needs_point_sprite_lowering = needs_point_sprite_lowering(ctx, dinfo); 1114 sel_ctx.fill_mode_lowered = fill_mode_lowered(ctx, dinfo); 1115 sel_ctx.cull_mode_lowered = cull_mode_lowered(ctx, sel_ctx.fill_mode_lowered); 1116 sel_ctx.provoking_vertex = get_provoking_vertex(&sel_ctx, &sel_ctx.alternate_tri); 1117 sel_ctx.needs_vertex_reordering = needs_vertex_reordering(&sel_ctx); 1118 sel_ctx.missing_dual_src_outputs = missing_dual_src_outputs(ctx); 1119 sel_ctx.frag_result_color_lowering = frag_result_color_lowering(ctx); 1120 sel_ctx.manual_depth_range = manual_depth_range(ctx); 1121 1122 validate_geometry_shader_variant(&sel_ctx); 1123 1124 for (unsigned i = 0; i < ARRAY_SIZE(order); ++i) { 1125 auto sel = ctx->gfx_stages[order[i]]; 1126 if (!sel) 1127 continue; 1128 1129 d3d12_shader_selector *prev = get_prev_shader(ctx, sel->stage); 1130 d3d12_shader_selector *next = get_next_shader(ctx, sel->stage); 1131 1132 select_shader_variant(&sel_ctx, sel, prev, next); 1133 } 1134} 1135 1136void 1137d3d12_shader_free(struct d3d12_shader_selector *sel) 1138{ 1139 auto shader = sel->first; 1140 while (shader) { 1141 free(shader->bytecode); 1142 shader = shader->next_variant; 1143 } 1144 ralloc_free(sel->initial); 1145 ralloc_free(sel); 1146} 1147 1148#ifdef _WIN32 1149// Used to get path to self 1150extern "C" extern IMAGE_DOS_HEADER __ImageBase; 1151#endif 1152 1153void d3d12_validation_tools::load_dxil_dll() 1154{ 1155 if (!dxil_module.load(UTIL_DL_PREFIX "dxil" UTIL_DL_EXT)) { 1156#ifdef _WIN32 1157 char selfPath[MAX_PATH] = ""; 1158 uint32_t pathSize = GetModuleFileNameA((HINSTANCE)&__ImageBase, selfPath, sizeof(selfPath)); 1159 if (pathSize == 0 || pathSize == sizeof(selfPath)) { 1160 debug_printf("D3D12: Unable to get path to self"); 1161 return; 1162 } 1163 1164 auto lastSlash = strrchr(selfPath, '\\'); 1165 if (!lastSlash) { 1166 debug_printf("D3D12: Unable to get path to self"); 1167 return; 1168 } 1169 1170 *(lastSlash + 1) = '\0'; 1171 if (strcat_s(selfPath, "dxil.dll") != 0) { 1172 debug_printf("D3D12: Unable to get path to dxil.dll next to self"); 1173 return; 1174 } 1175 1176 dxil_module.load(selfPath); 1177#endif 1178 } 1179} 1180 1181d3d12_validation_tools::d3d12_validation_tools() 1182{ 1183 load_dxil_dll(); 1184 DxcCreateInstanceProc dxil_create_func = (DxcCreateInstanceProc)util_dl_get_proc_address(dxil_module, "DxcCreateInstance"); 1185 1186 if (dxil_create_func) { 1187 HRESULT hr = dxil_create_func(CLSID_DxcValidator, IID_PPV_ARGS(&validator)); 1188 if (FAILED(hr)) { 1189 debug_printf("D3D12: Unable to create validator\n"); 1190 } 1191 } 1192#ifdef _WIN32 1193 else if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)) { 1194 debug_printf("D3D12: Unable to load DXIL.dll\n"); 1195 } 1196#endif 1197 1198 DxcCreateInstanceProc compiler_create_func = nullptr; 1199 if(dxc_compiler_module.load("dxcompiler.dll")) 1200 compiler_create_func = (DxcCreateInstanceProc)util_dl_get_proc_address(dxc_compiler_module, "DxcCreateInstance"); 1201 1202 if (compiler_create_func) { 1203 HRESULT hr = compiler_create_func(CLSID_DxcLibrary, IID_PPV_ARGS(&library)); 1204 if (FAILED(hr)) { 1205 debug_printf("D3D12: Unable to create library instance: %x\n", hr); 1206 } 1207 1208 if (d3d12_debug & D3D12_DEBUG_DISASS) { 1209 hr = compiler_create_func(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); 1210 if (FAILED(hr)) { 1211 debug_printf("D3D12: Unable to create compiler instance\n"); 1212 } 1213 } 1214 } else if (d3d12_debug & D3D12_DEBUG_DISASS) { 1215 debug_printf("D3D12: Disassembly requested but compiler couldn't be loaded\n"); 1216 } 1217} 1218 1219d3d12_validation_tools::HModule::HModule(): 1220 module(0) 1221{ 1222} 1223 1224d3d12_validation_tools::HModule::~HModule() 1225{ 1226 if (module) 1227 util_dl_close(module); 1228} 1229 1230inline 1231d3d12_validation_tools::HModule::operator util_dl_library * () const 1232{ 1233 return module; 1234} 1235 1236bool 1237d3d12_validation_tools::HModule::load(LPCSTR file_name) 1238{ 1239 module = util_dl_open(file_name); 1240 return module != nullptr; 1241} 1242 1243 1244class ShaderBlob : public IDxcBlob { 1245public: 1246 ShaderBlob(blob* data) : m_data(data) {} 1247 1248 LPVOID STDMETHODCALLTYPE GetBufferPointer(void) override { return m_data->data; } 1249 1250 SIZE_T STDMETHODCALLTYPE GetBufferSize() override { return m_data->size; } 1251 1252 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) override { return E_NOINTERFACE; } 1253 1254 ULONG STDMETHODCALLTYPE AddRef() override { return 1; } 1255 1256 ULONG STDMETHODCALLTYPE Release() override { return 0; } 1257 1258 blob* m_data; 1259}; 1260 1261bool d3d12_validation_tools::validate_and_sign(struct blob *dxil) 1262{ 1263 ShaderBlob source(dxil); 1264 1265 ComPtr<IDxcOperationResult> result; 1266 1267 validator->Validate(&source, DxcValidatorFlags_InPlaceEdit, &result); 1268 HRESULT validationStatus; 1269 result->GetStatus(&validationStatus); 1270 if (FAILED(validationStatus) && library) { 1271 ComPtr<IDxcBlobEncoding> printBlob, printBlobUtf8; 1272 result->GetErrorBuffer(&printBlob); 1273 library->GetBlobAsUtf8(printBlob.Get(), printBlobUtf8.GetAddressOf()); 1274 1275 char *errorString; 1276 if (printBlobUtf8) { 1277 errorString = reinterpret_cast<char*>(printBlobUtf8->GetBufferPointer()); 1278 1279 errorString[printBlobUtf8->GetBufferSize() - 1] = 0; 1280 debug_printf("== VALIDATION ERROR =============================================\n%s\n" 1281 "== END ==========================================================\n", 1282 errorString); 1283 } 1284 1285 return false; 1286 } 1287 return true; 1288 1289} 1290 1291void d3d12_validation_tools::disassemble(struct blob *dxil) 1292{ 1293 if (!compiler) { 1294 fprintf(stderr, "D3D12: No Disassembler\n"); 1295 return; 1296 } 1297 ShaderBlob source(dxil); 1298 IDxcBlobEncoding* pDisassembly = nullptr; 1299 1300 if (FAILED(compiler->Disassemble(&source, &pDisassembly))) { 1301 fprintf(stderr, "D3D12: Disassembler failed\n"); 1302 return; 1303 } 1304 1305 ComPtr<IDxcBlobEncoding> dissassably(pDisassembly); 1306 ComPtr<IDxcBlobEncoding> blobUtf8; 1307 library->GetBlobAsUtf8(pDisassembly, blobUtf8.GetAddressOf()); 1308 if (!blobUtf8) { 1309 fprintf(stderr, "D3D12: Unable to get utf8 encoding\n"); 1310 return; 1311 } 1312 1313 char *disassembly = reinterpret_cast<char*>(blobUtf8->GetBufferPointer()); 1314 disassembly[blobUtf8->GetBufferSize() - 1] = 0; 1315 1316 fprintf(stderr, "== BEGIN SHADER ============================================\n" 1317 "%s\n" 1318 "== END SHADER ==============================================\n", 1319 disassembly); 1320} 1321