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_blit.h" 25#include "d3d12_cmd_signature.h" 26#include "d3d12_context.h" 27#include "d3d12_compiler.h" 28#include "d3d12_compute_transforms.h" 29#include "d3d12_debug.h" 30#include "d3d12_fence.h" 31#include "d3d12_format.h" 32#include "d3d12_query.h" 33#include "d3d12_resource.h" 34#include "d3d12_root_signature.h" 35#include "d3d12_screen.h" 36#include "d3d12_surface.h" 37#ifdef HAVE_GALLIUM_D3D12_VIDEO 38#include "d3d12_video_dec.h" 39#include "d3d12_video_enc.h" 40#include "d3d12_video_proc.h" 41#include "d3d12_video_buffer.h" 42#endif 43#include "util/u_atomic.h" 44#include "util/u_blitter.h" 45#include "util/u_dual_blend.h" 46#include "util/u_framebuffer.h" 47#include "util/u_helpers.h" 48#include "util/u_inlines.h" 49#include "util/u_memory.h" 50#include "util/u_upload_mgr.h" 51#include "util/u_pstipple.h" 52#include "util/u_dl.h" 53#include "nir_to_dxil.h" 54 55#include <dxguids/dxguids.h> 56 57extern "C" { 58#include "indices/u_primconvert.h" 59} 60 61#include <string.h> 62 63#ifdef _WIN32 64#include "dxil_validator.h" 65#endif 66 67static void 68d3d12_context_destroy(struct pipe_context *pctx) 69{ 70 struct d3d12_context *ctx = d3d12_context(pctx); 71 72 struct d3d12_screen *screen = d3d12_screen(pctx->screen); 73 mtx_lock(&screen->submit_mutex); 74 list_del(&ctx->context_list_entry); 75 mtx_unlock(&screen->submit_mutex); 76 77#ifdef _WIN32 78 if (ctx->dxil_validator) 79 dxil_destroy_validator(ctx->dxil_validator); 80#endif 81 82 if (ctx->timestamp_query) 83 pctx->destroy_query(pctx, ctx->timestamp_query); 84 85 util_unreference_framebuffer_state(&ctx->fb); 86 util_blitter_destroy(ctx->blitter); 87 d3d12_end_batch(ctx, d3d12_current_batch(ctx)); 88 for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) 89 d3d12_destroy_batch(ctx, &ctx->batches[i]); 90 ctx->cmdlist->Release(); 91 d3d12_descriptor_pool_free(ctx->sampler_pool); 92 util_primconvert_destroy(ctx->primconvert); 93 slab_destroy_child(&ctx->transfer_pool); 94 slab_destroy_child(&ctx->transfer_pool_unsync); 95 d3d12_gs_variant_cache_destroy(ctx); 96 d3d12_gfx_pipeline_state_cache_destroy(ctx); 97 d3d12_compute_pipeline_state_cache_destroy(ctx); 98 d3d12_root_signature_cache_destroy(ctx); 99 d3d12_cmd_signature_cache_destroy(ctx); 100 d3d12_compute_transform_cache_destroy(ctx); 101 d3d12_context_state_table_destroy(ctx); 102 pipe_resource_reference(&ctx->pstipple.texture, nullptr); 103 pipe_sampler_view_reference(&ctx->pstipple.sampler_view, nullptr); 104 util_dynarray_fini(&ctx->recently_destroyed_bos); 105 FREE(ctx->pstipple.sampler_cso); 106 107 u_suballocator_destroy(&ctx->query_allocator); 108 109 if (pctx->stream_uploader) 110 u_upload_destroy(pctx->stream_uploader); 111 if (pctx->const_uploader) 112 u_upload_destroy(pctx->const_uploader); 113 114 FREE(ctx); 115} 116 117static void * 118d3d12_create_vertex_elements_state(struct pipe_context *pctx, 119 unsigned num_elements, 120 const struct pipe_vertex_element *elements) 121{ 122 struct d3d12_vertex_elements_state *cso = CALLOC_STRUCT(d3d12_vertex_elements_state); 123 if (!cso) 124 return NULL; 125 126 for (unsigned i = 0; i < num_elements; ++i) { 127 cso->elements[i].SemanticName = "TEXCOORD"; 128 cso->elements[i].SemanticIndex = i; 129 130 enum pipe_format format_helper = 131 d3d12_emulated_vtx_format((enum pipe_format)elements[i].src_format); 132 bool needs_emulation = format_helper != elements[i].src_format; 133 cso->needs_format_emulation |= needs_emulation; 134 cso->format_conversion[i] = 135 needs_emulation ? (enum pipe_format)elements[i].src_format : PIPE_FORMAT_NONE; 136 137 cso->elements[i].Format = d3d12_get_format(format_helper); 138 assert(cso->elements[i].Format != DXGI_FORMAT_UNKNOWN); 139 cso->elements[i].InputSlot = elements[i].vertex_buffer_index; 140 cso->elements[i].AlignedByteOffset = elements[i].src_offset; 141 142 if (elements[i].instance_divisor) { 143 cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA; 144 cso->elements[i].InstanceDataStepRate = elements[i].instance_divisor; 145 } else { 146 cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; 147 cso->elements[i].InstanceDataStepRate = 0; 148 } 149 } 150 151 cso->num_elements = num_elements; 152 return cso; 153} 154 155static void 156d3d12_bind_vertex_elements_state(struct pipe_context *pctx, 157 void *ve) 158{ 159 struct d3d12_context *ctx = d3d12_context(pctx); 160 ctx->gfx_pipeline_state.ves = (struct d3d12_vertex_elements_state *)ve; 161 ctx->state_dirty |= D3D12_DIRTY_VERTEX_ELEMENTS; 162} 163 164static void 165d3d12_delete_vertex_elements_state(struct pipe_context *pctx, 166 void *ve) 167{ 168 FREE(ve); 169} 170 171static D3D12_BLEND 172blend_factor_rgb(enum pipe_blendfactor factor) 173{ 174 switch (factor) { 175 case PIPE_BLENDFACTOR_ZERO: return D3D12_BLEND_ZERO; 176 case PIPE_BLENDFACTOR_ONE: return D3D12_BLEND_ONE; 177 case PIPE_BLENDFACTOR_SRC_COLOR: return D3D12_BLEND_SRC_COLOR; 178 case PIPE_BLENDFACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA; 179 case PIPE_BLENDFACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA; 180 case PIPE_BLENDFACTOR_DST_COLOR: return D3D12_BLEND_DEST_COLOR; 181 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT; 182 case PIPE_BLENDFACTOR_CONST_COLOR: return D3D12_BLEND_BLEND_FACTOR; 183 case PIPE_BLENDFACTOR_SRC1_COLOR: return D3D12_BLEND_SRC1_COLOR; 184 case PIPE_BLENDFACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA; 185 case PIPE_BLENDFACTOR_INV_SRC_COLOR: return D3D12_BLEND_INV_SRC_COLOR; 186 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA; 187 case PIPE_BLENDFACTOR_INV_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA; 188 case PIPE_BLENDFACTOR_INV_DST_COLOR: return D3D12_BLEND_INV_DEST_COLOR; 189 case PIPE_BLENDFACTOR_INV_CONST_COLOR: return D3D12_BLEND_INV_BLEND_FACTOR; 190 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return D3D12_BLEND_INV_SRC1_COLOR; 191 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA; 192 case PIPE_BLENDFACTOR_CONST_ALPHA: return D3D12_BLEND_BLEND_FACTOR; /* Doesn't exist in D3D12 */ 193 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return D3D12_BLEND_INV_BLEND_FACTOR; /* Doesn't exist in D3D12 */ 194 } 195 unreachable("unexpected blend factor"); 196} 197 198static D3D12_BLEND 199blend_factor_alpha(enum pipe_blendfactor factor) 200{ 201 switch (factor) { 202 case PIPE_BLENDFACTOR_ZERO: return D3D12_BLEND_ZERO; 203 case PIPE_BLENDFACTOR_ONE: return D3D12_BLEND_ONE; 204 case PIPE_BLENDFACTOR_SRC_COLOR: 205 case PIPE_BLENDFACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA; 206 case PIPE_BLENDFACTOR_DST_COLOR: 207 case PIPE_BLENDFACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA; 208 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT; 209 case PIPE_BLENDFACTOR_CONST_COLOR: 210 case PIPE_BLENDFACTOR_CONST_ALPHA: return D3D12_BLEND_BLEND_FACTOR; 211 case PIPE_BLENDFACTOR_SRC1_COLOR: 212 case PIPE_BLENDFACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA; 213 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 214 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA; 215 case PIPE_BLENDFACTOR_INV_DST_COLOR: 216 case PIPE_BLENDFACTOR_INV_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA; 217 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 218 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA; 219 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 220 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return D3D12_BLEND_INV_BLEND_FACTOR; 221 } 222 unreachable("unexpected blend factor"); 223} 224 225static unsigned 226need_blend_factor_rgb(enum pipe_blendfactor factor) 227{ 228 switch (factor) { 229 case PIPE_BLENDFACTOR_CONST_COLOR: 230 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 231 return D3D12_BLEND_FACTOR_COLOR; 232 case PIPE_BLENDFACTOR_CONST_ALPHA: 233 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 234 return D3D12_BLEND_FACTOR_ALPHA; 235 236 default: 237 return D3D12_BLEND_FACTOR_NONE; 238 } 239} 240 241static unsigned 242need_blend_factor_alpha(enum pipe_blendfactor factor) 243{ 244 switch (factor) { 245 case PIPE_BLENDFACTOR_CONST_COLOR: 246 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 247 case PIPE_BLENDFACTOR_CONST_ALPHA: 248 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 249 return D3D12_BLEND_FACTOR_ANY; 250 251 default: 252 return D3D12_BLEND_FACTOR_NONE; 253 } 254} 255 256static D3D12_BLEND_OP 257blend_op(enum pipe_blend_func func) 258{ 259 switch (func) { 260 case PIPE_BLEND_ADD: return D3D12_BLEND_OP_ADD; 261 case PIPE_BLEND_SUBTRACT: return D3D12_BLEND_OP_SUBTRACT; 262 case PIPE_BLEND_REVERSE_SUBTRACT: return D3D12_BLEND_OP_REV_SUBTRACT; 263 case PIPE_BLEND_MIN: return D3D12_BLEND_OP_MIN; 264 case PIPE_BLEND_MAX: return D3D12_BLEND_OP_MAX; 265 } 266 unreachable("unexpected blend function"); 267} 268 269static D3D12_COMPARISON_FUNC 270compare_op(enum pipe_compare_func op) 271{ 272 switch (op) { 273 case PIPE_FUNC_NEVER: return D3D12_COMPARISON_FUNC_NEVER; 274 case PIPE_FUNC_LESS: return D3D12_COMPARISON_FUNC_LESS; 275 case PIPE_FUNC_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL; 276 case PIPE_FUNC_LEQUAL: return D3D12_COMPARISON_FUNC_LESS_EQUAL; 277 case PIPE_FUNC_GREATER: return D3D12_COMPARISON_FUNC_GREATER; 278 case PIPE_FUNC_NOTEQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL; 279 case PIPE_FUNC_GEQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL; 280 case PIPE_FUNC_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS; 281 } 282 unreachable("unexpected compare"); 283} 284 285static D3D12_LOGIC_OP 286logic_op(enum pipe_logicop func) 287{ 288 switch (func) { 289 case PIPE_LOGICOP_CLEAR: return D3D12_LOGIC_OP_CLEAR; 290 case PIPE_LOGICOP_NOR: return D3D12_LOGIC_OP_NOR; 291 case PIPE_LOGICOP_AND_INVERTED: return D3D12_LOGIC_OP_AND_INVERTED; 292 case PIPE_LOGICOP_COPY_INVERTED: return D3D12_LOGIC_OP_COPY_INVERTED; 293 case PIPE_LOGICOP_AND_REVERSE: return D3D12_LOGIC_OP_AND_REVERSE; 294 case PIPE_LOGICOP_INVERT: return D3D12_LOGIC_OP_INVERT; 295 case PIPE_LOGICOP_XOR: return D3D12_LOGIC_OP_XOR; 296 case PIPE_LOGICOP_NAND: return D3D12_LOGIC_OP_NAND; 297 case PIPE_LOGICOP_AND: return D3D12_LOGIC_OP_AND; 298 case PIPE_LOGICOP_EQUIV: return D3D12_LOGIC_OP_EQUIV; 299 case PIPE_LOGICOP_NOOP: return D3D12_LOGIC_OP_NOOP; 300 case PIPE_LOGICOP_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED; 301 case PIPE_LOGICOP_COPY: return D3D12_LOGIC_OP_COPY; 302 case PIPE_LOGICOP_OR_REVERSE: return D3D12_LOGIC_OP_OR_REVERSE; 303 case PIPE_LOGICOP_OR: return D3D12_LOGIC_OP_OR; 304 case PIPE_LOGICOP_SET: return D3D12_LOGIC_OP_SET; 305 } 306 unreachable("unexpected logicop function"); 307} 308 309static UINT8 310color_write_mask(unsigned colormask) 311{ 312 UINT8 mask = 0; 313 314 if (colormask & PIPE_MASK_R) 315 mask |= D3D12_COLOR_WRITE_ENABLE_RED; 316 if (colormask & PIPE_MASK_G) 317 mask |= D3D12_COLOR_WRITE_ENABLE_GREEN; 318 if (colormask & PIPE_MASK_B) 319 mask |= D3D12_COLOR_WRITE_ENABLE_BLUE; 320 if (colormask & PIPE_MASK_A) 321 mask |= D3D12_COLOR_WRITE_ENABLE_ALPHA; 322 323 return mask; 324} 325 326static void * 327d3d12_create_blend_state(struct pipe_context *pctx, 328 const struct pipe_blend_state *blend_state) 329{ 330 struct d3d12_blend_state *state = CALLOC_STRUCT(d3d12_blend_state); 331 if (!state) 332 return NULL; 333 334 if (blend_state->logicop_enable) { 335 state->desc.RenderTarget[0].LogicOpEnable = TRUE; 336 state->desc.RenderTarget[0].LogicOp = logic_op((pipe_logicop) blend_state->logicop_func); 337 } 338 339 /* TODO Dithering */ 340 341 state->desc.AlphaToCoverageEnable = blend_state->alpha_to_coverage; 342 343 int num_targets = 1; 344 if (blend_state->independent_blend_enable) { 345 state->desc.IndependentBlendEnable = TRUE; 346 num_targets = PIPE_MAX_COLOR_BUFS; 347 } 348 349 for (int i = 0; i < num_targets; ++i) { 350 const struct pipe_rt_blend_state *rt = blend_state->rt + i; 351 352 if (rt->blend_enable) { 353 state->desc.RenderTarget[i].BlendEnable = TRUE; 354 state->desc.RenderTarget[i].SrcBlend = blend_factor_rgb((pipe_blendfactor) rt->rgb_src_factor); 355 state->desc.RenderTarget[i].DestBlend = blend_factor_rgb((pipe_blendfactor) rt->rgb_dst_factor); 356 state->desc.RenderTarget[i].BlendOp = blend_op((pipe_blend_func) rt->rgb_func); 357 state->desc.RenderTarget[i].SrcBlendAlpha = blend_factor_alpha((pipe_blendfactor) rt->alpha_src_factor); 358 state->desc.RenderTarget[i].DestBlendAlpha = blend_factor_alpha((pipe_blendfactor) rt->alpha_dst_factor); 359 state->desc.RenderTarget[i].BlendOpAlpha = blend_op((pipe_blend_func) rt->alpha_func); 360 361 state->blend_factor_flags |= need_blend_factor_rgb((pipe_blendfactor) rt->rgb_src_factor); 362 state->blend_factor_flags |= need_blend_factor_rgb((pipe_blendfactor) rt->rgb_dst_factor); 363 state->blend_factor_flags |= need_blend_factor_alpha((pipe_blendfactor) rt->alpha_src_factor); 364 state->blend_factor_flags |= need_blend_factor_alpha((pipe_blendfactor) rt->alpha_dst_factor); 365 366 if (state->blend_factor_flags == (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ALPHA) && 367 (d3d12_debug & D3D12_DEBUG_VERBOSE)) { 368 /* We can't set a blend factor for both constant color and constant alpha */ 369 debug_printf("D3D12: unsupported blend factors combination (const color and const alpha)\n"); 370 } 371 372 if (util_blend_state_is_dual(blend_state, i)) 373 state->is_dual_src = true; 374 } 375 376 state->desc.RenderTarget[i].RenderTargetWriteMask = color_write_mask(rt->colormask); 377 } 378 379 return state; 380} 381 382static void 383d3d12_bind_blend_state(struct pipe_context *pctx, void *blend_state) 384{ 385 struct d3d12_context *ctx = d3d12_context(pctx); 386 struct d3d12_blend_state *new_state = (struct d3d12_blend_state *) blend_state; 387 struct d3d12_blend_state *old_state = ctx->gfx_pipeline_state.blend; 388 389 ctx->gfx_pipeline_state.blend = new_state; 390 ctx->state_dirty |= D3D12_DIRTY_BLEND; 391 if (new_state == NULL || old_state == NULL || 392 new_state->blend_factor_flags != old_state->blend_factor_flags) 393 ctx->state_dirty |= D3D12_DIRTY_BLEND_COLOR; 394} 395 396static void 397d3d12_delete_blend_state(struct pipe_context *pctx, void *blend_state) 398{ 399 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), blend_state); 400 FREE(blend_state); 401} 402 403static D3D12_STENCIL_OP 404stencil_op(enum pipe_stencil_op op) 405{ 406 switch (op) { 407 case PIPE_STENCIL_OP_KEEP: return D3D12_STENCIL_OP_KEEP; 408 case PIPE_STENCIL_OP_ZERO: return D3D12_STENCIL_OP_ZERO; 409 case PIPE_STENCIL_OP_REPLACE: return D3D12_STENCIL_OP_REPLACE; 410 case PIPE_STENCIL_OP_INCR: return D3D12_STENCIL_OP_INCR_SAT; 411 case PIPE_STENCIL_OP_DECR: return D3D12_STENCIL_OP_DECR_SAT; 412 case PIPE_STENCIL_OP_INCR_WRAP: return D3D12_STENCIL_OP_INCR; 413 case PIPE_STENCIL_OP_DECR_WRAP: return D3D12_STENCIL_OP_DECR; 414 case PIPE_STENCIL_OP_INVERT: return D3D12_STENCIL_OP_INVERT; 415 } 416 unreachable("unexpected op"); 417} 418 419static D3D12_DEPTH_STENCILOP_DESC 420stencil_op_state(const struct pipe_stencil_state *src) 421{ 422 D3D12_DEPTH_STENCILOP_DESC ret; 423 ret.StencilFailOp = stencil_op((pipe_stencil_op) src->fail_op); 424 ret.StencilPassOp = stencil_op((pipe_stencil_op) src->zpass_op); 425 ret.StencilDepthFailOp = stencil_op((pipe_stencil_op) src->zfail_op); 426 ret.StencilFunc = compare_op((pipe_compare_func) src->func); 427 return ret; 428} 429 430static void * 431d3d12_create_depth_stencil_alpha_state(struct pipe_context *pctx, 432 const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha) 433{ 434 struct d3d12_depth_stencil_alpha_state *dsa = CALLOC_STRUCT(d3d12_depth_stencil_alpha_state); 435 if (!dsa) 436 return NULL; 437 438 if (depth_stencil_alpha->depth_enabled) { 439 dsa->desc.DepthEnable = TRUE; 440 dsa->desc.DepthFunc = compare_op((pipe_compare_func) depth_stencil_alpha->depth_func); 441 } 442 443 /* TODO Add support for GL_depth_bound_tests */ 444 #if 0 445 if (depth_stencil_alpha->depth.bounds_test) { 446 dsa->desc.DepthBoundsTestEnable = TRUE; 447 dsa->min_depth_bounds = depth_stencil_alpha->depth.bounds_min; 448 dsa->max_depth_bounds = depth_stencil_alpha->depth.bounds_max; 449 } 450 #endif 451 452 if (depth_stencil_alpha->stencil[0].enabled) { 453 dsa->desc.StencilEnable = TRUE; 454 dsa->desc.FrontFace = stencil_op_state(depth_stencil_alpha->stencil); 455 } 456 457 if (depth_stencil_alpha->stencil[1].enabled) 458 dsa->desc.BackFace = stencil_op_state(depth_stencil_alpha->stencil + 1); 459 else 460 dsa->desc.BackFace = dsa->desc.FrontFace; 461 462 dsa->desc.StencilReadMask = depth_stencil_alpha->stencil[0].valuemask; /* FIXME Back face mask */ 463 dsa->desc.StencilWriteMask = depth_stencil_alpha->stencil[0].writemask; /* FIXME Back face mask */ 464 dsa->desc.DepthWriteMask = (D3D12_DEPTH_WRITE_MASK) depth_stencil_alpha->depth_writemask; 465 466 return dsa; 467} 468 469static void 470d3d12_bind_depth_stencil_alpha_state(struct pipe_context *pctx, 471 void *dsa) 472{ 473 struct d3d12_context *ctx = d3d12_context(pctx); 474 ctx->gfx_pipeline_state.zsa = (struct d3d12_depth_stencil_alpha_state *) dsa; 475 ctx->state_dirty |= D3D12_DIRTY_ZSA; 476} 477 478static void 479d3d12_delete_depth_stencil_alpha_state(struct pipe_context *pctx, 480 void *dsa_state) 481{ 482 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), dsa_state); 483 FREE(dsa_state); 484} 485 486static D3D12_FILL_MODE 487fill_mode(unsigned mode) 488{ 489 switch (mode) { 490 case PIPE_POLYGON_MODE_FILL: 491 return D3D12_FILL_MODE_SOLID; 492 case PIPE_POLYGON_MODE_LINE: 493 return D3D12_FILL_MODE_WIREFRAME; 494 case PIPE_POLYGON_MODE_POINT: 495 return D3D12_FILL_MODE_SOLID; 496 497 default: 498 unreachable("unsupported fill-mode"); 499 } 500} 501 502static void * 503d3d12_create_rasterizer_state(struct pipe_context *pctx, 504 const struct pipe_rasterizer_state *rs_state) 505{ 506 struct d3d12_rasterizer_state *cso = CALLOC_STRUCT(d3d12_rasterizer_state); 507 if (!cso) 508 return NULL; 509 510 cso->base = *rs_state; 511 512 assert(rs_state->depth_clip_near == rs_state->depth_clip_far); 513 514 switch (rs_state->cull_face) { 515 case PIPE_FACE_NONE: 516 if (rs_state->fill_front != rs_state->fill_back) { 517 cso->base.cull_face = PIPE_FACE_BACK; 518 cso->desc.CullMode = D3D12_CULL_MODE_BACK; 519 cso->desc.FillMode = fill_mode(rs_state->fill_front); 520 521 /* create a modified CSO for the back-state, so we can draw with 522 * either. 523 */ 524 struct pipe_rasterizer_state templ = *rs_state; 525 templ.cull_face = PIPE_FACE_FRONT; 526 templ.fill_front = rs_state->fill_back; 527 cso->twoface_back = d3d12_create_rasterizer_state(pctx, &templ); 528 529 if (!cso->twoface_back) { 530 FREE(cso); 531 return NULL; 532 } 533 } else { 534 cso->desc.CullMode = D3D12_CULL_MODE_NONE; 535 cso->desc.FillMode = fill_mode(rs_state->fill_front); 536 } 537 break; 538 539 case PIPE_FACE_FRONT: 540 cso->desc.CullMode = D3D12_CULL_MODE_FRONT; 541 cso->desc.FillMode = fill_mode(rs_state->fill_back); 542 break; 543 544 case PIPE_FACE_BACK: 545 cso->desc.CullMode = D3D12_CULL_MODE_BACK; 546 cso->desc.FillMode = fill_mode(rs_state->fill_front); 547 break; 548 549 case PIPE_FACE_FRONT_AND_BACK: 550 /* this is wrong, and we shouldn't actually have to support this! */ 551 cso->desc.CullMode = D3D12_CULL_MODE_NONE; 552 cso->desc.FillMode = D3D12_FILL_MODE_SOLID; 553 break; 554 555 default: 556 unreachable("unsupported cull-mode"); 557 } 558 559 cso->desc.FrontCounterClockwise = rs_state->front_ccw; 560 cso->desc.DepthClipEnable = rs_state->depth_clip_near; 561 cso->desc.MultisampleEnable = rs_state->multisample; 562 cso->desc.AntialiasedLineEnable = rs_state->line_smooth; 563 cso->desc.ForcedSampleCount = 0; // TODO 564 cso->desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; /* Not Implemented */ 565 566 return cso; 567} 568 569static void 570d3d12_bind_rasterizer_state(struct pipe_context *pctx, void *rs_state) 571{ 572 struct d3d12_context *ctx = d3d12_context(pctx); 573 ctx->gfx_pipeline_state.rast = (struct d3d12_rasterizer_state *)rs_state; 574 ctx->state_dirty |= D3D12_DIRTY_RASTERIZER | D3D12_DIRTY_SCISSOR; 575} 576 577static void 578d3d12_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state) 579{ 580 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), rs_state); 581 FREE(rs_state); 582} 583 584static D3D12_TEXTURE_ADDRESS_MODE 585sampler_address_mode(enum pipe_tex_wrap wrap, enum pipe_tex_filter filter) 586{ 587 switch (wrap) { 588 case PIPE_TEX_WRAP_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_WRAP; 589 case PIPE_TEX_WRAP_CLAMP: return filter == PIPE_TEX_FILTER_NEAREST ? 590 D3D12_TEXTURE_ADDRESS_MODE_CLAMP : 591 D3D12_TEXTURE_ADDRESS_MODE_BORDER; 592 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; 593 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_BORDER; 594 case PIPE_TEX_WRAP_MIRROR_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; 595 case PIPE_TEX_WRAP_MIRROR_CLAMP: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; /* not technically correct, but kinda works */ 596 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; 597 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; /* FIXME: Doesn't exist in D3D12 */ 598 } 599 unreachable("unexpected wrap"); 600} 601 602static D3D12_FILTER 603get_filter(const struct pipe_sampler_state *state) 604{ 605 static const D3D12_FILTER lut[16] = { 606 D3D12_FILTER_MIN_MAG_MIP_POINT, 607 D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR, 608 D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, 609 D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR, 610 D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT, 611 D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, 612 D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, 613 D3D12_FILTER_MIN_MAG_MIP_LINEAR, 614 D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT, 615 D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR, 616 D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT, 617 D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR, 618 D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT, 619 D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR, 620 D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, 621 D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR, 622 }; 623 624 static const D3D12_FILTER anisotropic_lut[2] = { 625 D3D12_FILTER_ANISOTROPIC, 626 D3D12_FILTER_COMPARISON_ANISOTROPIC, 627 }; 628 629 if (state->max_anisotropy > 1) { 630 return anisotropic_lut[state->compare_mode]; 631 } else { 632 int idx = (state->mag_img_filter << 1) | 633 (state->min_img_filter << 2) | 634 (state->compare_mode << 3); 635 if (state->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) 636 idx |= state->min_mip_filter; 637 return lut[idx]; 638 } 639} 640 641static void * 642d3d12_create_sampler_state(struct pipe_context *pctx, 643 const struct pipe_sampler_state *state) 644{ 645 struct d3d12_context *ctx = d3d12_context(pctx); 646 struct d3d12_screen *screen = d3d12_screen(pctx->screen); 647 struct d3d12_sampler_state *ss; 648 D3D12_SAMPLER_DESC desc = {}; 649 if (!state) 650 return NULL; 651 652 ss = CALLOC_STRUCT(d3d12_sampler_state); 653 ss->filter = (pipe_tex_filter)state->min_img_filter; 654 ss->wrap_r = (pipe_tex_wrap)state->wrap_r; 655 ss->wrap_s = (pipe_tex_wrap)state->wrap_s; 656 ss->wrap_t = (pipe_tex_wrap)state->wrap_t; 657 ss->lod_bias = state->lod_bias; 658 ss->min_lod = state->min_lod; 659 ss->max_lod = state->max_lod; 660 memcpy(ss->border_color, state->border_color.f, sizeof(float) * 4); 661 ss->compare_func = (pipe_compare_func)state->compare_func; 662 663 if (state->min_mip_filter < PIPE_TEX_MIPFILTER_NONE) { 664 desc.MinLOD = state->min_lod; 665 desc.MaxLOD = state->max_lod; 666 } else if (state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 667 desc.MinLOD = 0; 668 desc.MaxLOD = 0; 669 } else { 670 unreachable("unexpected mip filter"); 671 } 672 673 if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 674 desc.ComparisonFunc = compare_op((pipe_compare_func) state->compare_func); 675 } else if (state->compare_mode == PIPE_TEX_COMPARE_NONE) { 676 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; 677 } else 678 unreachable("unexpected comparison mode"); 679 680 desc.MaxAnisotropy = state->max_anisotropy; 681 desc.Filter = get_filter(state); 682 683 desc.AddressU = sampler_address_mode((pipe_tex_wrap) state->wrap_s, 684 (pipe_tex_filter) state->min_img_filter); 685 desc.AddressV = sampler_address_mode((pipe_tex_wrap) state->wrap_t, 686 (pipe_tex_filter) state->min_img_filter); 687 desc.AddressW = sampler_address_mode((pipe_tex_wrap) state->wrap_r, 688 (pipe_tex_filter) state->min_img_filter); 689 desc.MipLODBias = CLAMP(state->lod_bias, -16.0f, 15.99f); 690 memcpy(desc.BorderColor, state->border_color.f, sizeof(float) * 4); 691 692 // TODO Normalized Coordinates? 693 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ss->handle); 694 screen->dev->CreateSampler(&desc, ss->handle.cpu_handle); 695 696 if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 697 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; 698 desc.Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT; 699 700 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, 701 &ss->handle_without_shadow); 702 screen->dev->CreateSampler(&desc, 703 ss->handle_without_shadow.cpu_handle); 704 ss->is_shadow_sampler = true; 705 } 706 707 return ss; 708} 709 710static void 711d3d12_bind_sampler_states(struct pipe_context *pctx, 712 enum pipe_shader_type shader, 713 unsigned start_slot, 714 unsigned num_samplers, 715 void **samplers) 716{ 717 struct d3d12_context *ctx = d3d12_context(pctx); 718 719#define STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(X) \ 720 static_assert((enum compare_func)PIPE_FUNC_##X == COMPARE_FUNC_##X, #X " needs switch case"); 721 722 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(LESS); 723 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(GREATER); 724 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(LEQUAL); 725 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(GEQUAL); 726 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(NOTEQUAL); 727 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(NEVER); 728 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(ALWAYS); 729 730#undef STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC 731 732 for (unsigned i = 0; i < num_samplers; ++i) { 733 d3d12_sampler_state *sampler = (struct d3d12_sampler_state*) samplers[i]; 734 ctx->samplers[shader][start_slot + i] = sampler; 735 dxil_wrap_sampler_state &wrap = ctx->tex_wrap_states[shader][start_slot + i]; 736 if (sampler) { 737 wrap.wrap[0] = sampler->wrap_s; 738 wrap.wrap[1] = sampler->wrap_t; 739 wrap.wrap[2] = sampler->wrap_r; 740 wrap.lod_bias = sampler->lod_bias; 741 wrap.min_lod = sampler->min_lod; 742 wrap.max_lod = sampler->max_lod; 743 memcpy(wrap.border_color, sampler->border_color, 4 * sizeof(float)); 744 ctx->tex_compare_func[shader][start_slot + i] = (enum compare_func)sampler->compare_func; 745 } else { 746 memset(&wrap, 0, sizeof (dxil_wrap_sampler_state)); 747 } 748 } 749 750 ctx->num_samplers[shader] = start_slot + num_samplers; 751 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SAMPLERS; 752} 753 754static void 755d3d12_delete_sampler_state(struct pipe_context *pctx, 756 void *ss) 757{ 758 struct d3d12_batch *batch = d3d12_current_batch(d3d12_context(pctx)); 759 struct d3d12_sampler_state *state = (struct d3d12_sampler_state*) ss; 760 util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle, 761 state->handle); 762 if (state->is_shadow_sampler) 763 util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle, 764 state->handle_without_shadow); 765 FREE(ss); 766} 767 768static D3D12_SRV_DIMENSION 769view_dimension(enum pipe_texture_target target, unsigned samples) 770{ 771 switch (target) { 772 case PIPE_BUFFER: return D3D12_SRV_DIMENSION_BUFFER; 773 case PIPE_TEXTURE_1D: return D3D12_SRV_DIMENSION_TEXTURE1D; 774 case PIPE_TEXTURE_1D_ARRAY: return D3D12_SRV_DIMENSION_TEXTURE1DARRAY; 775 case PIPE_TEXTURE_RECT: 776 case PIPE_TEXTURE_2D: 777 return samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMS : 778 D3D12_SRV_DIMENSION_TEXTURE2D; 779 case PIPE_TEXTURE_2D_ARRAY: 780 return samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY : 781 D3D12_SRV_DIMENSION_TEXTURE2DARRAY; 782 case PIPE_TEXTURE_CUBE: return D3D12_SRV_DIMENSION_TEXTURECUBE; 783 case PIPE_TEXTURE_CUBE_ARRAY: return D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; 784 case PIPE_TEXTURE_3D: return D3D12_SRV_DIMENSION_TEXTURE3D; 785 default: 786 unreachable("unexpected target"); 787 } 788} 789 790static D3D12_SHADER_COMPONENT_MAPPING 791component_mapping(enum pipe_swizzle swizzle, D3D12_SHADER_COMPONENT_MAPPING id) 792{ 793 switch (swizzle) { 794 case PIPE_SWIZZLE_X: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0; 795 case PIPE_SWIZZLE_Y: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1; 796 case PIPE_SWIZZLE_Z: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2; 797 case PIPE_SWIZZLE_W: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3; 798 case PIPE_SWIZZLE_0: return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0; 799 case PIPE_SWIZZLE_1: return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1; 800 case PIPE_SWIZZLE_NONE: return id; 801 default: 802 unreachable("unexpected swizzle"); 803 } 804} 805 806void 807d3d12_init_sampler_view_descriptor(struct d3d12_sampler_view *sampler_view) 808{ 809 struct pipe_sampler_view *state = &sampler_view->base; 810 struct pipe_resource *texture = state->texture; 811 struct d3d12_resource *res = d3d12_resource(texture); 812 struct d3d12_screen *screen = d3d12_screen(texture->screen); 813 814 struct d3d12_format_info format_info = d3d12_get_format_info(res->overall_format, state->format, state->target); 815 D3D12_SHADER_RESOURCE_VIEW_DESC desc = {}; 816 desc.Format = d3d12_get_resource_srv_format(state->format, state->target); 817 desc.ViewDimension = view_dimension(state->target, texture->nr_samples); 818 819 /* Integer cube textures are not really supported, because TextureLoad doesn't exist 820 * for cube maps, and we sampling is not supported for integer textures, so we have to 821 * handle this SRV as if it were a 2D texture array */ 822 if ((desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE || 823 desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) && 824 util_format_is_pure_integer(state->format)) { 825 desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; 826 } 827 828 desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( 829 component_mapping((pipe_swizzle)sampler_view->swizzle_override_r, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0), 830 component_mapping((pipe_swizzle)sampler_view->swizzle_override_g, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1), 831 component_mapping((pipe_swizzle)sampler_view->swizzle_override_b, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2), 832 component_mapping((pipe_swizzle)sampler_view->swizzle_override_a, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3) 833 ); 834 835 uint64_t offset = 0; 836 ID3D12Resource *d3d12_res = d3d12_resource_underlying(res, &offset); 837 assert(offset == 0 || res->base.b.target == PIPE_BUFFER); 838 839 unsigned array_size = state->u.tex.last_layer - state->u.tex.first_layer + 1; 840 switch (desc.ViewDimension) { 841 case D3D12_SRV_DIMENSION_TEXTURE1D: 842 if (state->u.tex.first_layer > 0) 843 debug_printf("D3D12: can't create 1D SRV from layer %d\n", 844 state->u.tex.first_layer); 845 846 desc.Texture1D.MostDetailedMip = state->u.tex.first_level; 847 desc.Texture1D.MipLevels = sampler_view->mip_levels; 848 desc.Texture1D.ResourceMinLODClamp = 0.0f; 849 break; 850 case D3D12_SRV_DIMENSION_TEXTURE1DARRAY: 851 desc.Texture1DArray.MostDetailedMip = state->u.tex.first_level; 852 desc.Texture1DArray.MipLevels = sampler_view->mip_levels; 853 desc.Texture1DArray.ResourceMinLODClamp = 0.0f; 854 desc.Texture1DArray.FirstArraySlice = state->u.tex.first_layer; 855 desc.Texture1DArray.ArraySize = array_size; 856 break; 857 case D3D12_SRV_DIMENSION_TEXTURE2D: 858 if (state->u.tex.first_layer > 0) 859 debug_printf("D3D12: can't create 2D SRV from layer %d\n", 860 state->u.tex.first_layer); 861 862 desc.Texture2D.MostDetailedMip = state->u.tex.first_level; 863 desc.Texture2D.MipLevels = sampler_view->mip_levels; 864 desc.Texture2D.PlaneSlice = format_info.plane_slice; 865 desc.Texture2D.ResourceMinLODClamp = 0.0f; 866 break; 867 case D3D12_SRV_DIMENSION_TEXTURE2DMS: 868 if (state->u.tex.first_layer > 0) 869 debug_printf("D3D12: can't create 2DMS SRV from layer %d\n", 870 state->u.tex.first_layer); 871 break; 872 case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: 873 desc.Texture2DArray.MostDetailedMip = state->u.tex.first_level; 874 desc.Texture2DArray.MipLevels = sampler_view->mip_levels; 875 desc.Texture2DArray.ResourceMinLODClamp = 0.0f; 876 desc.Texture2DArray.FirstArraySlice = state->u.tex.first_layer; 877 desc.Texture2DArray.PlaneSlice = format_info.plane_slice; 878 desc.Texture2DArray.ArraySize = array_size; 879 break; 880 case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY: 881 desc.Texture2DMSArray.FirstArraySlice = state->u.tex.first_layer; 882 desc.Texture2DMSArray.ArraySize = array_size; 883 break; 884 case D3D12_SRV_DIMENSION_TEXTURE3D: 885 if (state->u.tex.first_layer > 0) 886 debug_printf("D3D12: can't create 3D SRV from layer %d\n", 887 state->u.tex.first_layer); 888 889 desc.Texture3D.MostDetailedMip = state->u.tex.first_level; 890 desc.Texture3D.MipLevels = sampler_view->mip_levels; 891 desc.Texture3D.ResourceMinLODClamp = 0.0f; 892 break; 893 case D3D12_SRV_DIMENSION_TEXTURECUBE: 894 if (state->u.tex.first_layer > 0) 895 debug_printf("D3D12: can't create CUBE SRV from layer %d\n", 896 state->u.tex.first_layer); 897 898 desc.TextureCube.MostDetailedMip = state->u.tex.first_level; 899 desc.TextureCube.MipLevels = sampler_view->mip_levels; 900 desc.TextureCube.ResourceMinLODClamp = 0.0f; 901 break; 902 case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY: 903 assert(array_size % 6 == 0); 904 desc.TextureCubeArray.MostDetailedMip = state->u.tex.first_level; 905 desc.TextureCubeArray.MipLevels = sampler_view->mip_levels; 906 desc.TextureCubeArray.First2DArrayFace = state->u.tex.first_layer; 907 desc.TextureCubeArray.NumCubes = array_size / 6; 908 desc.TextureCubeArray.ResourceMinLODClamp = 0.0f; 909 break; 910 case D3D12_SRV_DIMENSION_BUFFER: 911 desc.Buffer.StructureByteStride = 0; 912 desc.Buffer.FirstElement = offset / util_format_get_blocksize(state->format); 913 desc.Buffer.NumElements = texture->width0 / util_format_get_blocksize(state->format); 914 break; 915 default: 916 unreachable("Invalid SRV dimension"); 917 } 918 919 screen->dev->CreateShaderResourceView(d3d12_res, &desc, 920 sampler_view->handle.cpu_handle); 921} 922 923static struct pipe_sampler_view * 924d3d12_create_sampler_view(struct pipe_context *pctx, 925 struct pipe_resource *texture, 926 const struct pipe_sampler_view *state) 927{ 928 struct d3d12_screen *screen = d3d12_screen(pctx->screen); 929 struct d3d12_resource *res = d3d12_resource(texture); 930 struct d3d12_sampler_view *sampler_view = CALLOC_STRUCT(d3d12_sampler_view); 931 932 sampler_view->base = *state; 933 sampler_view->base.texture = NULL; 934 pipe_resource_reference(&sampler_view->base.texture, texture); 935 sampler_view->base.reference.count = 1; 936 sampler_view->base.context = pctx; 937 sampler_view->mip_levels = state->u.tex.last_level - state->u.tex.first_level + 1; 938 sampler_view->array_size = texture->array_size; 939 sampler_view->texture_generation_id = p_atomic_read(&res->generation_id); 940 941 struct d3d12_format_info format_info = d3d12_get_format_info(res->overall_format, state->format, state->target); 942 pipe_swizzle swizzle[4] = { 943 format_info.swizzle[sampler_view->base.swizzle_r], 944 format_info.swizzle[sampler_view->base.swizzle_g], 945 format_info.swizzle[sampler_view->base.swizzle_b], 946 format_info.swizzle[sampler_view->base.swizzle_a] 947 }; 948 949 sampler_view->swizzle_override_r = swizzle[0]; 950 sampler_view->swizzle_override_g = swizzle[1]; 951 sampler_view->swizzle_override_b = swizzle[2]; 952 sampler_view->swizzle_override_a = swizzle[3]; 953 954 mtx_lock(&screen->descriptor_pool_mutex); 955 d3d12_descriptor_pool_alloc_handle(screen->view_pool, &sampler_view->handle); 956 mtx_unlock(&screen->descriptor_pool_mutex); 957 958 d3d12_init_sampler_view_descriptor(sampler_view); 959 960 return &sampler_view->base; 961} 962 963static void 964d3d12_increment_sampler_view_bind_count(struct pipe_context *ctx, 965 enum pipe_shader_type shader_type, 966 struct pipe_sampler_view *view) { 967 struct d3d12_resource *res = d3d12_resource(view->texture); 968 if (res) 969 res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]++; 970} 971 972static void 973d3d12_decrement_sampler_view_bind_count(struct pipe_context *ctx, 974 enum pipe_shader_type shader_type, 975 struct pipe_sampler_view *view) { 976 struct d3d12_resource *res = d3d12_resource(view->texture); 977 if (res) { 978 assert(res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0); 979 res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]--; 980 } 981} 982 983static void 984d3d12_set_sampler_views(struct pipe_context *pctx, 985 enum pipe_shader_type shader_type, 986 unsigned start_slot, 987 unsigned num_views, 988 unsigned unbind_num_trailing_slots, 989 bool take_ownership, 990 struct pipe_sampler_view **views) 991{ 992 struct d3d12_context *ctx = d3d12_context(pctx); 993 unsigned shader_bit = (1 << shader_type); 994 ctx->has_int_samplers &= ~shader_bit; 995 996 for (unsigned i = 0; i < num_views; ++i) { 997 struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + i]; 998 if (old_view) 999 d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view); 1000 1001 struct pipe_sampler_view *new_view = views[i]; 1002 if (new_view) 1003 d3d12_increment_sampler_view_bind_count(pctx, shader_type, new_view); 1004 1005 if (take_ownership) { 1006 pipe_sampler_view_reference(&old_view, NULL); 1007 old_view = views[i]; 1008 } else { 1009 pipe_sampler_view_reference(&old_view, views[i]); 1010 } 1011 1012 if (views[i]) { 1013 dxil_wrap_sampler_state &wss = ctx->tex_wrap_states[shader_type][start_slot + i]; 1014 dxil_texture_swizzle_state &swizzle_state = ctx->tex_swizzle_state[shader_type][i]; 1015 if (util_format_is_pure_integer(views[i]->format)) { 1016 ctx->has_int_samplers |= shader_bit; 1017 wss.is_int_sampler = 1; 1018 wss.last_level = views[i]->texture->last_level; 1019 /* When we emulate a integer cube texture (array) by using a texture 2d Array 1020 * the coordinates are evaluated to always reside withing the acceptable range 1021 * because the 3d ray for picking the texel is always pointing at one cube face, 1022 * hence we can skip the boundary condition handling when the texture operations are 1023 * lowered to texel fetches later. */ 1024 wss.skip_boundary_conditions = views[i]->target == PIPE_TEXTURE_CUBE || 1025 views[i]->target == PIPE_TEXTURE_CUBE_ARRAY; 1026 } else { 1027 wss.is_int_sampler = 0; 1028 } 1029 /* We need the swizzle state for compare texture lowering, because it 1030 * encode the use of the shadow texture lookup result as either luminosity, 1031 * intensity, or alpha. and we need the swizzle state for applying the 1032 * boundary color correctly */ 1033 struct d3d12_sampler_view *ss = d3d12_sampler_view(views[i]); 1034 swizzle_state.swizzle_r = ss->swizzle_override_r; 1035 swizzle_state.swizzle_g = ss->swizzle_override_g; 1036 swizzle_state.swizzle_b = ss->swizzle_override_b; 1037 swizzle_state.swizzle_a = ss->swizzle_override_a; 1038 } 1039 } 1040 1041 for (unsigned i = 0; i < unbind_num_trailing_slots; i++) { 1042 struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + num_views + i]; 1043 if (old_view) 1044 d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view); 1045 pipe_sampler_view_reference(&old_view, NULL); 1046 } 1047 ctx->num_sampler_views[shader_type] = start_slot + num_views; 1048 ctx->shader_dirty[shader_type] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; 1049} 1050 1051static void 1052d3d12_destroy_sampler_view(struct pipe_context *pctx, 1053 struct pipe_sampler_view *pview) 1054{ 1055 struct d3d12_sampler_view *view = d3d12_sampler_view(pview); 1056 d3d12_descriptor_handle_free(&view->handle); 1057 pipe_resource_reference(&view->base.texture, NULL); 1058 FREE(view); 1059} 1060 1061static void 1062delete_shader(struct d3d12_context *ctx, enum pipe_shader_type stage, 1063 struct d3d12_shader_selector *shader) 1064{ 1065 d3d12_gfx_pipeline_state_cache_invalidate_shader(ctx, stage, shader); 1066 1067 /* Make sure the pipeline state no longer reference the deleted shader */ 1068 struct d3d12_shader *iter = shader->first; 1069 while (iter) { 1070 if (ctx->gfx_pipeline_state.stages[stage] == iter) { 1071 ctx->gfx_pipeline_state.stages[stage] = NULL; 1072 break; 1073 } 1074 iter = iter->next_variant; 1075 } 1076 1077 d3d12_shader_free(shader); 1078} 1079 1080static void 1081bind_stage(struct d3d12_context *ctx, enum pipe_shader_type stage, 1082 struct d3d12_shader_selector *shader) 1083{ 1084 assert(stage < D3D12_GFX_SHADER_STAGES); 1085 ctx->gfx_stages[stage] = shader; 1086} 1087 1088static void * 1089d3d12_create_vs_state(struct pipe_context *pctx, 1090 const struct pipe_shader_state *shader) 1091{ 1092 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX, shader); 1093} 1094 1095static void 1096d3d12_bind_vs_state(struct pipe_context *pctx, 1097 void *vss) 1098{ 1099 bind_stage(d3d12_context(pctx), PIPE_SHADER_VERTEX, 1100 (struct d3d12_shader_selector *) vss); 1101} 1102 1103static void 1104d3d12_delete_vs_state(struct pipe_context *pctx, 1105 void *vs) 1106{ 1107 delete_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX, 1108 (struct d3d12_shader_selector *) vs); 1109} 1110 1111static void * 1112d3d12_create_fs_state(struct pipe_context *pctx, 1113 const struct pipe_shader_state *shader) 1114{ 1115 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, shader); 1116} 1117 1118static void 1119d3d12_bind_fs_state(struct pipe_context *pctx, 1120 void *fss) 1121{ 1122 bind_stage(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, 1123 (struct d3d12_shader_selector *) fss); 1124} 1125 1126static void 1127d3d12_delete_fs_state(struct pipe_context *pctx, 1128 void *fs) 1129{ 1130 delete_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, 1131 (struct d3d12_shader_selector *) fs); 1132} 1133 1134static void * 1135d3d12_create_gs_state(struct pipe_context *pctx, 1136 const struct pipe_shader_state *shader) 1137{ 1138 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, shader); 1139} 1140 1141static void 1142d3d12_bind_gs_state(struct pipe_context *pctx, void *gss) 1143{ 1144 bind_stage(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, 1145 (struct d3d12_shader_selector *) gss); 1146} 1147 1148static void 1149d3d12_delete_gs_state(struct pipe_context *pctx, void *gs) 1150{ 1151 delete_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, 1152 (struct d3d12_shader_selector *) gs); 1153} 1154 1155static void * 1156d3d12_create_tcs_state(struct pipe_context *pctx, 1157 const struct pipe_shader_state *shader) 1158{ 1159 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL, shader); 1160} 1161 1162static void 1163d3d12_bind_tcs_state(struct pipe_context *pctx, void *tcss) 1164{ 1165 bind_stage(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL, 1166 (struct d3d12_shader_selector *)tcss); 1167} 1168 1169static void 1170d3d12_delete_tcs_state(struct pipe_context *pctx, void *tcs) 1171{ 1172 delete_shader(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL, 1173 (struct d3d12_shader_selector *)tcs); 1174} 1175 1176static void * 1177d3d12_create_tes_state(struct pipe_context *pctx, 1178 const struct pipe_shader_state *shader) 1179{ 1180 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL, shader); 1181} 1182 1183static void 1184d3d12_bind_tes_state(struct pipe_context *pctx, void *tess) 1185{ 1186 bind_stage(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL, 1187 (struct d3d12_shader_selector *)tess); 1188} 1189 1190static void 1191d3d12_delete_tes_state(struct pipe_context *pctx, void *tes) 1192{ 1193 delete_shader(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL, 1194 (struct d3d12_shader_selector *)tes); 1195} 1196 1197static void * 1198d3d12_create_compute_state(struct pipe_context *pctx, 1199 const struct pipe_compute_state *shader) 1200{ 1201 return d3d12_create_compute_shader(d3d12_context(pctx), shader); 1202} 1203 1204static void 1205d3d12_bind_compute_state(struct pipe_context *pctx, void *css) 1206{ 1207 d3d12_context(pctx)->compute_state = (struct d3d12_shader_selector *)css; 1208} 1209 1210static void 1211d3d12_delete_compute_state(struct pipe_context *pctx, void *cs) 1212{ 1213 struct d3d12_context *ctx = d3d12_context(pctx); 1214 struct d3d12_shader_selector *shader = (struct d3d12_shader_selector *)cs; 1215 d3d12_compute_pipeline_state_cache_invalidate_shader(ctx, shader); 1216 1217 /* Make sure the pipeline state no longer reference the deleted shader */ 1218 struct d3d12_shader *iter = shader->first; 1219 while (iter) { 1220 if (ctx->compute_pipeline_state.stage == iter) { 1221 ctx->compute_pipeline_state.stage = NULL; 1222 break; 1223 } 1224 iter = iter->next_variant; 1225 } 1226 1227 d3d12_shader_free(shader); 1228} 1229 1230static bool 1231d3d12_init_polygon_stipple(struct pipe_context *pctx) 1232{ 1233 struct d3d12_context *ctx = d3d12_context(pctx); 1234 1235 ctx->pstipple.texture = util_pstipple_create_stipple_texture(pctx, NULL); 1236 if (!ctx->pstipple.texture) 1237 return false; 1238 1239 ctx->pstipple.sampler_view = util_pstipple_create_sampler_view(pctx, ctx->pstipple.texture); 1240 if (!ctx->pstipple.sampler_view) 1241 return false; 1242 1243 ctx->pstipple.sampler_cso = (struct d3d12_sampler_state *)util_pstipple_create_sampler(pctx); 1244 if (!ctx->pstipple.sampler_cso) 1245 return false; 1246 1247 return true; 1248} 1249 1250static void 1251d3d12_set_polygon_stipple(struct pipe_context *pctx, 1252 const struct pipe_poly_stipple *ps) 1253{ 1254 static bool initialized = false; 1255 static const uint32_t zero[32] = {0}; 1256 static uint32_t undef[32] = {0}; 1257 struct d3d12_context *ctx = d3d12_context(pctx); 1258 1259 if (!initialized) 1260 memset(undef, UINT32_MAX, sizeof(undef)); 1261 1262 if (!memcmp(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple))) 1263 return; 1264 1265 memcpy(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple)); 1266 ctx->pstipple.enabled = !!memcmp(ps->stipple, undef, sizeof(ps->stipple)) && 1267 !!memcmp(ps->stipple, zero, sizeof(ps->stipple)); 1268 if (ctx->pstipple.enabled) 1269 util_pstipple_update_stipple_texture(pctx, ctx->pstipple.texture, ps->stipple); 1270} 1271 1272static void 1273d3d12_set_vertex_buffers(struct pipe_context *pctx, 1274 unsigned start_slot, 1275 unsigned num_buffers, 1276 unsigned unbind_num_trailing_slots, 1277 bool take_ownership, 1278 const struct pipe_vertex_buffer *buffers) 1279{ 1280 struct d3d12_context *ctx = d3d12_context(pctx); 1281 util_set_vertex_buffers_count(ctx->vbs, &ctx->num_vbs, 1282 buffers, start_slot, num_buffers, 1283 unbind_num_trailing_slots, 1284 take_ownership); 1285 1286 for (unsigned i = 0; i < ctx->num_vbs; ++i) { 1287 const struct pipe_vertex_buffer* buf = ctx->vbs + i; 1288 if (!buf->buffer.resource) 1289 continue; 1290 struct d3d12_resource *res = d3d12_resource(buf->buffer.resource); 1291 ctx->vbvs[i].BufferLocation = d3d12_resource_gpu_virtual_address(res) + buf->buffer_offset; 1292 ctx->vbvs[i].StrideInBytes = buf->stride; 1293 ctx->vbvs[i].SizeInBytes = res->base.b.width0 - buf->buffer_offset; 1294 } 1295 ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS; 1296} 1297 1298static void 1299d3d12_set_viewport_states(struct pipe_context *pctx, 1300 unsigned start_slot, 1301 unsigned num_viewports, 1302 const struct pipe_viewport_state *state) 1303{ 1304 struct d3d12_context *ctx = d3d12_context(pctx); 1305 1306 for (unsigned i = 0; i < num_viewports; ++i) { 1307 if (state[i].scale[1] < 0) { 1308 ctx->flip_y = 1.0f; 1309 ctx->viewports[start_slot + i].TopLeftY = state[i].translate[1] + state[i].scale[1]; 1310 ctx->viewports[start_slot + i].Height = -state[i].scale[1] * 2; 1311 } else { 1312 ctx->flip_y = -1.0f; 1313 ctx->viewports[start_slot + i].TopLeftY = state[i].translate[1] - state[i].scale[1]; 1314 ctx->viewports[start_slot + i].Height = state[i].scale[1] * 2; 1315 } 1316 ctx->viewports[start_slot + i].TopLeftX = state[i].translate[0] - state[i].scale[0]; 1317 ctx->viewports[start_slot + i].Width = state[i].scale[0] * 2; 1318 1319 float near_depth = state[i].translate[2]; 1320 float far_depth = state[i].translate[2] + state[i].scale[2]; 1321 1322 /* When the rasterizer is configured for "full" depth clipping ([-1, 1]) 1323 * the viewport that we get is set to cover the positive half of clip space. 1324 * E.g. a [0, 1] viewport from the GL API will come to the driver as [0.5, 1]. 1325 * Since we halve clipping space from [-1, 1] to [0, 1], we need to double the 1326 * viewport, treating translate as the center instead of the near plane. When 1327 * the rasterizer is configured for "half" depth clipping ([0, 1]), the viewport 1328 * covers the entire clip range, so no fixup is needed. 1329 * 1330 * Note: If halfz mode changes, both the rasterizer and viewport are dirtied, 1331 * and on the next draw we will get the rasterizer state first, and viewport 1332 * second, because ST_NEW_RASTERIZER comes before ST_NEW_VIEWPORT. 1333 */ 1334 if (ctx->gfx_pipeline_state.rast && !ctx->gfx_pipeline_state.rast->base.clip_halfz) { 1335 near_depth -= state[i].scale[2]; 1336 } 1337 1338 bool reverse_depth_range = near_depth > far_depth; 1339 if (reverse_depth_range) { 1340 float tmp = near_depth; 1341 near_depth = far_depth; 1342 far_depth = tmp; 1343 ctx->reverse_depth_range |= (1 << (start_slot + i)); 1344 } else 1345 ctx->reverse_depth_range &= ~(1 << (start_slot + i)); 1346 ctx->viewports[start_slot + i].MinDepth = near_depth; 1347 ctx->viewports[start_slot + i].MaxDepth = far_depth; 1348 ctx->viewport_states[start_slot + i] = state[i]; 1349 } 1350 ctx->num_viewports = start_slot + num_viewports; 1351 ctx->state_dirty |= D3D12_DIRTY_VIEWPORT; 1352} 1353 1354 1355static void 1356d3d12_set_scissor_states(struct pipe_context *pctx, 1357 unsigned start_slot, unsigned num_scissors, 1358 const struct pipe_scissor_state *states) 1359{ 1360 struct d3d12_context *ctx = d3d12_context(pctx); 1361 1362 for (unsigned i = 0; i < num_scissors; i++) { 1363 ctx->scissors[start_slot + i].left = states[i].minx; 1364 ctx->scissors[start_slot + i].top = states[i].miny; 1365 ctx->scissors[start_slot + i].right = states[i].maxx; 1366 ctx->scissors[start_slot + i].bottom = states[i].maxy; 1367 ctx->scissor_states[start_slot + i] = states[i]; 1368 } 1369 ctx->state_dirty |= D3D12_DIRTY_SCISSOR; 1370} 1371 1372static void 1373d3d12_decrement_constant_buffer_bind_count(struct d3d12_context *ctx, 1374 enum pipe_shader_type shader, 1375 struct d3d12_resource *res) { 1376 assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0); 1377 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV]--; 1378} 1379 1380static void 1381d3d12_increment_constant_buffer_bind_count(struct d3d12_context *ctx, 1382 enum pipe_shader_type shader, 1383 struct d3d12_resource *res) { 1384 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV]++; 1385} 1386 1387static void 1388d3d12_set_constant_buffer(struct pipe_context *pctx, 1389 enum pipe_shader_type shader, uint index, 1390 bool take_ownership, 1391 const struct pipe_constant_buffer *buf) 1392{ 1393 struct d3d12_context *ctx = d3d12_context(pctx); 1394 struct d3d12_resource *old_buf = d3d12_resource(ctx->cbufs[shader][index].buffer); 1395 if (old_buf) 1396 d3d12_decrement_constant_buffer_bind_count(ctx, shader, old_buf); 1397 1398 if (buf) { 1399 unsigned offset = buf->buffer_offset; 1400 if (buf->user_buffer) { 1401 u_upload_data(pctx->const_uploader, 0, buf->buffer_size, 1402 D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT, 1403 buf->user_buffer, &offset, &ctx->cbufs[shader][index].buffer); 1404 d3d12_increment_constant_buffer_bind_count(ctx, shader, 1405 d3d12_resource(ctx->cbufs[shader][index].buffer)); 1406 } else { 1407 struct pipe_resource *buffer = buf->buffer; 1408 if (buffer) 1409 d3d12_increment_constant_buffer_bind_count(ctx, shader, d3d12_resource(buffer)); 1410 1411 if (take_ownership) { 1412 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL); 1413 ctx->cbufs[shader][index].buffer = buffer; 1414 } else { 1415 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, buffer); 1416 } 1417 } 1418 1419 ctx->cbufs[shader][index].buffer_offset = offset; 1420 ctx->cbufs[shader][index].buffer_size = buf->buffer_size; 1421 ctx->cbufs[shader][index].user_buffer = NULL; 1422 1423 } else { 1424 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL); 1425 ctx->cbufs[shader][index].buffer_offset = 0; 1426 ctx->cbufs[shader][index].buffer_size = 0; 1427 ctx->cbufs[shader][index].user_buffer = NULL; 1428 } 1429 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_CONSTBUF; 1430} 1431 1432static void 1433d3d12_set_framebuffer_state(struct pipe_context *pctx, 1434 const struct pipe_framebuffer_state *state) 1435{ 1436 struct d3d12_context *ctx = d3d12_context(pctx); 1437 int samples = -1; 1438 1439 bool prev_cbufs_or_zsbuf = ctx->fb.nr_cbufs || ctx->fb.zsbuf; 1440 util_copy_framebuffer_state(&d3d12_context(pctx)->fb, state); 1441 bool new_cbufs_or_zsbuf = ctx->fb.nr_cbufs || ctx->fb.zsbuf; 1442 1443 ctx->gfx_pipeline_state.num_cbufs = state->nr_cbufs; 1444 ctx->gfx_pipeline_state.has_float_rtv = false; 1445 for (int i = 0; i < state->nr_cbufs; ++i) { 1446 if (state->cbufs[i]) { 1447 if (util_format_is_float(state->cbufs[i]->format)) 1448 ctx->gfx_pipeline_state.has_float_rtv = true; 1449 ctx->gfx_pipeline_state.rtv_formats[i] = d3d12_get_format(state->cbufs[i]->format); 1450 samples = MAX2(samples, (int)state->cbufs[i]->texture->nr_samples); 1451 } else { 1452 ctx->gfx_pipeline_state.rtv_formats[i] = DXGI_FORMAT_UNKNOWN; 1453 } 1454 } 1455 1456 if (state->zsbuf) { 1457 ctx->gfx_pipeline_state.dsv_format = d3d12_get_resource_rt_format(state->zsbuf->format); 1458 samples = MAX2(samples, (int)ctx->fb.zsbuf->texture->nr_samples); 1459 } else 1460 ctx->gfx_pipeline_state.dsv_format = DXGI_FORMAT_UNKNOWN; 1461 1462 if (samples < 0) 1463 samples = state->samples; 1464 1465 ctx->gfx_pipeline_state.samples = MAX2(samples, 1); 1466 1467 ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER; 1468 if (!prev_cbufs_or_zsbuf || !new_cbufs_or_zsbuf) 1469 ctx->state_dirty |= D3D12_DIRTY_VIEWPORT; 1470} 1471 1472static void 1473d3d12_set_blend_color(struct pipe_context *pctx, 1474 const struct pipe_blend_color *color) 1475{ 1476 struct d3d12_context *ctx = d3d12_context(pctx); 1477 memcpy(ctx->blend_factor, color->color, sizeof(float) * 4); 1478 ctx->state_dirty |= D3D12_DIRTY_BLEND_COLOR; 1479} 1480 1481static void 1482d3d12_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 1483{ 1484 struct d3d12_context *ctx = d3d12_context(pctx); 1485 ctx->gfx_pipeline_state.sample_mask = sample_mask; 1486 ctx->state_dirty |= D3D12_DIRTY_SAMPLE_MASK; 1487} 1488 1489static void 1490d3d12_set_stencil_ref(struct pipe_context *pctx, 1491 const struct pipe_stencil_ref ref) 1492{ 1493 struct d3d12_context *ctx = d3d12_context(pctx); 1494 if ((ref.ref_value[0] != ref.ref_value[1]) && 1495 (d3d12_debug & D3D12_DEBUG_VERBOSE)) 1496 debug_printf("D3D12: Different values for front and back stencil reference are not supported\n"); 1497 ctx->stencil_ref = ref; 1498 ctx->state_dirty |= D3D12_DIRTY_STENCIL_REF; 1499} 1500 1501static void 1502d3d12_set_clip_state(struct pipe_context *pctx, 1503 const struct pipe_clip_state *pcs) 1504{ 1505} 1506 1507static struct pipe_stream_output_target * 1508d3d12_create_stream_output_target(struct pipe_context *pctx, 1509 struct pipe_resource *pres, 1510 unsigned buffer_offset, 1511 unsigned buffer_size) 1512{ 1513 struct d3d12_resource *res = d3d12_resource(pres); 1514 struct d3d12_stream_output_target *cso = CALLOC_STRUCT(d3d12_stream_output_target); 1515 1516 if (!cso) 1517 return NULL; 1518 1519 pipe_reference_init(&cso->base.reference, 1); 1520 pipe_resource_reference(&cso->base.buffer, pres); 1521 cso->base.buffer_offset = buffer_offset; 1522 cso->base.buffer_size = buffer_size; 1523 cso->base.context = pctx; 1524 1525 if (res->bo && res->bo->buffer && d3d12_buffer(res->bo->buffer)->map) 1526 util_range_add(pres, &res->valid_buffer_range, buffer_offset, 1527 buffer_offset + buffer_size); 1528 1529 return &cso->base; 1530} 1531 1532static void 1533d3d12_stream_output_target_destroy(struct pipe_context *ctx, 1534 struct pipe_stream_output_target *state) 1535{ 1536 pipe_resource_reference(&state->buffer, NULL); 1537 1538 FREE(state); 1539} 1540 1541static void 1542fill_stream_output_buffer_view(D3D12_STREAM_OUTPUT_BUFFER_VIEW *view, 1543 struct d3d12_stream_output_target *target) 1544{ 1545 struct d3d12_resource *res = d3d12_resource(target->base.buffer); 1546 struct d3d12_resource *fill_res = d3d12_resource(target->fill_buffer); 1547 1548 view->SizeInBytes = target->base.buffer_size; 1549 view->BufferLocation = d3d12_resource_gpu_virtual_address(res) + target->base.buffer_offset; 1550 view->BufferFilledSizeLocation = d3d12_resource_gpu_virtual_address(fill_res) + target->fill_buffer_offset; 1551} 1552 1553static void 1554update_so_fill_buffer_count(struct d3d12_context *ctx, 1555 struct pipe_resource *fill_buffer, 1556 unsigned fill_buffer_offset, 1557 unsigned value) 1558{ 1559 struct pipe_transfer *transfer = NULL; 1560 uint32_t *ptr = (uint32_t *)pipe_buffer_map_range(&ctx->base, fill_buffer, 1561 fill_buffer_offset, sizeof(uint32_t), PIPE_MAP_WRITE, &transfer); 1562 *ptr = value; 1563 pipe_buffer_unmap(&ctx->base, transfer); 1564} 1565 1566static void 1567d3d12_set_stream_output_targets(struct pipe_context *pctx, 1568 unsigned num_targets, 1569 struct pipe_stream_output_target **targets, 1570 const unsigned *offsets) 1571{ 1572 struct d3d12_context *ctx = d3d12_context(pctx); 1573 1574 assert(num_targets <= ARRAY_SIZE(ctx->so_targets)); 1575 1576 d3d12_disable_fake_so_buffers(ctx); 1577 1578 for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { 1579 struct d3d12_stream_output_target *target = 1580 i < num_targets ? (struct d3d12_stream_output_target *)targets[i] : NULL; 1581 1582 if (target) { 1583 /* Sub-allocate a new fill buffer each time to avoid GPU/CPU synchronization */ 1584 if (offsets[i] != ~0u) { 1585 u_suballocator_alloc(&ctx->so_allocator, sizeof(uint32_t) * 5, 16, 1586 &target->fill_buffer_offset, &target->fill_buffer); 1587 update_so_fill_buffer_count(ctx, target->fill_buffer, target->fill_buffer_offset, offsets[i]); 1588 } 1589 fill_stream_output_buffer_view(&ctx->so_buffer_views[i], target); 1590 pipe_so_target_reference(&ctx->so_targets[i], targets[i]); 1591 } else { 1592 ctx->so_buffer_views[i].BufferLocation = 0; 1593 ctx->so_buffer_views[i].BufferFilledSizeLocation = 0; 1594 ctx->so_buffer_views[i].SizeInBytes = 0; 1595 pipe_so_target_reference(&ctx->so_targets[i], NULL); 1596 } 1597 } 1598 1599 ctx->gfx_pipeline_state.num_so_targets = num_targets; 1600 ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1601} 1602 1603static void 1604d3d12_decrement_ssbo_bind_count(struct d3d12_context *ctx, 1605 enum pipe_shader_type shader, 1606 struct d3d12_resource *res) { 1607 assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO] > 0); 1608 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO]--; 1609} 1610 1611static void 1612d3d12_increment_ssbo_bind_count(struct d3d12_context *ctx, 1613 enum pipe_shader_type shader, 1614 struct d3d12_resource *res) { 1615 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO]++; 1616} 1617 1618static void 1619d3d12_set_shader_buffers(struct pipe_context *pctx, 1620 enum pipe_shader_type shader, 1621 unsigned start_slot, unsigned count, 1622 const struct pipe_shader_buffer *buffers, 1623 unsigned writable_bitmask) 1624{ 1625 struct d3d12_context *ctx = d3d12_context(pctx); 1626 for (unsigned i = 0; i < count; ++i) { 1627 struct pipe_shader_buffer *slot = &ctx->ssbo_views[shader][i + start_slot]; 1628 if (slot->buffer) { 1629 d3d12_decrement_ssbo_bind_count(ctx, shader, d3d12_resource(slot->buffer)); 1630 pipe_resource_reference(&slot->buffer, NULL); 1631 } 1632 1633 if (buffers && buffers[i].buffer) { 1634 pipe_resource_reference(&slot->buffer, buffers[i].buffer); 1635 slot->buffer_offset = buffers[i].buffer_offset; 1636 slot->buffer_size = buffers[i].buffer_size; 1637 d3d12_increment_ssbo_bind_count(ctx, shader, d3d12_resource(buffers[i].buffer)); 1638 } else 1639 memset(slot, 0, sizeof(*slot)); 1640 } 1641 1642 if (buffers) { 1643 ctx->num_ssbo_views[shader] = MAX2(ctx->num_ssbo_views[shader], count + start_slot); 1644 } else { 1645 ctx->num_ssbo_views[shader] = 0; 1646 for (int i = start_slot + count - 1; i >= (int)start_slot; --i) { 1647 if (ctx->ssbo_views[shader][i].buffer) { 1648 ctx->num_ssbo_views[shader] = i; 1649 break; 1650 } 1651 } 1652 } 1653 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SSBO; 1654} 1655 1656static void 1657d3d12_decrement_image_bind_count(struct d3d12_context *ctx, 1658 enum pipe_shader_type shader, 1659 struct d3d12_resource *res) { 1660 assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0); 1661 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE]--; 1662} 1663 1664static void 1665d3d12_increment_image_bind_count(struct d3d12_context *ctx, 1666 enum pipe_shader_type shader, 1667 struct d3d12_resource *res) { 1668 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE]++; 1669} 1670 1671static bool 1672is_valid_uav_cast(enum pipe_format resource_format, enum pipe_format view_format) 1673{ 1674 if (view_format != PIPE_FORMAT_R32_UINT && 1675 view_format != PIPE_FORMAT_R32_SINT && 1676 view_format != PIPE_FORMAT_R32_FLOAT) 1677 return false; 1678 switch (d3d12_get_typeless_format(resource_format)) { 1679 case DXGI_FORMAT_R8G8B8A8_TYPELESS: 1680 case DXGI_FORMAT_B8G8R8A8_TYPELESS: 1681 case DXGI_FORMAT_B8G8R8X8_TYPELESS: 1682 case DXGI_FORMAT_R16G16_TYPELESS: 1683 case DXGI_FORMAT_R10G10B10A2_TYPELESS: 1684 return true; 1685 default: 1686 return false; 1687 } 1688} 1689 1690static enum pipe_format 1691get_shader_image_emulation_format(enum pipe_format resource_format) 1692{ 1693#define CASE(f) case DXGI_FORMAT_##f##_TYPELESS: return PIPE_FORMAT_##f##_UINT 1694 switch (d3d12_get_typeless_format(resource_format)) { 1695 CASE(R8); 1696 CASE(R8G8); 1697 CASE(R8G8B8A8); 1698 CASE(R16); 1699 CASE(R16G16); 1700 CASE(R16G16B16A16); 1701 CASE(R32); 1702 CASE(R32G32); 1703 CASE(R32G32B32A32); 1704 CASE(R10G10B10A2); 1705 case DXGI_FORMAT_R11G11B10_FLOAT: 1706 return PIPE_FORMAT_R11G11B10_FLOAT; 1707 default: 1708 unreachable("Unexpected shader image resource format"); 1709 } 1710} 1711 1712static void 1713d3d12_set_shader_images(struct pipe_context *pctx, 1714 enum pipe_shader_type shader, 1715 unsigned start_slot, unsigned count, 1716 unsigned unbind_num_trailing_slots, 1717 const struct pipe_image_view *images) 1718{ 1719 struct d3d12_context *ctx = d3d12_context(pctx); 1720 for (unsigned i = 0; i < count + unbind_num_trailing_slots; ++i) { 1721 struct pipe_image_view *slot = &ctx->image_views[shader][i + start_slot]; 1722 if (slot->resource) { 1723 d3d12_decrement_image_bind_count(ctx, shader, d3d12_resource(slot->resource)); 1724 pipe_resource_reference(&slot->resource, NULL); 1725 } 1726 1727 ctx->image_view_emulation_formats[shader][i] = PIPE_FORMAT_NONE; 1728 if (i < count && images && images[i].resource) { 1729 pipe_resource_reference(&slot->resource, images[i].resource); 1730 *slot = images[i]; 1731 d3d12_increment_image_bind_count(ctx, shader, d3d12_resource(images[i].resource)); 1732 1733 if (images[i].resource->target != PIPE_BUFFER && 1734 !is_valid_uav_cast(images[i].resource->format, images[i].format) && 1735 d3d12_get_typeless_format(images[i].format) != 1736 d3d12_get_typeless_format(images[i].resource->format)) { 1737 /* Can't use D3D casting, have to use shader lowering instead */ 1738 ctx->image_view_emulation_formats[shader][i] = 1739 get_shader_image_emulation_format(images[i].resource->format); 1740 } 1741 } else 1742 memset(slot, 0, sizeof(*slot)); 1743 } 1744 1745 if (images) { 1746 ctx->num_image_views[shader] = MAX2(ctx->num_image_views[shader], count + start_slot); 1747 } else { 1748 ctx->num_image_views[shader] = 0; 1749 for (int i = start_slot + count - 1; i >= (int)start_slot; --i) { 1750 if (ctx->image_views[shader][i].resource) { 1751 ctx->num_image_views[shader] = i; 1752 break; 1753 } 1754 } 1755 } 1756 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_IMAGE; 1757} 1758 1759void 1760d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resource *res) { 1761 // For each shader type, if the resource is currently bound as CBV, SRV, or UAV 1762 // set the context shader_dirty bit. 1763 for (uint i = 0; i < PIPE_SHADER_TYPES; ++i) { 1764 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0) { 1765 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF; 1766 } 1767 1768 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0) { 1769 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; 1770 } 1771 1772 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SSBO] > 0) { 1773 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO; 1774 } 1775 1776 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0) { 1777 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE; 1778 } 1779 } 1780} 1781 1782bool 1783d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor) 1784{ 1785 if (ctx->fake_so_buffer_factor == factor) 1786 return true; 1787 1788 d3d12_disable_fake_so_buffers(ctx); 1789 1790 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 1791 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i]; 1792 struct d3d12_stream_output_target *fake_target; 1793 1794 fake_target = CALLOC_STRUCT(d3d12_stream_output_target); 1795 if (!fake_target) 1796 return false; 1797 pipe_reference_init(&fake_target->base.reference, 1); 1798 fake_target->base.context = &ctx->base; 1799 1800 d3d12_resource_wait_idle(ctx, d3d12_resource(target->base.buffer), false); 1801 1802 /* Check if another target is using the same buffer */ 1803 for (unsigned j = 0; j < i; ++j) { 1804 if (ctx->so_targets[j] && ctx->so_targets[j]->buffer == target->base.buffer) { 1805 struct d3d12_stream_output_target *prev_target = 1806 (struct d3d12_stream_output_target *)ctx->fake_so_targets[j]; 1807 pipe_resource_reference(&fake_target->base.buffer, prev_target->base.buffer); 1808 pipe_resource_reference(&fake_target->fill_buffer, prev_target->fill_buffer); 1809 fake_target->fill_buffer_offset = prev_target->fill_buffer_offset; 1810 break; 1811 } 1812 } 1813 1814 /* Create new SO buffer 6x (2 triangles instead of 1 point) the original size if not */ 1815 if (!fake_target->base.buffer) { 1816 fake_target->base.buffer = pipe_buffer_create(ctx->base.screen, 1817 PIPE_BIND_STREAM_OUTPUT, 1818 PIPE_USAGE_STAGING, 1819 target->base.buffer->width0 * factor); 1820 u_suballocator_alloc(&ctx->so_allocator, sizeof(uint32_t) * 5, 256, 1821 &fake_target->fill_buffer_offset, &fake_target->fill_buffer); 1822 update_so_fill_buffer_count(ctx, fake_target->fill_buffer, fake_target->fill_buffer_offset, 0); 1823 } 1824 1825 fake_target->base.buffer_offset = target->base.buffer_offset * factor; 1826 /* TODO: This will mess with SO statistics/overflow queries, but we're already missing things there */ 1827 fake_target->base.buffer_size = target->base.buffer_size * factor; 1828 ctx->fake_so_targets[i] = &fake_target->base; 1829 fill_stream_output_buffer_view(&ctx->fake_so_buffer_views[i], fake_target); 1830 } 1831 1832 ctx->fake_so_buffer_factor = factor; 1833 ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1834 1835 return true; 1836} 1837 1838bool 1839d3d12_disable_fake_so_buffers(struct d3d12_context *ctx) 1840{ 1841 if (ctx->fake_so_buffer_factor == 0) 1842 return true; 1843 1844 d3d12_flush_cmdlist_and_wait(ctx); 1845 1846 bool cs_state_saved = false; 1847 d3d12_compute_transform_save_restore save; 1848 1849 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 1850 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i]; 1851 struct d3d12_stream_output_target *fake_target = (struct d3d12_stream_output_target *)ctx->fake_so_targets[i]; 1852 1853 if (fake_target == NULL) 1854 continue; 1855 1856 if (!cs_state_saved) { 1857 cs_state_saved = true; 1858 d3d12_save_compute_transform_state(ctx, &save); 1859 } 1860 1861 d3d12_compute_transform_key key; 1862 memset(&key, 0, sizeof(key)); 1863 key.type = d3d12_compute_transform_type::fake_so_buffer_vertex_count; 1864 ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key)); 1865 1866 ctx->transform_state_vars[0] = ctx->gfx_pipeline_state.so_info.stride[i]; 1867 ctx->transform_state_vars[1] = ctx->fake_so_buffer_factor; 1868 1869 pipe_shader_buffer new_cs_ssbos[3]; 1870 new_cs_ssbos[0].buffer = fake_target->fill_buffer; 1871 new_cs_ssbos[0].buffer_offset = fake_target->fill_buffer_offset; 1872 new_cs_ssbos[0].buffer_size = fake_target->fill_buffer->width0 - fake_target->fill_buffer_offset; 1873 1874 new_cs_ssbos[1].buffer = target->fill_buffer; 1875 new_cs_ssbos[1].buffer_offset = target->fill_buffer_offset; 1876 new_cs_ssbos[1].buffer_size = target->fill_buffer->width0 - target->fill_buffer_offset; 1877 ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 2, new_cs_ssbos, 2); 1878 1879 pipe_grid_info grid = {}; 1880 grid.block[0] = grid.block[1] = grid.block[2] = 1; 1881 grid.grid[0] = grid.grid[1] = grid.grid[2] = 1; 1882 ctx->base.launch_grid(&ctx->base, &grid); 1883 1884 key.type = d3d12_compute_transform_type::fake_so_buffer_copy_back; 1885 key.fake_so_buffer_copy_back.stride = ctx->gfx_pipeline_state.so_info.stride[i]; 1886 for (unsigned j = 0; j < ctx->gfx_pipeline_state.so_info.num_outputs; ++j) { 1887 auto& output = ctx->gfx_pipeline_state.so_info.output[j]; 1888 if (output.output_buffer != i) 1889 continue; 1890 1891 if (key.fake_so_buffer_copy_back.num_ranges > 0) { 1892 auto& last_range = key.fake_so_buffer_copy_back.ranges[key.fake_so_buffer_copy_back.num_ranges - 1]; 1893 if (output.dst_offset * 4 == last_range.offset + last_range.size) { 1894 last_range.size += output.num_components * 4; 1895 continue; 1896 } 1897 } 1898 1899 auto& new_range = key.fake_so_buffer_copy_back.ranges[key.fake_so_buffer_copy_back.num_ranges++]; 1900 new_range.offset = output.dst_offset * 4; 1901 new_range.size = output.num_components * 4; 1902 } 1903 ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key)); 1904 1905 ctx->transform_state_vars[0] = ctx->fake_so_buffer_factor; 1906 1907 new_cs_ssbos[0].buffer = target->base.buffer; 1908 new_cs_ssbos[0].buffer_offset = target->base.buffer_offset; 1909 new_cs_ssbos[0].buffer_size = target->base.buffer_size; 1910 new_cs_ssbos[1].buffer = fake_target->base.buffer; 1911 new_cs_ssbos[1].buffer_offset = fake_target->base.buffer_offset; 1912 new_cs_ssbos[1].buffer_size = fake_target->base.buffer_size; 1913 ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 2, new_cs_ssbos, 2); 1914 1915 pipe_constant_buffer cbuf = {}; 1916 cbuf.buffer = fake_target->fill_buffer; 1917 cbuf.buffer_offset = fake_target->fill_buffer_offset; 1918 cbuf.buffer_size = fake_target->fill_buffer->width0 - cbuf.buffer_offset; 1919 ctx->base.set_constant_buffer(&ctx->base, PIPE_SHADER_COMPUTE, 1, false, &cbuf); 1920 1921 grid.indirect = fake_target->fill_buffer; 1922 grid.indirect_offset = fake_target->fill_buffer_offset + 4; 1923 ctx->base.launch_grid(&ctx->base, &grid); 1924 1925 pipe_so_target_reference(&ctx->fake_so_targets[i], NULL); 1926 ctx->fake_so_buffer_views[i].SizeInBytes = 0; 1927 1928 /* Make sure the buffer is not copied twice */ 1929 for (unsigned j = i + 1; j <= ctx->gfx_pipeline_state.num_so_targets; ++j) { 1930 if (ctx->so_targets[j] && ctx->so_targets[j]->buffer == target->base.buffer) 1931 pipe_so_target_reference(&ctx->fake_so_targets[j], NULL); 1932 } 1933 } 1934 1935 ctx->fake_so_buffer_factor = 0; 1936 ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1937 1938 if (cs_state_saved) 1939 d3d12_restore_compute_transform_state(ctx, &save); 1940 1941 return true; 1942} 1943 1944void 1945d3d12_flush_cmdlist(struct d3d12_context *ctx) 1946{ 1947 d3d12_end_batch(ctx, d3d12_current_batch(ctx)); 1948 1949 ctx->current_batch_idx++; 1950 if (ctx->current_batch_idx == ARRAY_SIZE(ctx->batches)) 1951 ctx->current_batch_idx = 0; 1952 1953 d3d12_start_batch(ctx, d3d12_current_batch(ctx)); 1954} 1955 1956void 1957d3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx) 1958{ 1959 struct d3d12_batch *batch = d3d12_current_batch(ctx); 1960 1961 d3d12_foreach_submitted_batch(ctx, old_batch) 1962 d3d12_reset_batch(ctx, old_batch, PIPE_TIMEOUT_INFINITE); 1963 d3d12_flush_cmdlist(ctx); 1964 d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE); 1965} 1966 1967static void 1968d3d12_clear_render_target(struct pipe_context *pctx, 1969 struct pipe_surface *psurf, 1970 const union pipe_color_union *color, 1971 unsigned dstx, unsigned dsty, 1972 unsigned width, unsigned height, 1973 bool render_condition_enabled) 1974{ 1975 struct d3d12_context *ctx = d3d12_context(pctx); 1976 struct d3d12_surface *surf = d3d12_surface(psurf); 1977 1978 if (!render_condition_enabled && ctx->current_predication) 1979 ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); 1980 1981 struct d3d12_resource *res = d3d12_resource(psurf->texture); 1982 d3d12_transition_resource_state(ctx, res, 1983 D3D12_RESOURCE_STATE_RENDER_TARGET, 1984 D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 1985 d3d12_apply_resource_states(ctx, false); 1986 1987 enum pipe_format format = psurf->texture->format; 1988 float clear_color[4]; 1989 1990 if (util_format_is_pure_uint(format)) { 1991 for (int c = 0; c < 4; ++c) 1992 clear_color[c] = color->ui[c]; 1993 } else if (util_format_is_pure_sint(format)) { 1994 for (int c = 0; c < 4; ++c) 1995 clear_color[c] = color->i[c]; 1996 } else { 1997 for (int c = 0; c < 4; ++c) 1998 clear_color[c] = color->f[c]; 1999 } 2000 2001 if (!(util_format_colormask(util_format_description(psurf->texture->format)) & 2002 PIPE_MASK_A)) 2003 clear_color[3] = 1.0f; 2004 2005 D3D12_RECT rect = { (int)dstx, (int)dsty, 2006 (int)dstx + (int)width, 2007 (int)dsty + (int)height }; 2008 ctx->cmdlist->ClearRenderTargetView(surf->desc_handle.cpu_handle, 2009 clear_color, 1, &rect); 2010 2011 d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf); 2012 2013 if (!render_condition_enabled && ctx->current_predication) { 2014 d3d12_enable_predication(ctx); 2015 } 2016} 2017 2018static void 2019d3d12_clear_depth_stencil(struct pipe_context *pctx, 2020 struct pipe_surface *psurf, 2021 unsigned clear_flags, 2022 double depth, 2023 unsigned stencil, 2024 unsigned dstx, unsigned dsty, 2025 unsigned width, unsigned height, 2026 bool render_condition_enabled) 2027{ 2028 struct d3d12_context *ctx = d3d12_context(pctx); 2029 struct d3d12_surface *surf = d3d12_surface(psurf); 2030 2031 if (!render_condition_enabled && ctx->current_predication) 2032 ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); 2033 2034 D3D12_CLEAR_FLAGS flags = (D3D12_CLEAR_FLAGS)0; 2035 if (clear_flags & PIPE_CLEAR_DEPTH) 2036 flags |= D3D12_CLEAR_FLAG_DEPTH; 2037 if (clear_flags & PIPE_CLEAR_STENCIL) 2038 flags |= D3D12_CLEAR_FLAG_STENCIL; 2039 2040 struct d3d12_resource *res = d3d12_resource(ctx->fb.zsbuf->texture); 2041 d3d12_transition_resource_state(ctx, res, 2042 D3D12_RESOURCE_STATE_DEPTH_WRITE, 2043 D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 2044 d3d12_apply_resource_states(ctx, false); 2045 2046 D3D12_RECT rect = { (int)dstx, (int)dsty, 2047 (int)dstx + (int)width, 2048 (int)dsty + (int)height }; 2049 ctx->cmdlist->ClearDepthStencilView(surf->desc_handle.cpu_handle, flags, 2050 depth, stencil, 1, &rect); 2051 2052 d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf); 2053 2054 if (!render_condition_enabled && ctx->current_predication) { 2055 d3d12_enable_predication(ctx); 2056 } 2057} 2058 2059static void 2060d3d12_clear(struct pipe_context *pctx, 2061 unsigned buffers, 2062 const struct pipe_scissor_state *scissor_state, 2063 const union pipe_color_union *color, 2064 double depth, unsigned stencil) 2065{ 2066 struct d3d12_context *ctx = d3d12_context(pctx); 2067 2068 if (buffers & PIPE_CLEAR_COLOR) { 2069 for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 2070 if (buffers & (PIPE_CLEAR_COLOR0 << i)) { 2071 struct pipe_surface *psurf = ctx->fb.cbufs[i]; 2072 d3d12_clear_render_target(pctx, psurf, color, 2073 0, 0, psurf->width, psurf->height, 2074 true); 2075 } 2076 } 2077 } 2078 2079 if (buffers & PIPE_CLEAR_DEPTHSTENCIL && ctx->fb.zsbuf) { 2080 struct pipe_surface *psurf = ctx->fb.zsbuf; 2081 d3d12_clear_depth_stencil(pctx, psurf, 2082 buffers & PIPE_CLEAR_DEPTHSTENCIL, 2083 depth, stencil, 2084 0, 0, psurf->width, psurf->height, 2085 true); 2086 } 2087} 2088 2089static void 2090d3d12_flush(struct pipe_context *pipe, 2091 struct pipe_fence_handle **fence, 2092 unsigned flags) 2093{ 2094 struct d3d12_context *ctx = d3d12_context(pipe); 2095 struct d3d12_batch *batch = d3d12_current_batch(ctx); 2096 2097 d3d12_flush_cmdlist(ctx); 2098 2099 if (fence) 2100 d3d12_fence_reference((struct d3d12_fence **)fence, batch->fence); 2101} 2102 2103static void 2104d3d12_flush_resource(struct pipe_context *pctx, 2105 struct pipe_resource *pres) 2106{ 2107 struct d3d12_context *ctx = d3d12_context(pctx); 2108 struct d3d12_resource *res = d3d12_resource(pres); 2109 2110 d3d12_transition_resource_state(ctx, res, 2111 D3D12_RESOURCE_STATE_COMMON, 2112 D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 2113 d3d12_apply_resource_states(ctx, false); 2114} 2115 2116static void 2117d3d12_signal(struct pipe_context *pipe, 2118 struct pipe_fence_handle *pfence) 2119{ 2120 struct d3d12_screen *screen = d3d12_screen(pipe->screen); 2121 struct d3d12_fence *fence = d3d12_fence(pfence); 2122 d3d12_flush_cmdlist(d3d12_context(pipe)); 2123 screen->cmdqueue->Signal(fence->cmdqueue_fence, fence->value); 2124} 2125 2126static void 2127d3d12_wait(struct pipe_context *pipe, struct pipe_fence_handle *pfence) 2128{ 2129 struct d3d12_screen *screen = d3d12_screen(pipe->screen); 2130 struct d3d12_fence *fence = d3d12_fence(pfence); 2131 d3d12_flush_cmdlist(d3d12_context(pipe)); 2132 screen->cmdqueue->Wait(fence->cmdqueue_fence, fence->value); 2133} 2134 2135static void 2136d3d12_init_null_sampler(struct d3d12_context *ctx) 2137{ 2138 struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 2139 2140 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ctx->null_sampler); 2141 2142 D3D12_SAMPLER_DESC desc; 2143 desc.Filter = D3D12_FILTER_ANISOTROPIC; 2144 desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 2145 desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 2146 desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 2147 desc.MipLODBias = 0.0f; 2148 desc.MaxAnisotropy = 0; 2149 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; 2150 desc.MinLOD = 0.0f; 2151 desc.MaxLOD = 0.0f; 2152 memset(desc.BorderColor, 0, sizeof(desc.BorderColor)); 2153 screen->dev->CreateSampler(&desc, ctx->null_sampler.cpu_handle); 2154} 2155 2156static uint64_t 2157d3d12_get_timestamp(struct pipe_context *pctx) 2158{ 2159 struct d3d12_context *ctx = d3d12_context(pctx); 2160 2161 if (!ctx->timestamp_query) 2162 ctx->timestamp_query = pctx->create_query(pctx, PIPE_QUERY_TIMESTAMP, 0); 2163 2164 pipe_query_result result; 2165 pctx->end_query(pctx, ctx->timestamp_query); 2166 pctx->get_query_result(pctx, ctx->timestamp_query, true, &result); 2167 return result.u64; 2168} 2169 2170static void 2171d3d12_rebind_buffer(struct d3d12_context *ctx, struct d3d12_resource *res) 2172{ 2173 if (res->base.b.bind & PIPE_BIND_VERTEX_BUFFER) { 2174 for (unsigned i = 0; i < ctx->num_vbs; ++i) { 2175 struct pipe_vertex_buffer *buf = &ctx->vbs[i]; 2176 2177 if (!buf->is_user_buffer && &res->base.b == buf->buffer.resource) { 2178 ctx->vbvs[i].BufferLocation = d3d12_resource_gpu_virtual_address(res) + buf->buffer_offset; 2179 ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS; 2180 } 2181 } 2182 } 2183 2184 if (res->base.b.bind & PIPE_BIND_STREAM_OUTPUT) { 2185 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 2186 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i]; 2187 assert(!target || target->fill_buffer != &res->base.b); 2188 if (target && target->base.buffer == &res->base.b) { 2189 fill_stream_output_buffer_view(&ctx->so_buffer_views[i], target); 2190 ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 2191 } 2192 2193 assert(!ctx->fake_so_targets[i] || ctx->fake_so_targets[i]->buffer != &res->base.b); 2194 } 2195 } 2196 2197 d3d12_invalidate_context_bindings(ctx, res); 2198} 2199 2200static void 2201d3d12_replace_buffer_storage(struct pipe_context *pctx, 2202 struct pipe_resource *pdst, 2203 struct pipe_resource *psrc, 2204 unsigned minimum_num_rebinds, 2205 uint32_t rebind_mask, 2206 uint32_t delete_buffer_id) 2207{ 2208 struct d3d12_context *ctx = d3d12_context(pctx); 2209 struct d3d12_resource *dst = d3d12_resource(pdst); 2210 struct d3d12_resource *src = d3d12_resource(psrc); 2211 2212 struct d3d12_bo *old_bo = dst->bo; 2213 d3d12_bo_reference(src->bo); 2214 dst->bo = src->bo; 2215 p_atomic_inc(&dst->generation_id); 2216 d3d12_rebind_buffer(ctx, dst); 2217 d3d12_bo_unreference(old_bo); 2218} 2219 2220static void 2221d3d12_memory_barrier(struct pipe_context *pctx, unsigned flags) 2222{ 2223 struct d3d12_context *ctx = d3d12_context(pctx); 2224 if (flags & PIPE_BARRIER_VERTEX_BUFFER) 2225 ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS; 2226 if (flags & PIPE_BARRIER_INDEX_BUFFER) 2227 ctx->state_dirty |= D3D12_DIRTY_INDEX_BUFFER; 2228 if (flags & PIPE_BARRIER_FRAMEBUFFER) 2229 ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER; 2230 if (flags & PIPE_BARRIER_STREAMOUT_BUFFER) 2231 ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 2232 2233 /* TODO: 2234 * PIPE_BARRIER_INDIRECT_BUFFER 2235 */ 2236 2237 for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 2238 if (flags & PIPE_BARRIER_CONSTANT_BUFFER) 2239 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF; 2240 if (flags & PIPE_BARRIER_TEXTURE) 2241 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; 2242 if (flags & PIPE_BARRIER_SHADER_BUFFER) 2243 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO; 2244 if (flags & PIPE_BARRIER_IMAGE) 2245 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE; 2246 } 2247 2248 /* Indicate that UAVs shouldn't override transitions. Ignore barriers that are only 2249 * for UAVs or other fixed-function state that doesn't need a draw to resolve. 2250 */ 2251 const unsigned ignored_barrier_flags = 2252 PIPE_BARRIER_IMAGE | 2253 PIPE_BARRIER_SHADER_BUFFER | 2254 PIPE_BARRIER_UPDATE | 2255 PIPE_BARRIER_MAPPED_BUFFER | 2256 PIPE_BARRIER_QUERY_BUFFER; 2257 d3d12_current_batch(ctx)->pending_memory_barrier = (flags & ~ignored_barrier_flags) != 0; 2258 2259 if (flags & (PIPE_BARRIER_IMAGE | PIPE_BARRIER_SHADER_BUFFER)) { 2260 D3D12_RESOURCE_BARRIER uavBarrier; 2261 uavBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; 2262 uavBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; 2263 uavBarrier.UAV.pResource = nullptr; 2264 ctx->cmdlist->ResourceBarrier(1, &uavBarrier); 2265 } 2266} 2267 2268static void 2269d3d12_get_sample_position(struct pipe_context *pctx, unsigned sample_count, unsigned sample_index, 2270 float *positions) 2271{ 2272 /* Sample patterns transcribed from 2273 * https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels 2274 */ 2275 static const int sample_pattern_1sample[2] = { 0, 0 }; 2276 static const int sample_pattern_2samples[2][2] = { 2277 { 4, 4 }, 2278 { -4, -4 }, 2279 }; 2280 static const int sample_pattern_4samples[4][2] = { 2281 { -2, -6 }, 2282 { 6, -2 }, 2283 { -6, 2 }, 2284 { 2, 6 }, 2285 }; 2286 static const int sample_pattern_8samples[8][2] = { 2287 { 1, -3 }, 2288 { -1, 3 }, 2289 { 5, 1 }, 2290 { -3, -5 }, 2291 { -5, 5 }, 2292 { -7, -1 }, 2293 { 3, 7 }, 2294 { 7, -7 }, 2295 }; 2296 static const int sample_pattern_16samples[16][2] = { 2297 { 1, 1 }, 2298 { -1, -3 }, 2299 { -3, 2 }, 2300 { 4, -1 }, 2301 { -5, -2 }, 2302 { 2, 5 }, 2303 { 5, 3 }, 2304 { 3, -5 }, 2305 { -2, 6 }, 2306 { 0, -7 }, 2307 { -4, -6 }, 2308 { -6, 4 }, 2309 { -8, 0 }, 2310 { 7, -4 }, 2311 { 6, 7 }, 2312 { -7, -8 }, 2313 }; 2314 const int *samples; 2315 switch (sample_count) { 2316 case 1: 2317 default: 2318 samples = sample_pattern_1sample; 2319 break; 2320 case 2: 2321 samples = sample_pattern_2samples[sample_index]; 2322 break; 2323 case 4: 2324 samples = sample_pattern_4samples[sample_index]; 2325 break; 2326 case 8: 2327 samples = sample_pattern_8samples[sample_index]; 2328 break; 2329 case 16: 2330 samples = sample_pattern_16samples[sample_index]; 2331 break; 2332 } 2333 2334 /* GL coords go from 0 -> 1, D3D from -0.5 -> 0.5 */ 2335 for (unsigned i = 0; i < 2; ++i) 2336 positions[i] = (float)(samples[i] + 8) / 16.0f; 2337} 2338 2339static void 2340d3d12_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices) 2341{ 2342 struct d3d12_context *ctx = d3d12_context(pctx); 2343 ctx->patch_vertices = patch_vertices; 2344 ctx->cmdlist_dirty |= D3D12_DIRTY_PRIM_MODE; 2345} 2346 2347static void 2348d3d12_set_tess_state(struct pipe_context *pctx, 2349 const float default_outer_level[4], 2350 const float default_inner_level[2]) 2351{ 2352 struct d3d12_context *ctx = d3d12_context(pctx); 2353 memcpy(ctx->default_outer_tess_factor, default_outer_level, sizeof(ctx->default_outer_tess_factor)); 2354 memcpy(ctx->default_inner_tess_factor, default_inner_level, sizeof(ctx->default_inner_tess_factor)); 2355} 2356 2357static enum pipe_reset_status 2358d3d12_get_reset_status(struct pipe_context *pctx) 2359{ 2360 struct d3d12_screen *screen = d3d12_screen(pctx->screen); 2361 HRESULT hr = screen->dev->GetDeviceRemovedReason(); 2362 switch (hr) { 2363 case DXGI_ERROR_DEVICE_HUNG: 2364 case DXGI_ERROR_INVALID_CALL: 2365 return PIPE_GUILTY_CONTEXT_RESET; 2366 case DXGI_ERROR_DEVICE_RESET: 2367 return PIPE_INNOCENT_CONTEXT_RESET; 2368 default: 2369 return SUCCEEDED(hr) ? PIPE_NO_RESET : PIPE_UNKNOWN_CONTEXT_RESET; 2370 } 2371} 2372 2373#ifdef HAVE_GALLIUM_D3D12_VIDEO 2374struct pipe_video_codec* 2375d3d12_video_create_codec(struct pipe_context *context, 2376 const struct pipe_video_codec *templat) 2377{ 2378 if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 2379 return d3d12_video_encoder_create_encoder(context, templat); 2380 } else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { 2381 return d3d12_video_create_decoder(context, templat); 2382 } else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) { 2383 return d3d12_video_processor_create(context, templat); 2384 } else { 2385 debug_printf("D3D12: Unsupported video codec entrypoint %d\n", templat->entrypoint); 2386 return nullptr; 2387 } 2388} 2389#endif 2390 2391struct pipe_context * 2392d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) 2393{ 2394 struct d3d12_screen *screen = d3d12_screen(pscreen); 2395 if (FAILED(screen->dev->GetDeviceRemovedReason())) { 2396 /* Attempt recovery, but this may fail */ 2397 screen->deinit(screen); 2398 if (!screen->init(screen)) { 2399 debug_printf("D3D12: failed to reset screen\n"); 2400 return nullptr; 2401 } 2402 } 2403 2404 struct d3d12_context *ctx = CALLOC_STRUCT(d3d12_context); 2405 if (!ctx) 2406 return NULL; 2407 2408 ctx->base.screen = pscreen; 2409 ctx->base.priv = priv; 2410 2411 ctx->base.destroy = d3d12_context_destroy; 2412 2413 ctx->base.create_vertex_elements_state = d3d12_create_vertex_elements_state; 2414 ctx->base.bind_vertex_elements_state = d3d12_bind_vertex_elements_state; 2415 ctx->base.delete_vertex_elements_state = d3d12_delete_vertex_elements_state; 2416 2417 ctx->base.create_blend_state = d3d12_create_blend_state; 2418 ctx->base.bind_blend_state = d3d12_bind_blend_state; 2419 ctx->base.delete_blend_state = d3d12_delete_blend_state; 2420 2421 ctx->base.create_depth_stencil_alpha_state = d3d12_create_depth_stencil_alpha_state; 2422 ctx->base.bind_depth_stencil_alpha_state = d3d12_bind_depth_stencil_alpha_state; 2423 ctx->base.delete_depth_stencil_alpha_state = d3d12_delete_depth_stencil_alpha_state; 2424 2425 ctx->base.create_rasterizer_state = d3d12_create_rasterizer_state; 2426 ctx->base.bind_rasterizer_state = d3d12_bind_rasterizer_state; 2427 ctx->base.delete_rasterizer_state = d3d12_delete_rasterizer_state; 2428 2429 ctx->base.create_sampler_state = d3d12_create_sampler_state; 2430 ctx->base.bind_sampler_states = d3d12_bind_sampler_states; 2431 ctx->base.delete_sampler_state = d3d12_delete_sampler_state; 2432 2433 ctx->base.create_sampler_view = d3d12_create_sampler_view; 2434 ctx->base.set_sampler_views = d3d12_set_sampler_views; 2435 ctx->base.sampler_view_destroy = d3d12_destroy_sampler_view; 2436 2437 ctx->base.create_vs_state = d3d12_create_vs_state; 2438 ctx->base.bind_vs_state = d3d12_bind_vs_state; 2439 ctx->base.delete_vs_state = d3d12_delete_vs_state; 2440 2441 ctx->base.create_fs_state = d3d12_create_fs_state; 2442 ctx->base.bind_fs_state = d3d12_bind_fs_state; 2443 ctx->base.delete_fs_state = d3d12_delete_fs_state; 2444 2445 ctx->base.create_gs_state = d3d12_create_gs_state; 2446 ctx->base.bind_gs_state = d3d12_bind_gs_state; 2447 ctx->base.delete_gs_state = d3d12_delete_gs_state; 2448 2449 ctx->base.create_tcs_state = d3d12_create_tcs_state; 2450 ctx->base.bind_tcs_state = d3d12_bind_tcs_state; 2451 ctx->base.delete_tcs_state = d3d12_delete_tcs_state; 2452 2453 ctx->base.create_tes_state = d3d12_create_tes_state; 2454 ctx->base.bind_tes_state = d3d12_bind_tes_state; 2455 ctx->base.delete_tes_state = d3d12_delete_tes_state; 2456 2457 ctx->base.set_patch_vertices = d3d12_set_patch_vertices; 2458 ctx->base.set_tess_state = d3d12_set_tess_state; 2459 2460 ctx->base.create_compute_state = d3d12_create_compute_state; 2461 ctx->base.bind_compute_state = d3d12_bind_compute_state; 2462 ctx->base.delete_compute_state = d3d12_delete_compute_state; 2463 2464 ctx->base.set_polygon_stipple = d3d12_set_polygon_stipple; 2465 ctx->base.set_vertex_buffers = d3d12_set_vertex_buffers; 2466 ctx->base.set_viewport_states = d3d12_set_viewport_states; 2467 ctx->base.set_scissor_states = d3d12_set_scissor_states; 2468 ctx->base.set_constant_buffer = d3d12_set_constant_buffer; 2469 ctx->base.set_framebuffer_state = d3d12_set_framebuffer_state; 2470 ctx->base.set_clip_state = d3d12_set_clip_state; 2471 ctx->base.set_blend_color = d3d12_set_blend_color; 2472 ctx->base.set_sample_mask = d3d12_set_sample_mask; 2473 ctx->base.set_stencil_ref = d3d12_set_stencil_ref; 2474 2475 ctx->base.create_stream_output_target = d3d12_create_stream_output_target; 2476 ctx->base.stream_output_target_destroy = d3d12_stream_output_target_destroy; 2477 ctx->base.set_stream_output_targets = d3d12_set_stream_output_targets; 2478 2479 ctx->base.set_shader_buffers = d3d12_set_shader_buffers; 2480 ctx->base.set_shader_images = d3d12_set_shader_images; 2481 2482 ctx->base.get_timestamp = d3d12_get_timestamp; 2483 2484 ctx->base.clear = d3d12_clear; 2485 ctx->base.clear_render_target = d3d12_clear_render_target; 2486 ctx->base.clear_depth_stencil = d3d12_clear_depth_stencil; 2487 ctx->base.draw_vbo = d3d12_draw_vbo; 2488 ctx->base.launch_grid = d3d12_launch_grid; 2489 ctx->base.flush = d3d12_flush; 2490 ctx->base.flush_resource = d3d12_flush_resource; 2491 2492 ctx->base.fence_server_signal = d3d12_signal; 2493 ctx->base.fence_server_sync = d3d12_wait; 2494 2495 ctx->base.memory_barrier = d3d12_memory_barrier; 2496 2497 ctx->base.get_sample_position = d3d12_get_sample_position; 2498 2499 ctx->base.get_device_reset_status = d3d12_get_reset_status; 2500 2501 ctx->gfx_pipeline_state.sample_mask = ~0; 2502 2503 d3d12_context_surface_init(&ctx->base); 2504 d3d12_context_resource_init(&ctx->base); 2505 d3d12_context_query_init(&ctx->base); 2506 d3d12_context_blit_init(&ctx->base); 2507 2508#ifdef HAVE_GALLIUM_D3D12_VIDEO 2509 // Add d3d12 video functions entrypoints 2510 ctx->base.create_video_codec = d3d12_video_create_codec; 2511 ctx->base.create_video_buffer = d3d12_video_buffer_create; 2512#endif 2513 slab_create_child(&ctx->transfer_pool, &d3d12_screen(pscreen)->transfer_pool); 2514 slab_create_child(&ctx->transfer_pool_unsync, &d3d12_screen(pscreen)->transfer_pool); 2515 2516 ctx->base.stream_uploader = u_upload_create_default(&ctx->base); 2517 ctx->base.const_uploader = u_upload_create_default(&ctx->base); 2518 u_suballocator_init(&ctx->so_allocator, &ctx->base, 4096, 0, 2519 PIPE_USAGE_DEFAULT, 2520 0, false); 2521 2522 struct primconvert_config cfg = {}; 2523 cfg.primtypes_mask = 1 << PIPE_PRIM_POINTS | 2524 1 << PIPE_PRIM_LINES | 2525 1 << PIPE_PRIM_LINE_STRIP | 2526 1 << PIPE_PRIM_TRIANGLES | 2527 1 << PIPE_PRIM_TRIANGLE_STRIP; 2528 cfg.restart_primtypes_mask = cfg.primtypes_mask; 2529 cfg.fixed_prim_restart = true; 2530 ctx->primconvert = util_primconvert_create_config(&ctx->base, &cfg); 2531 if (!ctx->primconvert) { 2532 debug_printf("D3D12: failed to create primconvert\n"); 2533 return NULL; 2534 } 2535 2536 d3d12_gfx_pipeline_state_cache_init(ctx); 2537 d3d12_compute_pipeline_state_cache_init(ctx); 2538 d3d12_root_signature_cache_init(ctx); 2539 d3d12_cmd_signature_cache_init(ctx); 2540 d3d12_gs_variant_cache_init(ctx); 2541 d3d12_tcs_variant_cache_init(ctx); 2542 d3d12_compute_transform_cache_init(ctx); 2543 d3d12_context_state_table_init(ctx); 2544 2545 util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT); 2546 if (!d3d12_mod) { 2547 debug_printf("D3D12: failed to load D3D12.DLL\n"); 2548 return NULL; 2549 } 2550 ctx->D3D12SerializeVersionedRootSignature = 2551 (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)util_dl_get_proc_address(d3d12_mod, "D3D12SerializeVersionedRootSignature"); 2552 2553 ctx->submit_id = (uint64_t)p_atomic_add_return(&screen->ctx_count, 1) << 32ull; 2554 2555 for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) { 2556 if (!d3d12_init_batch(ctx, &ctx->batches[i])) { 2557 FREE(ctx); 2558 return NULL; 2559 } 2560 } 2561 d3d12_start_batch(ctx, &ctx->batches[0]); 2562 2563 ctx->sampler_pool = d3d12_descriptor_pool_new(screen, 2564 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 2565 64); 2566 if (!ctx->sampler_pool) { 2567 FREE(ctx); 2568 return NULL; 2569 } 2570 d3d12_init_null_sampler(ctx); 2571 2572#ifdef _WIN32 2573 if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL) || 2574 (d3d12_debug & D3D12_DEBUG_DISASS)) 2575 ctx->dxil_validator = dxil_create_validator(NULL); 2576#endif 2577 2578 ctx->blitter = util_blitter_create(&ctx->base); 2579 if (!ctx->blitter) 2580 return NULL; 2581 2582 if (!d3d12_init_polygon_stipple(&ctx->base)) { 2583 debug_printf("D3D12: failed to initialize polygon stipple resources\n"); 2584 FREE(ctx); 2585 return NULL; 2586 } 2587 2588 mtx_lock(&screen->submit_mutex); 2589 list_addtail(&ctx->context_list_entry, &screen->context_list); 2590 mtx_unlock(&screen->submit_mutex); 2591 2592 if (flags & PIPE_CONTEXT_PREFER_THREADED) 2593 return threaded_context_create(&ctx->base, 2594 &screen->transfer_pool, 2595 d3d12_replace_buffer_storage, 2596 NULL, 2597 &ctx->threaded_context); 2598 2599 return &ctx->base; 2600} 2601 2602bool 2603d3d12_need_zero_one_depth_range(struct d3d12_context *ctx) 2604{ 2605 struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 2606 2607 /** 2608 * OpenGL Compatibility spec, section 15.2.3 (Shader Outputs) says 2609 * the following: 2610 * 2611 * For fixed-point depth buffers, the final fragment depth written by 2612 * a fragment shader is first clamped to [0, 1] and then converted to 2613 * fixed-point as if it were a window z value (see section 13.8.1). 2614 * For floating-point depth buffers, conversion is not performed but 2615 * clamping is. Note that the depth range computation is not applied 2616 * here, only the conversion to fixed-point. 2617 * 2618 * However, the D3D11.3 Functional Spec, section 17.10 (Depth Clamp) says 2619 * the following: 2620 * 2621 * Depth values that reach the Output Merger, whether coming from 2622 * interpolation or from Pixel Shader output (replacing the 2623 * interpolated z), are always clamped: 2624 * z = min(Viewport.MaxDepth,max(Viewport.MinDepth,z)) 2625 * following the D3D11 Floating Point Rules(3.1) for min/max. 2626 * 2627 * This means that we can't always use the fixed-function viewport-mapping 2628 * D3D provides. 2629 * 2630 * There's only one case where the difference matters: When the fragment 2631 * shader writes a non-implicit value to gl_FragDepth. In all other 2632 * cases, the fragment either shouldn't have been rasterized in the 2633 * first place, or the implicit gl_FragCoord.z-value should already have 2634 * been clamped to the depth-range. 2635 * 2636 * For simplicity, let's assume that an explicitly written frag-result 2637 * doesn't simply forward the value of gl_FragCoord.z. If it does, we'll 2638 * end up generating needless code, but the result will be correct. 2639 */ 2640 2641 return fs->initial->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH); 2642} 2643