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_format.h" 27#include "d3d12_query.h" 28#include "d3d12_resource.h" 29#include "d3d12_root_signature.h" 30#include "d3d12_screen.h" 31#include "d3d12_surface.h" 32 33#include "util/u_debug.h" 34#include "util/u_draw.h" 35#include "util/u_helpers.h" 36#include "util/u_inlines.h" 37#include "util/u_prim.h" 38#include "util/u_prim_restart.h" 39#include "util/u_math.h" 40 41extern "C" { 42#include "indices/u_primconvert.h" 43} 44 45static const D3D12_RECT MAX_SCISSOR = { D3D12_VIEWPORT_BOUNDS_MIN, 46 D3D12_VIEWPORT_BOUNDS_MIN, 47 D3D12_VIEWPORT_BOUNDS_MAX, 48 D3D12_VIEWPORT_BOUNDS_MAX }; 49 50static D3D12_GPU_DESCRIPTOR_HANDLE 51fill_cbv_descriptors(struct d3d12_context *ctx, 52 struct d3d12_shader *shader, 53 int stage) 54{ 55 struct d3d12_batch *batch = d3d12_current_batch(ctx); 56 struct d3d12_descriptor_handle table_start; 57 d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); 58 59 for (unsigned i = 0; i < shader->num_cb_bindings; i++) { 60 unsigned binding = shader->cb_bindings[i].binding; 61 struct pipe_constant_buffer *buffer = &ctx->cbufs[stage][binding]; 62 63 D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {}; 64 if (buffer && buffer->buffer) { 65 struct d3d12_resource *res = d3d12_resource(buffer->buffer); 66 d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE); 67 cbv_desc.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset; 68 cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16, 69 align(buffer->buffer_size, 256)); 70 d3d12_batch_reference_resource(batch, res); 71 } 72 73 struct d3d12_descriptor_handle handle; 74 d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle); 75 d3d12_screen(ctx->base.screen)->dev->CreateConstantBufferView(&cbv_desc, handle.cpu_handle); 76 } 77 78 return table_start.gpu_handle; 79} 80 81static D3D12_GPU_DESCRIPTOR_HANDLE 82fill_srv_descriptors(struct d3d12_context *ctx, 83 struct d3d12_shader *shader, 84 unsigned stage) 85{ 86 struct d3d12_batch *batch = d3d12_current_batch(ctx); 87 struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 88 D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 89 struct d3d12_descriptor_handle table_start; 90 91 d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); 92 93 for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++) 94 { 95 struct d3d12_sampler_view *view; 96 97 if (i == shader->pstipple_binding) { 98 view = (struct d3d12_sampler_view*)ctx->pstipple.sampler_view; 99 } else { 100 view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][i]; 101 } 102 103 unsigned desc_idx = i - shader->begin_srv_binding; 104 if (view != NULL) { 105 descs[desc_idx] = view->handle.cpu_handle; 106 d3d12_batch_reference_sampler_view(batch, view); 107 108 D3D12_RESOURCE_STATES state = (stage == PIPE_SHADER_FRAGMENT) ? 109 D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE : 110 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; 111 if (view->base.texture->target == PIPE_BUFFER) { 112 d3d12_transition_resource_state(ctx, d3d12_resource(view->base.texture), 113 state, 114 D3D12_BIND_INVALIDATE_NONE); 115 } else { 116 d3d12_transition_subresources_state(ctx, d3d12_resource(view->base.texture), 117 view->base.u.tex.first_level, view->mip_levels, 118 view->base.u.tex.first_layer, view->array_size, 119 d3d12_get_format_start_plane(view->base.format), 120 d3d12_get_format_num_planes(view->base.format), 121 state, 122 D3D12_BIND_INVALIDATE_NONE); 123 } 124 } else { 125 descs[desc_idx] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle; 126 } 127 } 128 129 d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->end_srv_binding - shader->begin_srv_binding); 130 131 return table_start.gpu_handle; 132} 133 134static D3D12_GPU_DESCRIPTOR_HANDLE 135fill_sampler_descriptors(struct d3d12_context *ctx, 136 const struct d3d12_shader_selector *shader_sel, 137 unsigned stage) 138{ 139 const struct d3d12_shader *shader = shader_sel->current; 140 struct d3d12_batch *batch = d3d12_current_batch(ctx); 141 D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 142 struct d3d12_descriptor_handle table_start; 143 144 d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start); 145 146 for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++) 147 { 148 struct d3d12_sampler_state *sampler; 149 150 if (i == shader->pstipple_binding) { 151 sampler = ctx->pstipple.sampler_cso; 152 } else { 153 sampler = ctx->samplers[stage][i]; 154 } 155 156 unsigned desc_idx = i - shader->begin_srv_binding; 157 if (sampler != NULL) { 158 if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad) 159 descs[desc_idx] = sampler->handle_without_shadow.cpu_handle; 160 else 161 descs[desc_idx] = sampler->handle.cpu_handle; 162 } else 163 descs[desc_idx] = ctx->null_sampler.cpu_handle; 164 } 165 166 d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding); 167 return table_start.gpu_handle; 168} 169 170static unsigned 171fill_state_vars(struct d3d12_context *ctx, 172 const struct pipe_draw_info *dinfo, 173 const struct pipe_draw_start_count_bias *draw, 174 struct d3d12_shader *shader, 175 uint32_t *values) 176{ 177 unsigned size = 0; 178 179 for (unsigned j = 0; j < shader->num_state_vars; ++j) { 180 uint32_t *ptr = values + size; 181 182 switch (shader->state_vars[j].var) { 183 case D3D12_STATE_VAR_Y_FLIP: 184 ptr[0] = fui(ctx->flip_y); 185 size += 4; 186 break; 187 case D3D12_STATE_VAR_PT_SPRITE: 188 ptr[0] = fui(1.0 / ctx->viewports[0].Width); 189 ptr[1] = fui(1.0 / ctx->viewports[0].Height); 190 ptr[2] = fui(ctx->gfx_pipeline_state.rast->base.point_size); 191 ptr[3] = fui(D3D12_MAX_POINT_SIZE); 192 size += 4; 193 break; 194 case D3D12_STATE_VAR_FIRST_VERTEX: 195 ptr[0] = dinfo->index_size ? draw->index_bias : draw->start; 196 size += 4; 197 break; 198 case D3D12_STATE_VAR_DEPTH_TRANSFORM: 199 ptr[0] = fui(2.0f * ctx->viewport_states[0].scale[2]); 200 ptr[1] = fui(ctx->viewport_states[0].translate[2] - ctx->viewport_states[0].scale[2]); 201 size += 4; 202 break; 203 default: 204 unreachable("unknown state variable"); 205 } 206 } 207 208 return size; 209} 210 211static bool 212check_descriptors_left(struct d3d12_context *ctx) 213{ 214 struct d3d12_batch *batch = d3d12_current_batch(ctx); 215 unsigned needed_descs = 0; 216 217 for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 218 struct d3d12_shader_selector *shader = ctx->gfx_stages[i]; 219 220 if (!shader) 221 continue; 222 223 needed_descs += shader->current->num_cb_bindings; 224 needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; 225 } 226 227 if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs) 228 return false; 229 230 needed_descs = 0; 231 for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 232 struct d3d12_shader_selector *shader = ctx->gfx_stages[i]; 233 234 if (!shader) 235 continue; 236 237 needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; 238 } 239 240 if (d3d12_descriptor_heap_get_remaining_handles(batch->sampler_heap) < needed_descs) 241 return false; 242 243 return true; 244} 245 246#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 3) 247 248static unsigned 249update_graphics_root_parameters(struct d3d12_context *ctx, 250 const struct pipe_draw_info *dinfo, 251 const struct pipe_draw_start_count_bias *draw, 252 D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES], 253 int root_desc_indices[MAX_DESCRIPTOR_TABLES]) 254{ 255 unsigned num_params = 0; 256 unsigned num_root_desciptors = 0; 257 258 for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 259 if (!ctx->gfx_stages[i]) 260 continue; 261 262 struct d3d12_shader_selector *shader_sel = ctx->gfx_stages[i]; 263 struct d3d12_shader *shader = shader_sel->current; 264 uint64_t dirty = ctx->shader_dirty[i]; 265 assert(shader); 266 267 if (shader->num_cb_bindings > 0) { 268 if (dirty & D3D12_SHADER_DIRTY_CONSTBUF) { 269 assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES); 270 root_desc_tables[num_root_desciptors] = fill_cbv_descriptors(ctx, shader, i); 271 root_desc_indices[num_root_desciptors++] = num_params; 272 } 273 num_params++; 274 } 275 if (shader->end_srv_binding > 0) { 276 if (dirty & D3D12_SHADER_DIRTY_SAMPLER_VIEWS) { 277 assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES); 278 root_desc_tables[num_root_desciptors] = fill_srv_descriptors(ctx, shader, i); 279 root_desc_indices[num_root_desciptors++] = num_params; 280 } 281 num_params++; 282 if (dirty & D3D12_SHADER_DIRTY_SAMPLERS) { 283 assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES); 284 root_desc_tables[num_root_desciptors] = fill_sampler_descriptors(ctx, shader_sel, i); 285 root_desc_indices[num_root_desciptors++] = num_params; 286 } 287 num_params++; 288 } 289 /* TODO Don't always update state vars */ 290 if (shader->num_state_vars > 0) { 291 uint32_t constants[D3D12_MAX_STATE_VARS * 4]; 292 unsigned size = fill_state_vars(ctx, dinfo, draw, shader, constants); 293 ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0); 294 num_params++; 295 } 296 } 297 return num_root_desciptors; 298} 299 300static bool 301validate_stream_output_targets(struct d3d12_context *ctx) 302{ 303 unsigned factor = 0; 304 305 if (ctx->gfx_pipeline_state.num_so_targets && 306 ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]) 307 factor = ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]->key.gs.stream_output_factor; 308 309 if (factor > 1) 310 return d3d12_enable_fake_so_buffers(ctx, factor); 311 else 312 return d3d12_disable_fake_so_buffers(ctx); 313} 314 315static D3D_PRIMITIVE_TOPOLOGY 316topology(enum pipe_prim_type prim_type) 317{ 318 switch (prim_type) { 319 case PIPE_PRIM_POINTS: 320 return D3D_PRIMITIVE_TOPOLOGY_POINTLIST; 321 322 case PIPE_PRIM_LINES: 323 return D3D_PRIMITIVE_TOPOLOGY_LINELIST; 324 325 case PIPE_PRIM_LINE_STRIP: 326 return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; 327 328 case PIPE_PRIM_TRIANGLES: 329 return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; 330 331 case PIPE_PRIM_TRIANGLE_STRIP: 332 return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; 333 334 case PIPE_PRIM_LINES_ADJACENCY: 335 return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; 336 337 case PIPE_PRIM_LINE_STRIP_ADJACENCY: 338 return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ; 339 340 case PIPE_PRIM_TRIANGLES_ADJACENCY: 341 return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; 342 343 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 344 return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ; 345 346/* 347 case PIPE_PRIM_PATCHES: 348 return D3D_PRIMITIVE_TOPOLOGY_PATCHLIST; 349*/ 350 351 case PIPE_PRIM_QUADS: 352 case PIPE_PRIM_QUAD_STRIP: 353 return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; /* HACK: this is just wrong! */ 354 355 default: 356 debug_printf("pipe_prim_type: %s\n", u_prim_name(prim_type)); 357 unreachable("unexpected enum pipe_prim_type"); 358 } 359} 360 361static DXGI_FORMAT 362ib_format(unsigned index_size) 363{ 364 switch (index_size) { 365 case 1: return DXGI_FORMAT_R8_UINT; 366 case 2: return DXGI_FORMAT_R16_UINT; 367 case 4: return DXGI_FORMAT_R32_UINT; 368 369 default: 370 unreachable("unexpected index-buffer size"); 371 } 372} 373 374static void 375twoface_emulation(struct d3d12_context *ctx, 376 struct d3d12_rasterizer_state *rast, 377 const struct pipe_draw_info *dinfo, 378 const struct pipe_draw_start_count_bias *draw) 379{ 380 /* draw backfaces */ 381 ctx->base.bind_rasterizer_state(&ctx->base, rast->twoface_back); 382 d3d12_draw_vbo(&ctx->base, dinfo, 0, NULL, draw, 1); 383 384 /* restore real state */ 385 ctx->base.bind_rasterizer_state(&ctx->base, rast); 386} 387 388static void 389transition_surface_subresources_state(struct d3d12_context *ctx, 390 struct pipe_surface *psurf, 391 struct pipe_resource *pres, 392 D3D12_RESOURCE_STATES state) 393{ 394 struct d3d12_resource *res = d3d12_resource(pres); 395 unsigned start_layer, num_layers; 396 if (!d3d12_subresource_id_uses_layer(res->base.target)) { 397 start_layer = 0; 398 num_layers = 1; 399 } else { 400 start_layer = psurf->u.tex.first_layer; 401 num_layers = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1; 402 } 403 d3d12_transition_subresources_state(ctx, res, 404 psurf->u.tex.level, 1, 405 start_layer, num_layers, 406 d3d12_get_format_start_plane(psurf->format), 407 d3d12_get_format_num_planes(psurf->format), 408 state, 409 D3D12_BIND_INVALIDATE_FULL); 410} 411 412static bool 413prim_supported(enum pipe_prim_type prim_type) 414{ 415 switch (prim_type) { 416 case PIPE_PRIM_POINTS: 417 case PIPE_PRIM_LINES: 418 case PIPE_PRIM_LINE_STRIP: 419 case PIPE_PRIM_TRIANGLES: 420 case PIPE_PRIM_TRIANGLE_STRIP: 421 case PIPE_PRIM_LINES_ADJACENCY: 422 case PIPE_PRIM_LINE_STRIP_ADJACENCY: 423 case PIPE_PRIM_TRIANGLES_ADJACENCY: 424 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 425 return true; 426 427 default: 428 return false; 429 } 430} 431 432static inline struct d3d12_shader_selector * 433d3d12_last_vertex_stage(struct d3d12_context *ctx) 434{ 435 struct d3d12_shader_selector *sel = ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 436 if (!sel || sel->is_gs_variant) 437 sel = ctx->gfx_stages[PIPE_SHADER_VERTEX]; 438 return sel; 439} 440 441void 442d3d12_draw_vbo(struct pipe_context *pctx, 443 const struct pipe_draw_info *dinfo, 444 unsigned drawid_offset, 445 const struct pipe_draw_indirect_info *indirect, 446 const struct pipe_draw_start_count_bias *draws, 447 unsigned num_draws) 448{ 449 if (num_draws > 1) { 450 util_draw_multi(pctx, dinfo, drawid_offset, indirect, draws, num_draws); 451 return; 452 } 453 454 if (!indirect && (!draws[0].count || !dinfo->instance_count)) 455 return; 456 457 struct d3d12_context *ctx = d3d12_context(pctx); 458 struct d3d12_screen *screen = d3d12_screen(pctx->screen); 459 struct d3d12_batch *batch; 460 struct pipe_resource *index_buffer = NULL; 461 unsigned index_offset = 0; 462 enum d3d12_surface_conversion_mode conversion_modes[PIPE_MAX_COLOR_BUFS] = {}; 463 464 if (!prim_supported((enum pipe_prim_type)dinfo->mode) || 465 dinfo->index_size == 1 || 466 (dinfo->primitive_restart && dinfo->restart_index != 0xffff && 467 dinfo->restart_index != 0xffffffff)) { 468 469 if (!dinfo->primitive_restart && 470 !u_trim_pipe_prim((enum pipe_prim_type)dinfo->mode, (unsigned *)&draws[0].count)) 471 return; 472 473 ctx->initial_api_prim = (enum pipe_prim_type)dinfo->mode; 474 util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base); 475 util_primconvert_draw_vbo(ctx->primconvert, dinfo, drawid_offset, indirect, draws, num_draws); 476 return; 477 } 478 479 for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 480 if (ctx->fb.cbufs[i]) { 481 struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 482 conversion_modes[i] = d3d12_surface_update_pre_draw(surface, d3d12_rtv_format(ctx, i)); 483 if (conversion_modes[i] != D3D12_SURFACE_CONVERSION_NONE) 484 ctx->cmdlist_dirty |= D3D12_DIRTY_FRAMEBUFFER; 485 } 486 } 487 488 struct d3d12_rasterizer_state *rast = ctx->gfx_pipeline_state.rast; 489 if (rast->twoface_back) { 490 enum pipe_prim_type saved_mode = ctx->initial_api_prim; 491 twoface_emulation(ctx, rast, dinfo, &draws[0]); 492 ctx->initial_api_prim = saved_mode; 493 } 494 495 if (ctx->pstipple.enabled) 496 ctx->shader_dirty[PIPE_SHADER_FRAGMENT] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS | 497 D3D12_SHADER_DIRTY_SAMPLERS; 498 499 /* this should *really* be fixed at a higher level than here! */ 500 enum pipe_prim_type reduced_prim = u_reduced_prim((enum pipe_prim_type)dinfo->mode); 501 if (reduced_prim == PIPE_PRIM_TRIANGLES && 502 ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_FRONT_AND_BACK) 503 return; 504 505 if (ctx->gfx_pipeline_state.prim_type != dinfo->mode) { 506 ctx->gfx_pipeline_state.prim_type = (enum pipe_prim_type)dinfo->mode; 507 ctx->state_dirty |= D3D12_DIRTY_PRIM_MODE; 508 } 509 510 d3d12_select_shader_variants(ctx, dinfo); 511 d3d12_validate_queries(ctx); 512 for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 513 struct d3d12_shader *shader = ctx->gfx_stages[i] ? ctx->gfx_stages[i]->current : NULL; 514 if (ctx->gfx_pipeline_state.stages[i] != shader) { 515 ctx->gfx_pipeline_state.stages[i] = shader; 516 ctx->state_dirty |= D3D12_DIRTY_SHADER; 517 } 518 } 519 520 /* Reset to an invalid value after it's been used */ 521 ctx->initial_api_prim = PIPE_PRIM_MAX; 522 523 /* Copy the stream output info from the current vertex/geometry shader */ 524 if (ctx->state_dirty & D3D12_DIRTY_SHADER) { 525 struct d3d12_shader_selector *sel = d3d12_last_vertex_stage(ctx); 526 if (sel) { 527 ctx->gfx_pipeline_state.so_info = sel->so_info; 528 } else { 529 memset(&ctx->gfx_pipeline_state.so_info, 0, sizeof(sel->so_info)); 530 } 531 } 532 if (!validate_stream_output_targets(ctx)) { 533 debug_printf("validate_stream_output_targets() failed\n"); 534 return; 535 } 536 537 D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ib_strip_cut_value = 538 D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; 539 if (dinfo->index_size > 0) { 540 assert(dinfo->index_size != 1); 541 542 if (dinfo->has_user_indices) { 543 if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer, 544 &index_offset, 4)) { 545 debug_printf("util_upload_index_buffer() failed\n"); 546 return; 547 } 548 } else { 549 index_buffer = dinfo->index.resource; 550 } 551 552 if (dinfo->primitive_restart) { 553 assert(dinfo->restart_index == 0xffff || 554 dinfo->restart_index == 0xffffffff); 555 ib_strip_cut_value = dinfo->restart_index == 0xffff ? 556 D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF : 557 D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF; 558 } 559 } 560 561 if (ctx->gfx_pipeline_state.ib_strip_cut_value != ib_strip_cut_value) { 562 ctx->gfx_pipeline_state.ib_strip_cut_value = ib_strip_cut_value; 563 ctx->state_dirty |= D3D12_DIRTY_STRIP_CUT_VALUE; 564 } 565 566 if (!ctx->gfx_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_SHADER) { 567 ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx); 568 if (ctx->gfx_pipeline_state.root_signature != root_signature) { 569 ctx->gfx_pipeline_state.root_signature = root_signature; 570 ctx->state_dirty |= D3D12_DIRTY_ROOT_SIGNATURE; 571 for (int i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) 572 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_ALL; 573 } 574 } 575 576 if (!ctx->current_pso || ctx->state_dirty & D3D12_DIRTY_PSO) { 577 ctx->current_pso = d3d12_get_gfx_pipeline_state(ctx); 578 assert(ctx->current_pso); 579 } 580 581 ctx->cmdlist_dirty |= ctx->state_dirty; 582 583 if (!check_descriptors_left(ctx)) 584 d3d12_flush_cmdlist(ctx); 585 batch = d3d12_current_batch(ctx); 586 587 if (ctx->cmdlist_dirty & D3D12_DIRTY_ROOT_SIGNATURE) { 588 d3d12_batch_reference_object(batch, ctx->gfx_pipeline_state.root_signature); 589 ctx->cmdlist->SetGraphicsRootSignature(ctx->gfx_pipeline_state.root_signature); 590 } 591 592 if (ctx->cmdlist_dirty & D3D12_DIRTY_PSO) { 593 assert(ctx->current_pso); 594 d3d12_batch_reference_object(batch, ctx->current_pso); 595 ctx->cmdlist->SetPipelineState(ctx->current_pso); 596 } 597 598 D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES]; 599 int root_desc_indices[MAX_DESCRIPTOR_TABLES]; 600 unsigned num_root_desciptors = update_graphics_root_parameters(ctx, dinfo, &draws[0], root_desc_tables, root_desc_indices); 601 602 bool need_zero_one_depth_range = d3d12_need_zero_one_depth_range(ctx); 603 if (need_zero_one_depth_range != ctx->need_zero_one_depth_range) { 604 ctx->cmdlist_dirty |= D3D12_DIRTY_VIEWPORT; 605 ctx->need_zero_one_depth_range = need_zero_one_depth_range; 606 } 607 608 if (ctx->cmdlist_dirty & D3D12_DIRTY_VIEWPORT) { 609 if (ctx->need_zero_one_depth_range) { 610 D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS]; 611 for (unsigned i = 0; i < ctx->num_viewports; ++i) { 612 viewports[i] = ctx->viewports[i]; 613 viewports[i].MinDepth = 0.0f; 614 viewports[i].MaxDepth = 1.0f; 615 } 616 ctx->cmdlist->RSSetViewports(ctx->num_viewports, viewports); 617 } else 618 ctx->cmdlist->RSSetViewports(ctx->num_viewports, ctx->viewports); 619 } 620 621 if (ctx->cmdlist_dirty & D3D12_DIRTY_SCISSOR) { 622 if (ctx->gfx_pipeline_state.rast->base.scissor && ctx->num_viewports > 0) 623 ctx->cmdlist->RSSetScissorRects(ctx->num_viewports, ctx->scissors); 624 else 625 ctx->cmdlist->RSSetScissorRects(1, &MAX_SCISSOR); 626 } 627 628 if (ctx->cmdlist_dirty & D3D12_DIRTY_BLEND_COLOR) { 629 unsigned blend_factor_flags = ctx->gfx_pipeline_state.blend->blend_factor_flags; 630 if (blend_factor_flags & (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ANY)) { 631 ctx->cmdlist->OMSetBlendFactor(ctx->blend_factor); 632 } else if (blend_factor_flags & D3D12_BLEND_FACTOR_ALPHA) { 633 float alpha_const[4] = { ctx->blend_factor[3], ctx->blend_factor[3], 634 ctx->blend_factor[3], ctx->blend_factor[3] }; 635 ctx->cmdlist->OMSetBlendFactor(alpha_const); 636 } 637 } 638 639 if (ctx->cmdlist_dirty & D3D12_DIRTY_STENCIL_REF) 640 ctx->cmdlist->OMSetStencilRef(ctx->stencil_ref.ref_value[0]); 641 642 if (ctx->cmdlist_dirty & D3D12_DIRTY_PRIM_MODE) 643 ctx->cmdlist->IASetPrimitiveTopology(topology((enum pipe_prim_type)dinfo->mode)); 644 645 for (unsigned i = 0; i < ctx->num_vbs; ++i) { 646 if (ctx->vbs[i].buffer.resource) { 647 struct d3d12_resource *res = d3d12_resource(ctx->vbs[i].buffer.resource); 648 d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE); 649 if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS) 650 d3d12_batch_reference_resource(batch, res); 651 } 652 } 653 if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS) 654 ctx->cmdlist->IASetVertexBuffers(0, ctx->num_vbs, ctx->vbvs); 655 656 if (index_buffer) { 657 D3D12_INDEX_BUFFER_VIEW ibv; 658 struct d3d12_resource *res = d3d12_resource(index_buffer); 659 ibv.BufferLocation = d3d12_resource_gpu_virtual_address(res) + index_offset; 660 ibv.SizeInBytes = res->base.width0 - index_offset; 661 ibv.Format = ib_format(dinfo->index_size); 662 d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_INDEX_BUFFER, D3D12_BIND_INVALIDATE_NONE); 663 if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER || 664 memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) { 665 ctx->ibv = ibv; 666 d3d12_batch_reference_resource(batch, res); 667 ctx->cmdlist->IASetIndexBuffer(&ibv); 668 } 669 670 if (dinfo->has_user_indices) 671 pipe_resource_reference(&index_buffer, NULL); 672 } 673 674 if (ctx->cmdlist_dirty & D3D12_DIRTY_FRAMEBUFFER) { 675 D3D12_CPU_DESCRIPTOR_HANDLE render_targets[PIPE_MAX_COLOR_BUFS] = {}; 676 D3D12_CPU_DESCRIPTOR_HANDLE *depth_desc = NULL, tmp_desc; 677 for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 678 if (ctx->fb.cbufs[i]) { 679 struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 680 render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i]); 681 d3d12_batch_reference_surface_texture(batch, surface); 682 } else 683 render_targets[i] = screen->null_rtv.cpu_handle; 684 } 685 if (ctx->fb.zsbuf) { 686 struct d3d12_surface *surface = d3d12_surface(ctx->fb.zsbuf); 687 tmp_desc = surface->desc_handle.cpu_handle; 688 d3d12_batch_reference_surface_texture(batch, surface); 689 depth_desc = &tmp_desc; 690 } 691 ctx->cmdlist->OMSetRenderTargets(ctx->fb.nr_cbufs, render_targets, FALSE, depth_desc); 692 } 693 694 struct pipe_stream_output_target **so_targets = ctx->fake_so_buffer_factor ? ctx->fake_so_targets 695 : ctx->so_targets; 696 D3D12_STREAM_OUTPUT_BUFFER_VIEW *so_buffer_views = ctx->fake_so_buffer_factor ? ctx->fake_so_buffer_views 697 : ctx->so_buffer_views; 698 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 699 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)so_targets[i]; 700 701 if (!target) 702 continue; 703 704 struct d3d12_resource *so_buffer = d3d12_resource(target->base.buffer); 705 struct d3d12_resource *fill_buffer = d3d12_resource(target->fill_buffer); 706 707 d3d12_resource_make_writeable(pctx, target->base.buffer); 708 709 if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) { 710 d3d12_batch_reference_resource(batch, so_buffer); 711 d3d12_batch_reference_resource(batch, fill_buffer); 712 } 713 714 d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE); 715 d3d12_transition_resource_state(ctx, fill_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE); 716 } 717 if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) 718 ctx->cmdlist->SOSetTargets(0, 4, so_buffer_views); 719 720 for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 721 struct pipe_surface *psurf = ctx->fb.cbufs[i]; 722 if (!psurf) 723 continue; 724 725 struct pipe_resource *pres = conversion_modes[i] == D3D12_SURFACE_CONVERSION_BGRA_UINT ? 726 d3d12_surface(psurf)->rgba_texture : psurf->texture; 727 transition_surface_subresources_state(ctx, psurf, pres, 728 D3D12_RESOURCE_STATE_RENDER_TARGET); 729 } 730 if (ctx->fb.zsbuf) { 731 struct pipe_surface *psurf = ctx->fb.zsbuf; 732 transition_surface_subresources_state(ctx, psurf, psurf->texture, 733 D3D12_RESOURCE_STATE_DEPTH_WRITE); 734 } 735 736 d3d12_apply_resource_states(ctx); 737 738 for (unsigned i = 0; i < num_root_desciptors; ++i) 739 ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]); 740 741 if (dinfo->index_size > 0) 742 ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count, 743 draws[0].start, draws[0].index_bias, 744 dinfo->start_instance); 745 else 746 ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count, 747 draws[0].start, dinfo->start_instance); 748 749 ctx->state_dirty = 0; 750 751 if (index_buffer) 752 ctx->cmdlist_dirty = 0; 753 else 754 ctx->cmdlist_dirty &= D3D12_DIRTY_INDEX_BUFFER; 755 756 for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) 757 ctx->shader_dirty[i] = 0; 758 759 for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 760 if (ctx->fb.cbufs[i]) { 761 struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 762 d3d12_surface_update_post_draw(surface, conversion_modes[i]); 763 } 764 } 765} 766