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_context.h" 26#include "d3d12_compiler.h" 27#include "d3d12_debug.h" 28#include "d3d12_fence.h" 29#include "d3d12_format.h" 30#include "d3d12_query.h" 31#include "d3d12_resource.h" 32#include "d3d12_root_signature.h" 33#include "d3d12_screen.h" 34#include "d3d12_surface.h" 35 36#include "util/u_blitter.h" 37#include "util/u_dual_blend.h" 38#include "util/u_framebuffer.h" 39#include "util/u_helpers.h" 40#include "util/u_inlines.h" 41#include "util/u_memory.h" 42#include "util/u_upload_mgr.h" 43#include "util/u_pstipple.h" 44#include "util/u_dl.h" 45#include "nir_to_dxil.h" 46 47#include "D3D12ResourceState.h" 48 49#include <dxguids/dxguids.h> 50 51extern "C" { 52#include "indices/u_primconvert.h" 53} 54 55#include <string.h> 56 57static void 58d3d12_context_destroy(struct pipe_context *pctx) 59{ 60 struct d3d12_context *ctx = d3d12_context(pctx); 61 if (ctx->validation_tools) 62 d3d12_validator_destroy(ctx->validation_tools); 63 64 if (ctx->timestamp_query) 65 pctx->destroy_query(pctx, ctx->timestamp_query); 66 67 util_blitter_destroy(ctx->blitter); 68 d3d12_end_batch(ctx, d3d12_current_batch(ctx)); 69 for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) 70 d3d12_destroy_batch(ctx, &ctx->batches[i]); 71 ctx->cmdlist->Release(); 72 ctx->cmdqueue_fence->Release(); 73 d3d12_descriptor_pool_free(ctx->sampler_pool); 74 util_primconvert_destroy(ctx->primconvert); 75 slab_destroy_child(&ctx->transfer_pool); 76 d3d12_gs_variant_cache_destroy(ctx); 77 d3d12_gfx_pipeline_state_cache_destroy(ctx); 78 d3d12_root_signature_cache_destroy(ctx); 79 80 u_suballocator_destroy(&ctx->query_allocator); 81 82 if (pctx->stream_uploader) 83 u_upload_destroy(pctx->stream_uploader); 84 if (pctx->const_uploader) 85 u_upload_destroy(pctx->const_uploader); 86 87 delete ctx->resource_state_manager; 88 89 FREE(ctx); 90} 91 92static void * 93d3d12_create_vertex_elements_state(struct pipe_context *pctx, 94 unsigned num_elements, 95 const struct pipe_vertex_element *elements) 96{ 97 struct d3d12_vertex_elements_state *cso = CALLOC_STRUCT(d3d12_vertex_elements_state); 98 if (!cso) 99 return NULL; 100 101 for (unsigned i = 0; i < num_elements; ++i) { 102 cso->elements[i].SemanticName = "TEXCOORD"; 103 cso->elements[i].SemanticIndex = i; 104 105 enum pipe_format format_helper = 106 d3d12_emulated_vtx_format((enum pipe_format)elements[i].src_format); 107 bool needs_emulation = format_helper != elements[i].src_format; 108 cso->needs_format_emulation |= needs_emulation; 109 cso->format_conversion[i] = 110 needs_emulation ? (enum pipe_format)elements[i].src_format : PIPE_FORMAT_NONE; 111 112 cso->elements[i].Format = d3d12_get_format(format_helper); 113 assert(cso->elements[i].Format != DXGI_FORMAT_UNKNOWN); 114 cso->elements[i].InputSlot = elements[i].vertex_buffer_index; 115 cso->elements[i].AlignedByteOffset = elements[i].src_offset; 116 117 if (elements[i].instance_divisor) { 118 cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA; 119 cso->elements[i].InstanceDataStepRate = elements[i].instance_divisor; 120 } else { 121 cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; 122 cso->elements[i].InstanceDataStepRate = 0; 123 } 124 } 125 126 cso->num_elements = num_elements; 127 return cso; 128} 129 130static void 131d3d12_bind_vertex_elements_state(struct pipe_context *pctx, 132 void *ve) 133{ 134 struct d3d12_context *ctx = d3d12_context(pctx); 135 ctx->gfx_pipeline_state.ves = (struct d3d12_vertex_elements_state *)ve; 136 ctx->state_dirty |= D3D12_DIRTY_VERTEX_ELEMENTS; 137} 138 139static void 140d3d12_delete_vertex_elements_state(struct pipe_context *pctx, 141 void *ve) 142{ 143 FREE(ve); 144} 145 146static D3D12_BLEND 147blend_factor_rgb(enum pipe_blendfactor factor) 148{ 149 switch (factor) { 150 case PIPE_BLENDFACTOR_ZERO: return D3D12_BLEND_ZERO; 151 case PIPE_BLENDFACTOR_ONE: return D3D12_BLEND_ONE; 152 case PIPE_BLENDFACTOR_SRC_COLOR: return D3D12_BLEND_SRC_COLOR; 153 case PIPE_BLENDFACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA; 154 case PIPE_BLENDFACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA; 155 case PIPE_BLENDFACTOR_DST_COLOR: return D3D12_BLEND_DEST_COLOR; 156 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT; 157 case PIPE_BLENDFACTOR_CONST_COLOR: return D3D12_BLEND_BLEND_FACTOR; 158 case PIPE_BLENDFACTOR_SRC1_COLOR: return D3D12_BLEND_SRC1_COLOR; 159 case PIPE_BLENDFACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA; 160 case PIPE_BLENDFACTOR_INV_SRC_COLOR: return D3D12_BLEND_INV_SRC_COLOR; 161 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA; 162 case PIPE_BLENDFACTOR_INV_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA; 163 case PIPE_BLENDFACTOR_INV_DST_COLOR: return D3D12_BLEND_INV_DEST_COLOR; 164 case PIPE_BLENDFACTOR_INV_CONST_COLOR: return D3D12_BLEND_INV_BLEND_FACTOR; 165 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return D3D12_BLEND_INV_SRC1_COLOR; 166 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA; 167 case PIPE_BLENDFACTOR_CONST_ALPHA: return D3D12_BLEND_BLEND_FACTOR; /* Doesn't exist in D3D12 */ 168 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return D3D12_BLEND_INV_BLEND_FACTOR; /* Doesn't exist in D3D12 */ 169 } 170 unreachable("unexpected blend factor"); 171} 172 173static D3D12_BLEND 174blend_factor_alpha(enum pipe_blendfactor factor) 175{ 176 switch (factor) { 177 case PIPE_BLENDFACTOR_ZERO: return D3D12_BLEND_ZERO; 178 case PIPE_BLENDFACTOR_ONE: return D3D12_BLEND_ONE; 179 case PIPE_BLENDFACTOR_SRC_COLOR: 180 case PIPE_BLENDFACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA; 181 case PIPE_BLENDFACTOR_DST_COLOR: 182 case PIPE_BLENDFACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA; 183 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT; 184 case PIPE_BLENDFACTOR_CONST_COLOR: 185 case PIPE_BLENDFACTOR_CONST_ALPHA: return D3D12_BLEND_BLEND_FACTOR; 186 case PIPE_BLENDFACTOR_SRC1_COLOR: 187 case PIPE_BLENDFACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA; 188 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 189 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA; 190 case PIPE_BLENDFACTOR_INV_DST_COLOR: 191 case PIPE_BLENDFACTOR_INV_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA; 192 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 193 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA; 194 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 195 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return D3D12_BLEND_INV_BLEND_FACTOR; 196 } 197 unreachable("unexpected blend factor"); 198} 199 200static unsigned 201need_blend_factor_rgb(enum pipe_blendfactor factor) 202{ 203 switch (factor) { 204 case PIPE_BLENDFACTOR_CONST_COLOR: 205 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 206 return D3D12_BLEND_FACTOR_COLOR; 207 case PIPE_BLENDFACTOR_CONST_ALPHA: 208 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 209 return D3D12_BLEND_FACTOR_ALPHA; 210 211 default: 212 return D3D12_BLEND_FACTOR_NONE; 213 } 214} 215 216static unsigned 217need_blend_factor_alpha(enum pipe_blendfactor factor) 218{ 219 switch (factor) { 220 case PIPE_BLENDFACTOR_CONST_COLOR: 221 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 222 case PIPE_BLENDFACTOR_CONST_ALPHA: 223 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 224 return D3D12_BLEND_FACTOR_ANY; 225 226 default: 227 return D3D12_BLEND_FACTOR_NONE; 228 } 229} 230 231static D3D12_BLEND_OP 232blend_op(enum pipe_blend_func func) 233{ 234 switch (func) { 235 case PIPE_BLEND_ADD: return D3D12_BLEND_OP_ADD; 236 case PIPE_BLEND_SUBTRACT: return D3D12_BLEND_OP_SUBTRACT; 237 case PIPE_BLEND_REVERSE_SUBTRACT: return D3D12_BLEND_OP_REV_SUBTRACT; 238 case PIPE_BLEND_MIN: return D3D12_BLEND_OP_MIN; 239 case PIPE_BLEND_MAX: return D3D12_BLEND_OP_MAX; 240 } 241 unreachable("unexpected blend function"); 242} 243 244static D3D12_COMPARISON_FUNC 245compare_op(enum pipe_compare_func op) 246{ 247 switch (op) { 248 case PIPE_FUNC_NEVER: return D3D12_COMPARISON_FUNC_NEVER; 249 case PIPE_FUNC_LESS: return D3D12_COMPARISON_FUNC_LESS; 250 case PIPE_FUNC_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL; 251 case PIPE_FUNC_LEQUAL: return D3D12_COMPARISON_FUNC_LESS_EQUAL; 252 case PIPE_FUNC_GREATER: return D3D12_COMPARISON_FUNC_GREATER; 253 case PIPE_FUNC_NOTEQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL; 254 case PIPE_FUNC_GEQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL; 255 case PIPE_FUNC_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS; 256 } 257 unreachable("unexpected compare"); 258} 259 260static D3D12_LOGIC_OP 261logic_op(enum pipe_logicop func) 262{ 263 switch (func) { 264 case PIPE_LOGICOP_CLEAR: return D3D12_LOGIC_OP_CLEAR; 265 case PIPE_LOGICOP_NOR: return D3D12_LOGIC_OP_NOR; 266 case PIPE_LOGICOP_AND_INVERTED: return D3D12_LOGIC_OP_AND_INVERTED; 267 case PIPE_LOGICOP_COPY_INVERTED: return D3D12_LOGIC_OP_COPY_INVERTED; 268 case PIPE_LOGICOP_AND_REVERSE: return D3D12_LOGIC_OP_AND_REVERSE; 269 case PIPE_LOGICOP_INVERT: return D3D12_LOGIC_OP_INVERT; 270 case PIPE_LOGICOP_XOR: return D3D12_LOGIC_OP_XOR; 271 case PIPE_LOGICOP_NAND: return D3D12_LOGIC_OP_NAND; 272 case PIPE_LOGICOP_AND: return D3D12_LOGIC_OP_AND; 273 case PIPE_LOGICOP_EQUIV: return D3D12_LOGIC_OP_EQUIV; 274 case PIPE_LOGICOP_NOOP: return D3D12_LOGIC_OP_NOOP; 275 case PIPE_LOGICOP_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED; 276 case PIPE_LOGICOP_COPY: return D3D12_LOGIC_OP_COPY; 277 case PIPE_LOGICOP_OR_REVERSE: return D3D12_LOGIC_OP_OR_REVERSE; 278 case PIPE_LOGICOP_OR: return D3D12_LOGIC_OP_OR; 279 case PIPE_LOGICOP_SET: return D3D12_LOGIC_OP_SET; 280 } 281 unreachable("unexpected logicop function"); 282} 283 284static UINT8 285color_write_mask(unsigned colormask) 286{ 287 UINT8 mask = 0; 288 289 if (colormask & PIPE_MASK_R) 290 mask |= D3D12_COLOR_WRITE_ENABLE_RED; 291 if (colormask & PIPE_MASK_G) 292 mask |= D3D12_COLOR_WRITE_ENABLE_GREEN; 293 if (colormask & PIPE_MASK_B) 294 mask |= D3D12_COLOR_WRITE_ENABLE_BLUE; 295 if (colormask & PIPE_MASK_A) 296 mask |= D3D12_COLOR_WRITE_ENABLE_ALPHA; 297 298 return mask; 299} 300 301static void * 302d3d12_create_blend_state(struct pipe_context *pctx, 303 const struct pipe_blend_state *blend_state) 304{ 305 struct d3d12_blend_state *state = CALLOC_STRUCT(d3d12_blend_state); 306 if (!state) 307 return NULL; 308 309 if (blend_state->logicop_enable) { 310 state->desc.RenderTarget[0].LogicOpEnable = TRUE; 311 state->desc.RenderTarget[0].LogicOp = logic_op((pipe_logicop) blend_state->logicop_func); 312 } 313 314 /* TODO Dithering */ 315 316 state->desc.AlphaToCoverageEnable = blend_state->alpha_to_coverage; 317 318 int num_targets = 1; 319 if (blend_state->independent_blend_enable) { 320 state->desc.IndependentBlendEnable = TRUE; 321 num_targets = PIPE_MAX_COLOR_BUFS; 322 } 323 324 for (int i = 0; i < num_targets; ++i) { 325 const struct pipe_rt_blend_state *rt = blend_state->rt + i; 326 327 if (rt->blend_enable) { 328 state->desc.RenderTarget[i].BlendEnable = TRUE; 329 state->desc.RenderTarget[i].SrcBlend = blend_factor_rgb((pipe_blendfactor) rt->rgb_src_factor); 330 state->desc.RenderTarget[i].DestBlend = blend_factor_rgb((pipe_blendfactor) rt->rgb_dst_factor); 331 state->desc.RenderTarget[i].BlendOp = blend_op((pipe_blend_func) rt->rgb_func); 332 state->desc.RenderTarget[i].SrcBlendAlpha = blend_factor_alpha((pipe_blendfactor) rt->alpha_src_factor); 333 state->desc.RenderTarget[i].DestBlendAlpha = blend_factor_alpha((pipe_blendfactor) rt->alpha_dst_factor); 334 state->desc.RenderTarget[i].BlendOpAlpha = blend_op((pipe_blend_func) rt->alpha_func); 335 336 state->blend_factor_flags |= need_blend_factor_rgb((pipe_blendfactor) rt->rgb_src_factor); 337 state->blend_factor_flags |= need_blend_factor_rgb((pipe_blendfactor) rt->rgb_dst_factor); 338 state->blend_factor_flags |= need_blend_factor_alpha((pipe_blendfactor) rt->alpha_src_factor); 339 state->blend_factor_flags |= need_blend_factor_alpha((pipe_blendfactor) rt->alpha_dst_factor); 340 341 if (state->blend_factor_flags == (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ALPHA) && 342 (d3d12_debug & D3D12_DEBUG_VERBOSE)) { 343 /* We can't set a blend factor for both constant color and constant alpha */ 344 debug_printf("D3D12: unsupported blend factors combination (const color and const alpha)\n"); 345 } 346 347 if (util_blend_state_is_dual(blend_state, i)) 348 state->is_dual_src = true; 349 } 350 351 state->desc.RenderTarget[i].RenderTargetWriteMask = color_write_mask(rt->colormask); 352 } 353 354 return state; 355} 356 357static void 358d3d12_bind_blend_state(struct pipe_context *pctx, void *blend_state) 359{ 360 struct d3d12_context *ctx = d3d12_context(pctx); 361 struct d3d12_blend_state *new_state = (struct d3d12_blend_state *) blend_state; 362 struct d3d12_blend_state *old_state = ctx->gfx_pipeline_state.blend; 363 364 ctx->gfx_pipeline_state.blend = new_state; 365 ctx->state_dirty |= D3D12_DIRTY_BLEND; 366 if (new_state == NULL || old_state == NULL || 367 new_state->blend_factor_flags != old_state->blend_factor_flags) 368 ctx->state_dirty |= D3D12_DIRTY_BLEND_COLOR; 369} 370 371static void 372d3d12_delete_blend_state(struct pipe_context *pctx, void *blend_state) 373{ 374 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), blend_state); 375 FREE(blend_state); 376} 377 378static D3D12_STENCIL_OP 379stencil_op(enum pipe_stencil_op op) 380{ 381 switch (op) { 382 case PIPE_STENCIL_OP_KEEP: return D3D12_STENCIL_OP_KEEP; 383 case PIPE_STENCIL_OP_ZERO: return D3D12_STENCIL_OP_ZERO; 384 case PIPE_STENCIL_OP_REPLACE: return D3D12_STENCIL_OP_REPLACE; 385 case PIPE_STENCIL_OP_INCR: return D3D12_STENCIL_OP_INCR_SAT; 386 case PIPE_STENCIL_OP_DECR: return D3D12_STENCIL_OP_DECR_SAT; 387 case PIPE_STENCIL_OP_INCR_WRAP: return D3D12_STENCIL_OP_INCR; 388 case PIPE_STENCIL_OP_DECR_WRAP: return D3D12_STENCIL_OP_DECR; 389 case PIPE_STENCIL_OP_INVERT: return D3D12_STENCIL_OP_INVERT; 390 } 391 unreachable("unexpected op"); 392} 393 394static D3D12_DEPTH_STENCILOP_DESC 395stencil_op_state(const struct pipe_stencil_state *src) 396{ 397 D3D12_DEPTH_STENCILOP_DESC ret; 398 ret.StencilFailOp = stencil_op((pipe_stencil_op) src->fail_op); 399 ret.StencilPassOp = stencil_op((pipe_stencil_op) src->zpass_op); 400 ret.StencilDepthFailOp = stencil_op((pipe_stencil_op) src->zfail_op); 401 ret.StencilFunc = compare_op((pipe_compare_func) src->func); 402 return ret; 403} 404 405static void * 406d3d12_create_depth_stencil_alpha_state(struct pipe_context *pctx, 407 const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha) 408{ 409 struct d3d12_depth_stencil_alpha_state *dsa = CALLOC_STRUCT(d3d12_depth_stencil_alpha_state); 410 if (!dsa) 411 return NULL; 412 413 if (depth_stencil_alpha->depth_enabled) { 414 dsa->desc.DepthEnable = TRUE; 415 dsa->desc.DepthFunc = compare_op((pipe_compare_func) depth_stencil_alpha->depth_func); 416 } 417 418 /* TODO Add support for GL_depth_bound_tests */ 419 #if 0 420 if (depth_stencil_alpha->depth.bounds_test) { 421 dsa->desc.DepthBoundsTestEnable = TRUE; 422 dsa->min_depth_bounds = depth_stencil_alpha->depth.bounds_min; 423 dsa->max_depth_bounds = depth_stencil_alpha->depth.bounds_max; 424 } 425 #endif 426 427 if (depth_stencil_alpha->stencil[0].enabled) { 428 dsa->desc.StencilEnable = TRUE; 429 dsa->desc.FrontFace = stencil_op_state(depth_stencil_alpha->stencil); 430 } 431 432 if (depth_stencil_alpha->stencil[1].enabled) 433 dsa->desc.BackFace = stencil_op_state(depth_stencil_alpha->stencil + 1); 434 else 435 dsa->desc.BackFace = dsa->desc.FrontFace; 436 437 dsa->desc.StencilReadMask = depth_stencil_alpha->stencil[0].valuemask; /* FIXME Back face mask */ 438 dsa->desc.StencilWriteMask = depth_stencil_alpha->stencil[0].writemask; /* FIXME Back face mask */ 439 dsa->desc.DepthWriteMask = (D3D12_DEPTH_WRITE_MASK) depth_stencil_alpha->depth_writemask; 440 441 return dsa; 442} 443 444static void 445d3d12_bind_depth_stencil_alpha_state(struct pipe_context *pctx, 446 void *dsa) 447{ 448 struct d3d12_context *ctx = d3d12_context(pctx); 449 ctx->gfx_pipeline_state.zsa = (struct d3d12_depth_stencil_alpha_state *) dsa; 450 ctx->state_dirty |= D3D12_DIRTY_ZSA; 451} 452 453static void 454d3d12_delete_depth_stencil_alpha_state(struct pipe_context *pctx, 455 void *dsa_state) 456{ 457 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), dsa_state); 458 FREE(dsa_state); 459} 460 461static D3D12_FILL_MODE 462fill_mode(unsigned mode) 463{ 464 switch (mode) { 465 case PIPE_POLYGON_MODE_FILL: 466 return D3D12_FILL_MODE_SOLID; 467 case PIPE_POLYGON_MODE_LINE: 468 return D3D12_FILL_MODE_WIREFRAME; 469 case PIPE_POLYGON_MODE_POINT: 470 return D3D12_FILL_MODE_SOLID; 471 472 default: 473 unreachable("unsupported fill-mode"); 474 } 475} 476 477static void * 478d3d12_create_rasterizer_state(struct pipe_context *pctx, 479 const struct pipe_rasterizer_state *rs_state) 480{ 481 struct d3d12_rasterizer_state *cso = CALLOC_STRUCT(d3d12_rasterizer_state); 482 if (!cso) 483 return NULL; 484 485 cso->base = *rs_state; 486 487 assert(rs_state->depth_clip_near == rs_state->depth_clip_far); 488 489 switch (rs_state->cull_face) { 490 case PIPE_FACE_NONE: 491 if (rs_state->fill_front != rs_state->fill_back) { 492 cso->base.cull_face = PIPE_FACE_BACK; 493 cso->desc.CullMode = D3D12_CULL_MODE_BACK; 494 cso->desc.FillMode = fill_mode(rs_state->fill_front); 495 496 /* create a modified CSO for the back-state, so we can draw with 497 * either. 498 */ 499 struct pipe_rasterizer_state templ = *rs_state; 500 templ.cull_face = PIPE_FACE_FRONT; 501 templ.fill_front = rs_state->fill_back; 502 cso->twoface_back = d3d12_create_rasterizer_state(pctx, &templ); 503 504 if (!cso->twoface_back) { 505 FREE(cso); 506 return NULL; 507 } 508 } else { 509 cso->desc.CullMode = D3D12_CULL_MODE_NONE; 510 cso->desc.FillMode = fill_mode(rs_state->fill_front); 511 } 512 break; 513 514 case PIPE_FACE_FRONT: 515 cso->desc.CullMode = D3D12_CULL_MODE_FRONT; 516 cso->desc.FillMode = fill_mode(rs_state->fill_back); 517 break; 518 519 case PIPE_FACE_BACK: 520 cso->desc.CullMode = D3D12_CULL_MODE_BACK; 521 cso->desc.FillMode = fill_mode(rs_state->fill_front); 522 break; 523 524 case PIPE_FACE_FRONT_AND_BACK: 525 /* this is wrong, and we shouldn't actually have to support this! */ 526 cso->desc.CullMode = D3D12_CULL_MODE_NONE; 527 cso->desc.FillMode = D3D12_FILL_MODE_SOLID; 528 break; 529 530 default: 531 unreachable("unsupported cull-mode"); 532 } 533 534 cso->desc.FrontCounterClockwise = rs_state->front_ccw; 535 cso->desc.DepthClipEnable = rs_state->depth_clip_near; 536 cso->desc.MultisampleEnable = rs_state->multisample; 537 cso->desc.AntialiasedLineEnable = rs_state->line_smooth; 538 cso->desc.ForcedSampleCount = 0; // TODO 539 cso->desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; /* Not Implemented */ 540 541 return cso; 542} 543 544static void 545d3d12_bind_rasterizer_state(struct pipe_context *pctx, void *rs_state) 546{ 547 struct d3d12_context *ctx = d3d12_context(pctx); 548 ctx->gfx_pipeline_state.rast = (struct d3d12_rasterizer_state *)rs_state; 549 ctx->state_dirty |= D3D12_DIRTY_RASTERIZER | D3D12_DIRTY_SCISSOR; 550} 551 552static void 553d3d12_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state) 554{ 555 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), rs_state); 556 FREE(rs_state); 557} 558 559static D3D12_TEXTURE_ADDRESS_MODE 560sampler_address_mode(enum pipe_tex_wrap wrap, enum pipe_tex_filter filter) 561{ 562 switch (wrap) { 563 case PIPE_TEX_WRAP_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_WRAP; 564 case PIPE_TEX_WRAP_CLAMP: return filter == PIPE_TEX_FILTER_NEAREST ? 565 D3D12_TEXTURE_ADDRESS_MODE_CLAMP : 566 D3D12_TEXTURE_ADDRESS_MODE_BORDER; 567 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; 568 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_BORDER; 569 case PIPE_TEX_WRAP_MIRROR_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; 570 case PIPE_TEX_WRAP_MIRROR_CLAMP: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; /* not technically correct, but kinda works */ 571 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; 572 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; /* FIXME: Doesn't exist in D3D12 */ 573 } 574 unreachable("unexpected wrap"); 575} 576 577static D3D12_FILTER 578get_filter(const struct pipe_sampler_state *state) 579{ 580 static const D3D12_FILTER lut[16] = { 581 D3D12_FILTER_MIN_MAG_MIP_POINT, 582 D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR, 583 D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, 584 D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR, 585 D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT, 586 D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, 587 D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, 588 D3D12_FILTER_MIN_MAG_MIP_LINEAR, 589 D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT, 590 D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR, 591 D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT, 592 D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR, 593 D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT, 594 D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR, 595 D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, 596 D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR, 597 }; 598 599 static const D3D12_FILTER anisotropic_lut[2] = { 600 D3D12_FILTER_ANISOTROPIC, 601 D3D12_FILTER_COMPARISON_ANISOTROPIC, 602 }; 603 604 if (state->max_anisotropy > 1) { 605 return anisotropic_lut[state->compare_mode]; 606 } else { 607 int idx = (state->mag_img_filter << 1) | 608 (state->min_img_filter << 2) | 609 (state->compare_mode << 3); 610 if (state->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) 611 idx |= state->min_mip_filter; 612 return lut[idx]; 613 } 614} 615 616static void * 617d3d12_create_sampler_state(struct pipe_context *pctx, 618 const struct pipe_sampler_state *state) 619{ 620 struct d3d12_context *ctx = d3d12_context(pctx); 621 struct d3d12_screen *screen = d3d12_screen(pctx->screen); 622 struct d3d12_sampler_state *ss; 623 D3D12_SAMPLER_DESC desc = {}; 624 if (!state) 625 return NULL; 626 627 ss = CALLOC_STRUCT(d3d12_sampler_state); 628 ss->filter = (pipe_tex_filter)state->min_img_filter; 629 ss->wrap_r = (pipe_tex_wrap)state->wrap_r; 630 ss->wrap_s = (pipe_tex_wrap)state->wrap_s; 631 ss->wrap_t = (pipe_tex_wrap)state->wrap_t; 632 ss->lod_bias = state->lod_bias; 633 ss->min_lod = state->min_lod; 634 ss->max_lod = state->max_lod; 635 memcpy(ss->border_color, state->border_color.f, sizeof(float) * 4); 636 ss->compare_func = (pipe_compare_func)state->compare_func; 637 638 if (state->min_mip_filter < PIPE_TEX_MIPFILTER_NONE) { 639 desc.MinLOD = state->min_lod; 640 desc.MaxLOD = state->max_lod; 641 } else if (state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 642 desc.MinLOD = 0; 643 desc.MaxLOD = 0; 644 } else { 645 unreachable("unexpected mip filter"); 646 } 647 648 if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 649 desc.ComparisonFunc = compare_op((pipe_compare_func) state->compare_func); 650 desc.Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT; 651 } else if (state->compare_mode == PIPE_TEX_COMPARE_NONE) { 652 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; 653 desc.Filter = get_filter(state); 654 } else 655 unreachable("unexpected comparison mode"); 656 657 desc.MaxAnisotropy = state->max_anisotropy; 658 659 desc.AddressU = sampler_address_mode((pipe_tex_wrap) state->wrap_s, 660 (pipe_tex_filter) state->min_img_filter); 661 desc.AddressV = sampler_address_mode((pipe_tex_wrap) state->wrap_t, 662 (pipe_tex_filter) state->min_img_filter); 663 desc.AddressW = sampler_address_mode((pipe_tex_wrap) state->wrap_r, 664 (pipe_tex_filter) state->min_img_filter); 665 desc.MipLODBias = CLAMP(state->lod_bias, -16.0f, 15.99f); 666 memcpy(desc.BorderColor, state->border_color.f, sizeof(float) * 4); 667 668 // TODO Normalized Coordinates? 669 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ss->handle); 670 screen->dev->CreateSampler(&desc, ss->handle.cpu_handle); 671 672 if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 673 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; 674 struct pipe_sampler_state fake_state = *state; 675 fake_state.compare_mode = PIPE_TEX_COMPARE_NONE; 676 desc.Filter = get_filter(&fake_state); 677 678 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, 679 &ss->handle_without_shadow); 680 screen->dev->CreateSampler(&desc, 681 ss->handle_without_shadow.cpu_handle); 682 ss->is_shadow_sampler = true; 683 } 684 685 return ss; 686} 687 688static void 689d3d12_bind_sampler_states(struct pipe_context *pctx, 690 enum pipe_shader_type shader, 691 unsigned start_slot, 692 unsigned num_samplers, 693 void **samplers) 694{ 695 struct d3d12_context *ctx = d3d12_context(pctx); 696 bool shader_state_dirty = false; 697 698#define STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(X) \ 699 static_assert((enum compare_func)PIPE_FUNC_##X == COMPARE_FUNC_##X, #X " needs switch case"); 700 701 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(LESS); 702 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(GREATER); 703 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(LEQUAL); 704 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(GEQUAL); 705 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(NOTEQUAL); 706 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(NEVER); 707 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(ALWAYS); 708 709#undef STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC 710 711 for (unsigned i = 0; i < num_samplers; ++i) { 712 d3d12_sampler_state *sampler = (struct d3d12_sampler_state*) samplers[i]; 713 ctx->samplers[shader][start_slot + i] = sampler; 714 dxil_wrap_sampler_state &wrap = ctx->tex_wrap_states[shader][start_slot + i]; 715 if (sampler) { 716 shader_state_dirty |= wrap.wrap[0] != sampler->wrap_s || 717 wrap.wrap[1] != sampler->wrap_t || 718 wrap.wrap[2] != sampler->wrap_r; 719 shader_state_dirty |= !!memcmp(wrap.border_color, sampler->border_color, 4 * sizeof(float)); 720 721 wrap.wrap[0] = sampler->wrap_s; 722 wrap.wrap[1] = sampler->wrap_t; 723 wrap.wrap[2] = sampler->wrap_r; 724 wrap.lod_bias = sampler->lod_bias; 725 wrap.min_lod = sampler->min_lod; 726 wrap.max_lod = sampler->max_lod; 727 memcpy(wrap.border_color, sampler->border_color, 4 * sizeof(float)); 728 ctx->tex_compare_func[shader][start_slot + i] = (enum compare_func)sampler->compare_func; 729 } else { 730 memset(&wrap, 0, sizeof (dxil_wrap_sampler_state)); 731 } 732 } 733 734 ctx->num_samplers[shader] = start_slot + num_samplers; 735 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SAMPLERS; 736 if (shader_state_dirty) 737 ctx->state_dirty |= D3D12_DIRTY_SHADER; 738} 739 740static void 741d3d12_delete_sampler_state(struct pipe_context *pctx, 742 void *ss) 743{ 744 struct d3d12_batch *batch = d3d12_current_batch(d3d12_context(pctx)); 745 struct d3d12_sampler_state *state = (struct d3d12_sampler_state*) ss; 746 util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle, 747 state->handle); 748 if (state->is_shadow_sampler) 749 util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle, 750 state->handle_without_shadow); 751 FREE(ss); 752} 753 754static D3D12_SRV_DIMENSION 755view_dimension(enum pipe_texture_target target, unsigned samples) 756{ 757 switch (target) { 758 case PIPE_BUFFER: return D3D12_SRV_DIMENSION_BUFFER; 759 case PIPE_TEXTURE_1D: return D3D12_SRV_DIMENSION_TEXTURE1D; 760 case PIPE_TEXTURE_1D_ARRAY: return D3D12_SRV_DIMENSION_TEXTURE1DARRAY; 761 case PIPE_TEXTURE_RECT: 762 case PIPE_TEXTURE_2D: 763 return samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMS : 764 D3D12_SRV_DIMENSION_TEXTURE2D; 765 case PIPE_TEXTURE_2D_ARRAY: 766 return samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY : 767 D3D12_SRV_DIMENSION_TEXTURE2DARRAY; 768 case PIPE_TEXTURE_CUBE: return D3D12_SRV_DIMENSION_TEXTURECUBE; 769 case PIPE_TEXTURE_CUBE_ARRAY: return D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; 770 case PIPE_TEXTURE_3D: return D3D12_SRV_DIMENSION_TEXTURE3D; 771 default: 772 unreachable("unexpected target"); 773 } 774} 775 776static D3D12_SHADER_COMPONENT_MAPPING 777component_mapping(enum pipe_swizzle swizzle, D3D12_SHADER_COMPONENT_MAPPING id) 778{ 779 switch (swizzle) { 780 case PIPE_SWIZZLE_X: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0; 781 case PIPE_SWIZZLE_Y: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1; 782 case PIPE_SWIZZLE_Z: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2; 783 case PIPE_SWIZZLE_W: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3; 784 case PIPE_SWIZZLE_0: return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0; 785 case PIPE_SWIZZLE_1: return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1; 786 case PIPE_SWIZZLE_NONE: return id; 787 default: 788 unreachable("unexpected swizzle"); 789 } 790} 791 792static struct pipe_sampler_view * 793d3d12_create_sampler_view(struct pipe_context *pctx, 794 struct pipe_resource *texture, 795 const struct pipe_sampler_view *state) 796{ 797 struct d3d12_screen *screen = d3d12_screen(pctx->screen); 798 struct d3d12_resource *res = d3d12_resource(texture); 799 struct d3d12_sampler_view *sampler_view = CALLOC_STRUCT(d3d12_sampler_view); 800 801 sampler_view->base = *state; 802 sampler_view->base.texture = NULL; 803 pipe_resource_reference(&sampler_view->base.texture, texture); 804 sampler_view->base.reference.count = 1; 805 sampler_view->base.context = pctx; 806 sampler_view->mip_levels = state->u.tex.last_level - state->u.tex.first_level + 1; 807 sampler_view->array_size = texture->array_size; 808 809 D3D12_SHADER_RESOURCE_VIEW_DESC desc = {}; 810 struct d3d12_format_info format_info = d3d12_get_format_info(state->format, state->target); 811 pipe_swizzle swizzle[4] = { 812 format_info.swizzle[sampler_view->base.swizzle_r], 813 format_info.swizzle[sampler_view->base.swizzle_g], 814 format_info.swizzle[sampler_view->base.swizzle_b], 815 format_info.swizzle[sampler_view->base.swizzle_a] 816 }; 817 818 sampler_view->swizzle_override_r = swizzle[0]; 819 sampler_view->swizzle_override_g = swizzle[1]; 820 sampler_view->swizzle_override_b = swizzle[2]; 821 sampler_view->swizzle_override_a = swizzle[3]; 822 823 desc.Format = d3d12_get_resource_srv_format(state->format, state->target); 824 desc.ViewDimension = view_dimension(state->target, texture->nr_samples); 825 826 /* Integer cube textures are not really supported, because TextureLoad doesn't exist 827 * for cube maps, and we sampling is not supported for integer textures, so we have to 828 * handle this SRV as if it were a 2D texture array */ 829 if ((desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE || 830 desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) && 831 util_format_is_pure_integer(state->format)) { 832 desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; 833 } 834 835 desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( 836 component_mapping(swizzle[0], D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0), 837 component_mapping(swizzle[1], D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1), 838 component_mapping(swizzle[2], D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2), 839 component_mapping(swizzle[3], D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3) 840 ); 841 842 unsigned array_size = state->u.tex.last_layer - state->u.tex.first_layer + 1; 843 switch (desc.ViewDimension) { 844 case D3D12_SRV_DIMENSION_TEXTURE1D: 845 if (state->u.tex.first_layer > 0) 846 debug_printf("D3D12: can't create 1D SRV from layer %d\n", 847 state->u.tex.first_layer); 848 849 desc.Texture1D.MostDetailedMip = state->u.tex.first_level; 850 desc.Texture1D.MipLevels = sampler_view->mip_levels; 851 desc.Texture1D.ResourceMinLODClamp = 0.0f; 852 break; 853 case D3D12_SRV_DIMENSION_TEXTURE1DARRAY: 854 desc.Texture1DArray.MostDetailedMip = state->u.tex.first_level; 855 desc.Texture1DArray.MipLevels = sampler_view->mip_levels; 856 desc.Texture1DArray.ResourceMinLODClamp = 0.0f; 857 desc.Texture1DArray.FirstArraySlice = state->u.tex.first_layer; 858 desc.Texture1DArray.ArraySize = array_size; 859 break; 860 case D3D12_SRV_DIMENSION_TEXTURE2D: 861 if (state->u.tex.first_layer > 0) 862 debug_printf("D3D12: can't create 2D SRV from layer %d\n", 863 state->u.tex.first_layer); 864 865 desc.Texture2D.MostDetailedMip = state->u.tex.first_level; 866 desc.Texture2D.MipLevels = sampler_view->mip_levels; 867 desc.Texture2D.PlaneSlice = format_info.plane_slice; 868 desc.Texture2D.ResourceMinLODClamp = 0.0f; 869 break; 870 case D3D12_SRV_DIMENSION_TEXTURE2DMS: 871 if (state->u.tex.first_layer > 0) 872 debug_printf("D3D12: can't create 2DMS SRV from layer %d\n", 873 state->u.tex.first_layer); 874 break; 875 case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: 876 desc.Texture2DArray.MostDetailedMip = state->u.tex.first_level; 877 desc.Texture2DArray.MipLevels = sampler_view->mip_levels; 878 desc.Texture2DArray.ResourceMinLODClamp = 0.0f; 879 desc.Texture2DArray.FirstArraySlice = state->u.tex.first_layer; 880 desc.Texture2DArray.PlaneSlice = format_info.plane_slice; 881 desc.Texture2DArray.ArraySize = array_size; 882 break; 883 case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY: 884 desc.Texture2DMSArray.FirstArraySlice = state->u.tex.first_layer; 885 desc.Texture2DMSArray.ArraySize = array_size; 886 break; 887 case D3D12_SRV_DIMENSION_TEXTURE3D: 888 if (state->u.tex.first_layer > 0) 889 debug_printf("D3D12: can't create 3D SRV from layer %d\n", 890 state->u.tex.first_layer); 891 892 desc.Texture3D.MostDetailedMip = state->u.tex.first_level; 893 desc.Texture3D.MipLevels = sampler_view->mip_levels; 894 desc.Texture3D.ResourceMinLODClamp = 0.0f; 895 break; 896 case D3D12_SRV_DIMENSION_TEXTURECUBE: 897 if (state->u.tex.first_layer > 0) 898 debug_printf("D3D12: can't create CUBE SRV from layer %d\n", 899 state->u.tex.first_layer); 900 901 desc.TextureCube.MostDetailedMip = state->u.tex.first_level; 902 desc.TextureCube.MipLevels = sampler_view->mip_levels; 903 desc.TextureCube.ResourceMinLODClamp = 0.0f; 904 break; 905 case D3D12_SRV_DIMENSION_BUFFER: 906 desc.Buffer.FirstElement = 0; 907 desc.Buffer.StructureByteStride = 0; 908 desc.Buffer.NumElements = texture->width0 / util_format_get_blocksize(state->format); 909 break; 910 default: 911 unreachable("Invalid SRV dimension"); 912 } 913 914 mtx_lock(&screen->descriptor_pool_mutex); 915 d3d12_descriptor_pool_alloc_handle(screen->view_pool, &sampler_view->handle); 916 mtx_unlock(&screen->descriptor_pool_mutex); 917 918 screen->dev->CreateShaderResourceView(d3d12_resource_resource(res), &desc, 919 sampler_view->handle.cpu_handle); 920 921 return &sampler_view->base; 922} 923 924static void 925d3d12_increment_sampler_view_bind_count(struct pipe_context *ctx, 926 enum pipe_shader_type shader_type, 927 struct pipe_sampler_view *view) { 928 struct d3d12_resource *res = d3d12_resource(view->texture); 929 if (res) 930 res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]++; 931} 932 933static void 934d3d12_decrement_sampler_view_bind_count(struct pipe_context *ctx, 935 enum pipe_shader_type shader_type, 936 struct pipe_sampler_view *view) { 937 struct d3d12_resource *res = d3d12_resource(view->texture); 938 if (res) { 939 assert(res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0); 940 res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]--; 941 } 942} 943 944static void 945d3d12_set_sampler_views(struct pipe_context *pctx, 946 enum pipe_shader_type shader_type, 947 unsigned start_slot, 948 unsigned num_views, 949 unsigned unbind_num_trailing_slots, 950 bool take_ownership, 951 struct pipe_sampler_view **views) 952{ 953 struct d3d12_context *ctx = d3d12_context(pctx); 954 unsigned shader_bit = (1 << shader_type); 955 ctx->has_int_samplers &= ~shader_bit; 956 957 for (unsigned i = 0; i < num_views; ++i) { 958 struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + i]; 959 if (old_view) 960 d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view); 961 962 struct pipe_sampler_view *new_view = views[i]; 963 if (new_view) 964 d3d12_increment_sampler_view_bind_count(pctx, shader_type, new_view); 965 966 if (take_ownership) { 967 pipe_sampler_view_reference(&old_view, NULL); 968 old_view = views[i]; 969 } else { 970 pipe_sampler_view_reference(&old_view, views[i]); 971 } 972 973 if (views[i]) { 974 dxil_wrap_sampler_state &wss = ctx->tex_wrap_states[shader_type][start_slot + i]; 975 dxil_texture_swizzle_state &swizzle_state = ctx->tex_swizzle_state[shader_type][i]; 976 if (util_format_is_pure_integer(views[i]->format)) { 977 ctx->has_int_samplers |= shader_bit; 978 wss.is_int_sampler = 1; 979 wss.last_level = views[i]->texture->last_level; 980 /* When we emulate a integer cube texture (array) by using a texture 2d Array 981 * the coordinates are evaluated to always reside withing the acceptable range 982 * because the 3d ray for picking the texel is always pointing at one cube face, 983 * hence we can skip the boundary condition handling when the texture operations are 984 * lowered to texel fetches later. */ 985 wss.skip_boundary_conditions = views[i]->target == PIPE_TEXTURE_CUBE || 986 views[i]->target == PIPE_TEXTURE_CUBE_ARRAY; 987 } else { 988 wss.is_int_sampler = 0; 989 } 990 /* We need the swizzle state for compare texture lowering, because it 991 * encode the use of the shadow texture lookup result as either luminosity, 992 * intensity, or alpha. and we need the swizzle state for applying the 993 * boundary color correctly */ 994 struct d3d12_sampler_view *ss = d3d12_sampler_view(views[i]); 995 swizzle_state.swizzle_r = ss->swizzle_override_r; 996 swizzle_state.swizzle_g = ss->swizzle_override_g; 997 swizzle_state.swizzle_b = ss->swizzle_override_b; 998 swizzle_state.swizzle_a = ss->swizzle_override_a; 999 } 1000 } 1001 1002 for (unsigned i = 0; i < unbind_num_trailing_slots; i++) { 1003 struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + num_views + i]; 1004 if (old_view) 1005 d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view); 1006 pipe_sampler_view_reference(&old_view, NULL); 1007 } 1008 ctx->num_sampler_views[shader_type] = start_slot + num_views; 1009 ctx->shader_dirty[shader_type] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; 1010} 1011 1012static void 1013d3d12_destroy_sampler_view(struct pipe_context *pctx, 1014 struct pipe_sampler_view *pview) 1015{ 1016 struct d3d12_sampler_view *view = d3d12_sampler_view(pview); 1017 d3d12_descriptor_handle_free(&view->handle); 1018 pipe_resource_reference(&view->base.texture, NULL); 1019 FREE(view); 1020} 1021 1022static void 1023delete_shader(struct d3d12_context *ctx, enum pipe_shader_type stage, 1024 struct d3d12_shader_selector *shader) 1025{ 1026 d3d12_gfx_pipeline_state_cache_invalidate_shader(ctx, stage, shader); 1027 1028 /* Make sure the pipeline state no longer reference the deleted shader */ 1029 struct d3d12_shader *iter = shader->first; 1030 while (iter) { 1031 if (ctx->gfx_pipeline_state.stages[stage] == iter) { 1032 ctx->gfx_pipeline_state.stages[stage] = NULL; 1033 break; 1034 } 1035 iter = iter->next_variant; 1036 } 1037 1038 d3d12_shader_free(shader); 1039} 1040 1041static void 1042bind_stage(struct d3d12_context *ctx, enum pipe_shader_type stage, 1043 struct d3d12_shader_selector *shader) 1044{ 1045 assert(stage < D3D12_GFX_SHADER_STAGES); 1046 ctx->gfx_stages[stage] = shader; 1047} 1048 1049static void * 1050d3d12_create_vs_state(struct pipe_context *pctx, 1051 const struct pipe_shader_state *shader) 1052{ 1053 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX, shader); 1054} 1055 1056static void 1057d3d12_bind_vs_state(struct pipe_context *pctx, 1058 void *vss) 1059{ 1060 bind_stage(d3d12_context(pctx), PIPE_SHADER_VERTEX, 1061 (struct d3d12_shader_selector *) vss); 1062} 1063 1064static void 1065d3d12_delete_vs_state(struct pipe_context *pctx, 1066 void *vs) 1067{ 1068 delete_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX, 1069 (struct d3d12_shader_selector *) vs); 1070} 1071 1072static void * 1073d3d12_create_fs_state(struct pipe_context *pctx, 1074 const struct pipe_shader_state *shader) 1075{ 1076 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, shader); 1077} 1078 1079static void 1080d3d12_bind_fs_state(struct pipe_context *pctx, 1081 void *fss) 1082{ 1083 bind_stage(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, 1084 (struct d3d12_shader_selector *) fss); 1085} 1086 1087static void 1088d3d12_delete_fs_state(struct pipe_context *pctx, 1089 void *fs) 1090{ 1091 delete_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, 1092 (struct d3d12_shader_selector *) fs); 1093} 1094 1095static void * 1096d3d12_create_gs_state(struct pipe_context *pctx, 1097 const struct pipe_shader_state *shader) 1098{ 1099 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, shader); 1100} 1101 1102static void 1103d3d12_bind_gs_state(struct pipe_context *pctx, void *gss) 1104{ 1105 bind_stage(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, 1106 (struct d3d12_shader_selector *) gss); 1107} 1108 1109static void 1110d3d12_delete_gs_state(struct pipe_context *pctx, void *gs) 1111{ 1112 delete_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, 1113 (struct d3d12_shader_selector *) gs); 1114} 1115 1116static bool 1117d3d12_init_polygon_stipple(struct pipe_context *pctx) 1118{ 1119 struct d3d12_context *ctx = d3d12_context(pctx); 1120 1121 ctx->pstipple.texture = util_pstipple_create_stipple_texture(pctx, NULL); 1122 if (!ctx->pstipple.texture) 1123 return false; 1124 1125 ctx->pstipple.sampler_view = util_pstipple_create_sampler_view(pctx, ctx->pstipple.texture); 1126 if (!ctx->pstipple.sampler_view) 1127 return false; 1128 1129 ctx->pstipple.sampler_cso = (struct d3d12_sampler_state *)util_pstipple_create_sampler(pctx); 1130 if (!ctx->pstipple.sampler_cso) 1131 return false; 1132 1133 return true; 1134} 1135 1136static void 1137d3d12_set_polygon_stipple(struct pipe_context *pctx, 1138 const struct pipe_poly_stipple *ps) 1139{ 1140 static bool initialized = false; 1141 static const uint32_t zero[32] = {0}; 1142 static uint32_t undef[32] = {0}; 1143 struct d3d12_context *ctx = d3d12_context(pctx); 1144 1145 if (!initialized) 1146 memset(undef, UINT32_MAX, sizeof(undef)); 1147 1148 if (!memcmp(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple))) 1149 return; 1150 1151 memcpy(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple)); 1152 ctx->pstipple.enabled = !!memcmp(ps->stipple, undef, sizeof(ps->stipple)) && 1153 !!memcmp(ps->stipple, zero, sizeof(ps->stipple)); 1154 if (ctx->pstipple.enabled) 1155 util_pstipple_update_stipple_texture(pctx, ctx->pstipple.texture, ps->stipple); 1156} 1157 1158static void 1159d3d12_set_vertex_buffers(struct pipe_context *pctx, 1160 unsigned start_slot, 1161 unsigned num_buffers, 1162 unsigned unbind_num_trailing_slots, 1163 bool take_ownership, 1164 const struct pipe_vertex_buffer *buffers) 1165{ 1166 struct d3d12_context *ctx = d3d12_context(pctx); 1167 util_set_vertex_buffers_count(ctx->vbs, &ctx->num_vbs, 1168 buffers, start_slot, num_buffers, 1169 unbind_num_trailing_slots, 1170 take_ownership); 1171 1172 for (unsigned i = 0; i < ctx->num_vbs; ++i) { 1173 const struct pipe_vertex_buffer* buf = ctx->vbs + i; 1174 if (!buf->buffer.resource) 1175 continue; 1176 struct d3d12_resource *res = d3d12_resource(buf->buffer.resource); 1177 ctx->vbvs[i].BufferLocation = d3d12_resource_gpu_virtual_address(res) + buf->buffer_offset; 1178 ctx->vbvs[i].StrideInBytes = buf->stride; 1179 ctx->vbvs[i].SizeInBytes = res->base.width0 - buf->buffer_offset; 1180 } 1181 ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS; 1182} 1183 1184static void 1185d3d12_set_viewport_states(struct pipe_context *pctx, 1186 unsigned start_slot, 1187 unsigned num_viewports, 1188 const struct pipe_viewport_state *state) 1189{ 1190 struct d3d12_context *ctx = d3d12_context(pctx); 1191 1192 for (unsigned i = 0; i < num_viewports; ++i) { 1193 if (state[i].scale[1] < 0) { 1194 ctx->flip_y = 1.0f; 1195 ctx->viewports[start_slot + i].TopLeftY = state[i].translate[1] + state[i].scale[1]; 1196 ctx->viewports[start_slot + i].Height = -state[i].scale[1] * 2; 1197 } else { 1198 ctx->flip_y = -1.0f; 1199 ctx->viewports[start_slot + i].TopLeftY = state[i].translate[1] - state[i].scale[1]; 1200 ctx->viewports[start_slot + i].Height = state[i].scale[1] * 2; 1201 } 1202 ctx->viewports[start_slot + i].TopLeftX = state[i].translate[0] - state[i].scale[0]; 1203 ctx->viewports[start_slot + i].Width = state[i].scale[0] * 2; 1204 1205 float near_depth = state[i].translate[2] - state[i].scale[2]; 1206 float far_depth = state[i].translate[2] + state[i].scale[2]; 1207 1208 ctx->reverse_depth_range = near_depth > far_depth; 1209 if (ctx->reverse_depth_range) { 1210 float tmp = near_depth; 1211 near_depth = far_depth; 1212 far_depth = tmp; 1213 } 1214 ctx->viewports[start_slot + i].MinDepth = near_depth; 1215 ctx->viewports[start_slot + i].MaxDepth = far_depth; 1216 ctx->viewport_states[start_slot + i] = state[i]; 1217 } 1218 ctx->num_viewports = start_slot + num_viewports; 1219 ctx->state_dirty |= D3D12_DIRTY_VIEWPORT; 1220} 1221 1222 1223static void 1224d3d12_set_scissor_states(struct pipe_context *pctx, 1225 unsigned start_slot, unsigned num_scissors, 1226 const struct pipe_scissor_state *states) 1227{ 1228 struct d3d12_context *ctx = d3d12_context(pctx); 1229 1230 for (unsigned i = 0; i < num_scissors; i++) { 1231 ctx->scissors[start_slot + i].left = states[i].minx; 1232 ctx->scissors[start_slot + i].top = states[i].miny; 1233 ctx->scissors[start_slot + i].right = states[i].maxx; 1234 ctx->scissors[start_slot + i].bottom = states[i].maxy; 1235 ctx->scissor_states[start_slot + i] = states[i]; 1236 } 1237 ctx->state_dirty |= D3D12_DIRTY_SCISSOR; 1238} 1239 1240static void 1241d3d12_decrement_constant_buffer_bind_count(struct d3d12_context *ctx, 1242 enum pipe_shader_type shader, 1243 struct d3d12_resource *res) { 1244 assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0); 1245 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV]--; 1246} 1247 1248static void 1249d3d12_increment_constant_buffer_bind_count(struct d3d12_context *ctx, 1250 enum pipe_shader_type shader, 1251 struct d3d12_resource *res) { 1252 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV]++; 1253} 1254 1255static void 1256d3d12_set_constant_buffer(struct pipe_context *pctx, 1257 enum pipe_shader_type shader, uint index, 1258 bool take_ownership, 1259 const struct pipe_constant_buffer *buf) 1260{ 1261 struct d3d12_context *ctx = d3d12_context(pctx); 1262 1263 if (buf) { 1264 struct pipe_resource *buffer = buf->buffer; 1265 unsigned offset = buf->buffer_offset; 1266 if (buf->user_buffer) { 1267 u_upload_data(pctx->const_uploader, 0, buf->buffer_size, 1268 D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, 1269 buf->user_buffer, &offset, &ctx->cbufs[shader][index].buffer); 1270 1271 } else { 1272 if (take_ownership) { 1273 struct d3d12_resource *old_buf = d3d12_resource(ctx->cbufs[shader][index].buffer); 1274 if (old_buf) 1275 d3d12_decrement_constant_buffer_bind_count(ctx, shader, old_buf); 1276 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL); 1277 ctx->cbufs[shader][index].buffer = buffer; 1278 if (buffer) 1279 d3d12_increment_constant_buffer_bind_count(ctx, shader, d3d12_resource(buffer)); 1280 } else { 1281 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, buffer); 1282 } 1283 } 1284 1285 1286 ctx->cbufs[shader][index].buffer_offset = offset; 1287 ctx->cbufs[shader][index].buffer_size = buf->buffer_size; 1288 ctx->cbufs[shader][index].user_buffer = NULL; 1289 1290 } else { 1291 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL); 1292 ctx->cbufs[shader][index].buffer_offset = 0; 1293 ctx->cbufs[shader][index].buffer_size = 0; 1294 ctx->cbufs[shader][index].user_buffer = NULL; 1295 } 1296 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_CONSTBUF; 1297} 1298 1299static void 1300d3d12_set_framebuffer_state(struct pipe_context *pctx, 1301 const struct pipe_framebuffer_state *state) 1302{ 1303 struct d3d12_context *ctx = d3d12_context(pctx); 1304 int samples = -1; 1305 1306 util_copy_framebuffer_state(&d3d12_context(pctx)->fb, state); 1307 1308 ctx->gfx_pipeline_state.num_cbufs = state->nr_cbufs; 1309 ctx->gfx_pipeline_state.has_float_rtv = false; 1310 for (int i = 0; i < state->nr_cbufs; ++i) { 1311 if (state->cbufs[i]) { 1312 if (util_format_is_float(state->cbufs[i]->format)) 1313 ctx->gfx_pipeline_state.has_float_rtv = true; 1314 ctx->gfx_pipeline_state.rtv_formats[i] = d3d12_get_format(state->cbufs[i]->format); 1315 samples = MAX2(samples, (int)state->cbufs[i]->texture->nr_samples); 1316 } else { 1317 ctx->gfx_pipeline_state.rtv_formats[i] = DXGI_FORMAT_UNKNOWN; 1318 } 1319 } 1320 1321 if (state->zsbuf) { 1322 ctx->gfx_pipeline_state.dsv_format = d3d12_get_resource_rt_format(state->zsbuf->format); 1323 samples = MAX2(samples, (int)ctx->fb.zsbuf->texture->nr_samples); 1324 } else 1325 ctx->gfx_pipeline_state.dsv_format = DXGI_FORMAT_UNKNOWN; 1326 1327 if (samples < 0) 1328 samples = state->samples; 1329 1330 ctx->gfx_pipeline_state.samples = MAX2(samples, 1); 1331 1332 ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER; 1333} 1334 1335static void 1336d3d12_set_blend_color(struct pipe_context *pctx, 1337 const struct pipe_blend_color *color) 1338{ 1339 struct d3d12_context *ctx = d3d12_context(pctx); 1340 memcpy(ctx->blend_factor, color->color, sizeof(float) * 4); 1341 ctx->state_dirty |= D3D12_DIRTY_BLEND_COLOR; 1342} 1343 1344static void 1345d3d12_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 1346{ 1347 struct d3d12_context *ctx = d3d12_context(pctx); 1348 ctx->gfx_pipeline_state.sample_mask = sample_mask; 1349 ctx->state_dirty |= D3D12_DIRTY_SAMPLE_MASK; 1350} 1351 1352static void 1353d3d12_set_stencil_ref(struct pipe_context *pctx, 1354 const struct pipe_stencil_ref ref) 1355{ 1356 struct d3d12_context *ctx = d3d12_context(pctx); 1357 if ((ref.ref_value[0] != ref.ref_value[1]) && 1358 (d3d12_debug & D3D12_DEBUG_VERBOSE)) 1359 debug_printf("D3D12: Different values for front and back stencil reference are not supported\n"); 1360 ctx->stencil_ref = ref; 1361 ctx->state_dirty |= D3D12_DIRTY_STENCIL_REF; 1362} 1363 1364static void 1365d3d12_set_clip_state(struct pipe_context *pctx, 1366 const struct pipe_clip_state *pcs) 1367{ 1368} 1369 1370static struct pipe_stream_output_target * 1371d3d12_create_stream_output_target(struct pipe_context *pctx, 1372 struct pipe_resource *pres, 1373 unsigned buffer_offset, 1374 unsigned buffer_size) 1375{ 1376 struct d3d12_resource *res = d3d12_resource(pres); 1377 struct d3d12_stream_output_target *cso = CALLOC_STRUCT(d3d12_stream_output_target); 1378 1379 if (!cso) 1380 return NULL; 1381 1382 pipe_reference_init(&cso->base.reference, 1); 1383 pipe_resource_reference(&cso->base.buffer, pres); 1384 cso->base.buffer_offset = buffer_offset; 1385 cso->base.buffer_size = buffer_size; 1386 cso->base.context = pctx; 1387 1388 if (res->bo && res->bo->buffer && d3d12_buffer(res->bo->buffer)->map) 1389 util_range_add(pres, &res->valid_buffer_range, buffer_offset, 1390 buffer_offset + buffer_size); 1391 1392 return &cso->base; 1393} 1394 1395static void 1396d3d12_stream_output_target_destroy(struct pipe_context *ctx, 1397 struct pipe_stream_output_target *state) 1398{ 1399 pipe_resource_reference(&state->buffer, NULL); 1400 1401 FREE(state); 1402} 1403 1404static void 1405fill_stream_output_buffer_view(D3D12_STREAM_OUTPUT_BUFFER_VIEW *view, 1406 struct d3d12_stream_output_target *target) 1407{ 1408 struct d3d12_resource *res = d3d12_resource(target->base.buffer); 1409 struct d3d12_resource *fill_res = d3d12_resource(target->fill_buffer); 1410 1411 view->SizeInBytes = target->base.buffer_size; 1412 view->BufferLocation = d3d12_resource_gpu_virtual_address(res) + target->base.buffer_offset; 1413 view->BufferFilledSizeLocation = d3d12_resource_gpu_virtual_address(fill_res) + target->fill_buffer_offset; 1414} 1415 1416static void 1417d3d12_set_stream_output_targets(struct pipe_context *pctx, 1418 unsigned num_targets, 1419 struct pipe_stream_output_target **targets, 1420 const unsigned *offsets) 1421{ 1422 struct d3d12_context *ctx = d3d12_context(pctx); 1423 1424 assert(num_targets <= ARRAY_SIZE(ctx->so_targets)); 1425 1426 d3d12_disable_fake_so_buffers(ctx); 1427 1428 for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { 1429 struct d3d12_stream_output_target *target = 1430 i < num_targets ? (struct d3d12_stream_output_target *)targets[i] : NULL; 1431 1432 if (target) { 1433 /* Sub-allocate a new fill buffer each time to avoid GPU/CPU synchronization */ 1434 u_suballocator_alloc(&ctx->so_allocator, sizeof(uint64_t), 4, 1435 &target->fill_buffer_offset, &target->fill_buffer); 1436 fill_stream_output_buffer_view(&ctx->so_buffer_views[i], target); 1437 pipe_so_target_reference(&ctx->so_targets[i], targets[i]); 1438 } else { 1439 ctx->so_buffer_views[i].SizeInBytes = 0; 1440 pipe_so_target_reference(&ctx->so_targets[i], NULL); 1441 } 1442 } 1443 1444 ctx->gfx_pipeline_state.num_so_targets = num_targets; 1445 ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1446} 1447 1448static void 1449d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resource *res) { 1450 // For each shader type, if the resource is currently bound as CBV or SRV 1451 // set the context shader_dirty bit. 1452 for (uint i = 0; i < PIPE_SHADER_TYPES; ++i) { 1453 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0) { 1454 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF; 1455 } 1456 1457 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0) { 1458 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; 1459 } 1460 } 1461} 1462 1463bool 1464d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor) 1465{ 1466 if (ctx->fake_so_buffer_factor == factor) 1467 return true; 1468 1469 d3d12_disable_fake_so_buffers(ctx); 1470 1471 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 1472 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i]; 1473 struct d3d12_stream_output_target *fake_target; 1474 1475 fake_target = CALLOC_STRUCT(d3d12_stream_output_target); 1476 if (!fake_target) 1477 return false; 1478 pipe_reference_init(&fake_target->base.reference, 1); 1479 fake_target->base.context = &ctx->base; 1480 1481 d3d12_resource_wait_idle(ctx, d3d12_resource(target->base.buffer)); 1482 1483 /* Check if another target is using the same buffer */ 1484 for (unsigned j = 0; j < i; ++j) { 1485 if (ctx->so_targets[j] && ctx->so_targets[j]->buffer == target->base.buffer) { 1486 struct d3d12_stream_output_target *prev_target = 1487 (struct d3d12_stream_output_target *)ctx->fake_so_targets[j]; 1488 pipe_resource_reference(&fake_target->base.buffer, prev_target->base.buffer); 1489 pipe_resource_reference(&fake_target->fill_buffer, prev_target->fill_buffer); 1490 fake_target->fill_buffer_offset = prev_target->fill_buffer_offset; 1491 fake_target->cached_filled_size = prev_target->cached_filled_size; 1492 break; 1493 } 1494 } 1495 1496 /* Create new SO buffer 6x (2 triangles instead of 1 point) the original size if not */ 1497 if (!fake_target->base.buffer) { 1498 fake_target->base.buffer = pipe_buffer_create(ctx->base.screen, 1499 PIPE_BIND_STREAM_OUTPUT, 1500 PIPE_USAGE_STAGING, 1501 target->base.buffer->width0 * factor); 1502 u_suballocator_alloc(&ctx->so_allocator, sizeof(uint64_t), 4, 1503 &fake_target->fill_buffer_offset, &fake_target->fill_buffer); 1504 pipe_buffer_read(&ctx->base, target->fill_buffer, 1505 target->fill_buffer_offset, sizeof(uint64_t), 1506 &fake_target->cached_filled_size); 1507 } 1508 1509 fake_target->base.buffer_offset = target->base.buffer_offset * factor; 1510 fake_target->base.buffer_size = (target->base.buffer_size - fake_target->cached_filled_size) * factor; 1511 ctx->fake_so_targets[i] = &fake_target->base; 1512 fill_stream_output_buffer_view(&ctx->fake_so_buffer_views[i], fake_target); 1513 } 1514 1515 ctx->fake_so_buffer_factor = factor; 1516 ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1517 1518 return true; 1519} 1520 1521bool 1522d3d12_disable_fake_so_buffers(struct d3d12_context *ctx) 1523{ 1524 if (ctx->fake_so_buffer_factor == 0) 1525 return true; 1526 1527 d3d12_flush_cmdlist_and_wait(ctx); 1528 1529 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 1530 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i]; 1531 struct d3d12_stream_output_target *fake_target = (struct d3d12_stream_output_target *)ctx->fake_so_targets[i]; 1532 uint64_t filled_size = 0; 1533 struct pipe_transfer *src_transfer, *dst_transfer; 1534 uint8_t *src, *dst; 1535 1536 if (fake_target == NULL) 1537 continue; 1538 1539 pipe_buffer_read(&ctx->base, fake_target->fill_buffer, 1540 fake_target->fill_buffer_offset, sizeof(uint64_t), 1541 &filled_size); 1542 1543 src = (uint8_t *)pipe_buffer_map_range(&ctx->base, fake_target->base.buffer, 1544 fake_target->base.buffer_offset, 1545 fake_target->base.buffer_size, 1546 PIPE_MAP_READ, &src_transfer); 1547 dst = (uint8_t *)pipe_buffer_map_range(&ctx->base, target->base.buffer, 1548 target->base.buffer_offset, 1549 target->base.buffer_size, 1550 PIPE_MAP_READ, &dst_transfer); 1551 1552 /* Note: This will break once support for gl_SkipComponents is added */ 1553 uint32_t stride = ctx->gfx_pipeline_state.so_info.stride[i] * 4; 1554 uint64_t src_offset = 0, dst_offset = fake_target->cached_filled_size; 1555 while (src_offset < filled_size) { 1556 memcpy(dst + dst_offset, src + src_offset, stride); 1557 src_offset += stride * ctx->fake_so_buffer_factor; 1558 dst_offset += stride; 1559 } 1560 1561 pipe_buffer_unmap(&ctx->base, src_transfer); 1562 pipe_buffer_unmap(&ctx->base, dst_transfer); 1563 1564 pipe_so_target_reference(&ctx->fake_so_targets[i], NULL); 1565 ctx->fake_so_buffer_views[i].SizeInBytes = 0; 1566 1567 /* Make sure the buffer is not copied twice */ 1568 for (unsigned j = i + 1; j <= ctx->gfx_pipeline_state.num_so_targets; ++j) { 1569 if (ctx->so_targets[j] && ctx->so_targets[j]->buffer == target->base.buffer) 1570 pipe_so_target_reference(&ctx->fake_so_targets[j], NULL); 1571 } 1572 } 1573 1574 ctx->fake_so_buffer_factor = 0; 1575 ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1576 1577 return true; 1578} 1579 1580void 1581d3d12_flush_cmdlist(struct d3d12_context *ctx) 1582{ 1583 d3d12_end_batch(ctx, d3d12_current_batch(ctx)); 1584 1585 ctx->current_batch_idx++; 1586 if (ctx->current_batch_idx == ARRAY_SIZE(ctx->batches)) 1587 ctx->current_batch_idx = 0; 1588 1589 d3d12_start_batch(ctx, d3d12_current_batch(ctx)); 1590} 1591 1592void 1593d3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx) 1594{ 1595 struct d3d12_batch *batch = d3d12_current_batch(ctx); 1596 1597 d3d12_foreach_submitted_batch(ctx, old_batch) 1598 d3d12_reset_batch(ctx, old_batch, PIPE_TIMEOUT_INFINITE); 1599 d3d12_flush_cmdlist(ctx); 1600 d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE); 1601} 1602 1603void 1604d3d12_transition_resource_state(struct d3d12_context *ctx, 1605 struct d3d12_resource *res, 1606 D3D12_RESOURCE_STATES state, 1607 d3d12_bind_invalidate_option bind_invalidate) 1608{ 1609 TransitionableResourceState *xres = d3d12_resource_state(res); 1610 1611 if (bind_invalidate == D3D12_BIND_INVALIDATE_FULL) 1612 d3d12_invalidate_context_bindings(ctx, res); 1613 1614 ctx->resource_state_manager->TransitionResource(xres, state); 1615} 1616 1617void 1618d3d12_transition_subresources_state(struct d3d12_context *ctx, 1619 struct d3d12_resource *res, 1620 uint32_t start_level, uint32_t num_levels, 1621 uint32_t start_layer, uint32_t num_layers, 1622 uint32_t start_plane, uint32_t num_planes, 1623 D3D12_RESOURCE_STATES state, 1624 d3d12_bind_invalidate_option bind_invalidate) 1625{ 1626 TransitionableResourceState *xres = d3d12_resource_state(res); 1627 1628 if(bind_invalidate == D3D12_BIND_INVALIDATE_FULL) 1629 d3d12_invalidate_context_bindings(ctx, res); 1630 1631 for (uint32_t l = 0; l < num_levels; l++) { 1632 const uint32_t level = start_level + l; 1633 for (uint32_t a = 0; a < num_layers; a++) { 1634 const uint32_t layer = start_layer + a; 1635 for( uint32_t p = 0; p < num_planes; p++) { 1636 const uint32_t plane = start_plane + p; 1637 uint32_t subres_id = level + (layer * res->mip_levels) + plane * (res->mip_levels * res->base.array_size); 1638 assert(subres_id < xres->NumSubresources()); 1639 ctx->resource_state_manager->TransitionSubresource(xres, subres_id, state); 1640 } 1641 } 1642 } 1643} 1644 1645void 1646d3d12_apply_resource_states(struct d3d12_context *ctx) 1647{ 1648 ctx->resource_state_manager->ApplyAllResourceTransitions(ctx->cmdlist, ctx->fence_value); 1649} 1650 1651static void 1652d3d12_clear_render_target(struct pipe_context *pctx, 1653 struct pipe_surface *psurf, 1654 const union pipe_color_union *color, 1655 unsigned dstx, unsigned dsty, 1656 unsigned width, unsigned height, 1657 bool render_condition_enabled) 1658{ 1659 struct d3d12_context *ctx = d3d12_context(pctx); 1660 struct d3d12_surface *surf = d3d12_surface(psurf); 1661 1662 if (!render_condition_enabled && ctx->current_predication) 1663 ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); 1664 1665 struct d3d12_resource *res = d3d12_resource(psurf->texture); 1666 d3d12_transition_resource_state(ctx, res, 1667 D3D12_RESOURCE_STATE_RENDER_TARGET, 1668 D3D12_BIND_INVALIDATE_FULL); 1669 d3d12_apply_resource_states(ctx); 1670 1671 enum pipe_format format = psurf->texture->format; 1672 float clear_color[4]; 1673 1674 if (util_format_is_pure_uint(format)) { 1675 for (int c = 0; c < 4; ++c) 1676 clear_color[c] = color->ui[c]; 1677 } else if (util_format_is_pure_sint(format)) { 1678 for (int c = 0; c < 4; ++c) 1679 clear_color[c] = color->i[c]; 1680 } else { 1681 for (int c = 0; c < 4; ++c) 1682 clear_color[c] = color->f[c]; 1683 } 1684 1685 D3D12_RECT rect = { (int)dstx, (int)dsty, 1686 (int)dstx + (int)width, 1687 (int)dsty + (int)height }; 1688 ctx->cmdlist->ClearRenderTargetView(surf->desc_handle.cpu_handle, 1689 clear_color, 1, &rect); 1690 1691 d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf); 1692 1693 if (!render_condition_enabled && ctx->current_predication) { 1694 ctx->cmdlist->SetPredication( 1695 d3d12_resource_resource(ctx->current_predication), 0, 1696 D3D12_PREDICATION_OP_EQUAL_ZERO); 1697 } 1698} 1699 1700static void 1701d3d12_clear_depth_stencil(struct pipe_context *pctx, 1702 struct pipe_surface *psurf, 1703 unsigned clear_flags, 1704 double depth, 1705 unsigned stencil, 1706 unsigned dstx, unsigned dsty, 1707 unsigned width, unsigned height, 1708 bool render_condition_enabled) 1709{ 1710 struct d3d12_context *ctx = d3d12_context(pctx); 1711 struct d3d12_surface *surf = d3d12_surface(psurf); 1712 1713 if (!render_condition_enabled && ctx->current_predication) 1714 ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); 1715 1716 D3D12_CLEAR_FLAGS flags = (D3D12_CLEAR_FLAGS)0; 1717 if (clear_flags & PIPE_CLEAR_DEPTH) 1718 flags |= D3D12_CLEAR_FLAG_DEPTH; 1719 if (clear_flags & PIPE_CLEAR_STENCIL) 1720 flags |= D3D12_CLEAR_FLAG_STENCIL; 1721 1722 struct d3d12_resource *res = d3d12_resource(ctx->fb.zsbuf->texture); 1723 d3d12_transition_resource_state(ctx, res, 1724 D3D12_RESOURCE_STATE_DEPTH_WRITE, 1725 D3D12_BIND_INVALIDATE_FULL); 1726 d3d12_apply_resource_states(ctx); 1727 1728 D3D12_RECT rect = { (int)dstx, (int)dsty, 1729 (int)dstx + (int)width, 1730 (int)dsty + (int)height }; 1731 ctx->cmdlist->ClearDepthStencilView(surf->desc_handle.cpu_handle, flags, 1732 depth, stencil, 1, &rect); 1733 1734 d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf); 1735 1736 if (!render_condition_enabled && ctx->current_predication) { 1737 ctx->cmdlist->SetPredication( 1738 d3d12_resource_resource(ctx->current_predication), 0, 1739 D3D12_PREDICATION_OP_EQUAL_ZERO); 1740 } 1741} 1742 1743static void 1744d3d12_clear(struct pipe_context *pctx, 1745 unsigned buffers, 1746 const struct pipe_scissor_state *scissor_state, 1747 const union pipe_color_union *color, 1748 double depth, unsigned stencil) 1749{ 1750 struct d3d12_context *ctx = d3d12_context(pctx); 1751 1752 if (buffers & PIPE_CLEAR_COLOR) { 1753 for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 1754 if (buffers & (PIPE_CLEAR_COLOR0 << i)) { 1755 struct pipe_surface *psurf = ctx->fb.cbufs[i]; 1756 d3d12_clear_render_target(pctx, psurf, color, 1757 0, 0, psurf->width, psurf->height, 1758 true); 1759 } 1760 } 1761 } 1762 1763 if (buffers & PIPE_CLEAR_DEPTHSTENCIL && ctx->fb.zsbuf) { 1764 struct pipe_surface *psurf = ctx->fb.zsbuf; 1765 d3d12_clear_depth_stencil(pctx, psurf, 1766 buffers & PIPE_CLEAR_DEPTHSTENCIL, 1767 depth, stencil, 1768 0, 0, psurf->width, psurf->height, 1769 true); 1770 } 1771} 1772 1773static void 1774d3d12_flush(struct pipe_context *pipe, 1775 struct pipe_fence_handle **fence, 1776 unsigned flags) 1777{ 1778 struct d3d12_context *ctx = d3d12_context(pipe); 1779 struct d3d12_batch *batch = d3d12_current_batch(ctx); 1780 1781 d3d12_flush_cmdlist(ctx); 1782 1783 if (fence) 1784 d3d12_fence_reference((struct d3d12_fence **)fence, batch->fence); 1785} 1786 1787static void 1788d3d12_flush_resource(struct pipe_context *pctx, 1789 struct pipe_resource *pres) 1790{ 1791 struct d3d12_context *ctx = d3d12_context(pctx); 1792 struct d3d12_resource *res = d3d12_resource(pres); 1793 1794 d3d12_transition_resource_state(ctx, res, 1795 D3D12_RESOURCE_STATE_COMMON, 1796 D3D12_BIND_INVALIDATE_FULL); 1797 d3d12_apply_resource_states(ctx); 1798} 1799 1800static void 1801d3d12_init_null_sampler(struct d3d12_context *ctx) 1802{ 1803 struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 1804 1805 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ctx->null_sampler); 1806 1807 D3D12_SAMPLER_DESC desc; 1808 desc.Filter = D3D12_FILTER_ANISOTROPIC; 1809 desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 1810 desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 1811 desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 1812 desc.MipLODBias = 0.0f; 1813 desc.MaxAnisotropy = 0; 1814 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; 1815 desc.MinLOD = 0.0f; 1816 desc.MaxLOD = 0.0f; 1817 memset(desc.BorderColor, 0, sizeof(desc.BorderColor)); 1818 screen->dev->CreateSampler(&desc, ctx->null_sampler.cpu_handle); 1819} 1820 1821static uint64_t 1822d3d12_get_timestamp(struct pipe_context *pctx) 1823{ 1824 struct d3d12_context *ctx = d3d12_context(pctx); 1825 1826 if (!ctx->timestamp_query) 1827 ctx->timestamp_query = pctx->create_query(pctx, PIPE_QUERY_TIMESTAMP, 0); 1828 1829 pipe_query_result result; 1830 pctx->end_query(pctx, ctx->timestamp_query); 1831 pctx->get_query_result(pctx, ctx->timestamp_query, true, &result); 1832 return result.u64; 1833} 1834 1835struct pipe_context * 1836d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) 1837{ 1838 struct d3d12_screen *screen = d3d12_screen(pscreen); 1839 1840 struct d3d12_context *ctx = CALLOC_STRUCT(d3d12_context); 1841 if (!ctx) 1842 return NULL; 1843 1844 ctx->base.screen = pscreen; 1845 ctx->base.priv = priv; 1846 1847 ctx->base.destroy = d3d12_context_destroy; 1848 1849 ctx->base.create_vertex_elements_state = d3d12_create_vertex_elements_state; 1850 ctx->base.bind_vertex_elements_state = d3d12_bind_vertex_elements_state; 1851 ctx->base.delete_vertex_elements_state = d3d12_delete_vertex_elements_state; 1852 1853 ctx->base.create_blend_state = d3d12_create_blend_state; 1854 ctx->base.bind_blend_state = d3d12_bind_blend_state; 1855 ctx->base.delete_blend_state = d3d12_delete_blend_state; 1856 1857 ctx->base.create_depth_stencil_alpha_state = d3d12_create_depth_stencil_alpha_state; 1858 ctx->base.bind_depth_stencil_alpha_state = d3d12_bind_depth_stencil_alpha_state; 1859 ctx->base.delete_depth_stencil_alpha_state = d3d12_delete_depth_stencil_alpha_state; 1860 1861 ctx->base.create_rasterizer_state = d3d12_create_rasterizer_state; 1862 ctx->base.bind_rasterizer_state = d3d12_bind_rasterizer_state; 1863 ctx->base.delete_rasterizer_state = d3d12_delete_rasterizer_state; 1864 1865 ctx->base.create_sampler_state = d3d12_create_sampler_state; 1866 ctx->base.bind_sampler_states = d3d12_bind_sampler_states; 1867 ctx->base.delete_sampler_state = d3d12_delete_sampler_state; 1868 1869 ctx->base.create_sampler_view = d3d12_create_sampler_view; 1870 ctx->base.set_sampler_views = d3d12_set_sampler_views; 1871 ctx->base.sampler_view_destroy = d3d12_destroy_sampler_view; 1872 1873 ctx->base.create_vs_state = d3d12_create_vs_state; 1874 ctx->base.bind_vs_state = d3d12_bind_vs_state; 1875 ctx->base.delete_vs_state = d3d12_delete_vs_state; 1876 1877 ctx->base.create_fs_state = d3d12_create_fs_state; 1878 ctx->base.bind_fs_state = d3d12_bind_fs_state; 1879 ctx->base.delete_fs_state = d3d12_delete_fs_state; 1880 1881 ctx->base.create_gs_state = d3d12_create_gs_state; 1882 ctx->base.bind_gs_state = d3d12_bind_gs_state; 1883 ctx->base.delete_gs_state = d3d12_delete_gs_state; 1884 1885 ctx->base.set_polygon_stipple = d3d12_set_polygon_stipple; 1886 ctx->base.set_vertex_buffers = d3d12_set_vertex_buffers; 1887 ctx->base.set_viewport_states = d3d12_set_viewport_states; 1888 ctx->base.set_scissor_states = d3d12_set_scissor_states; 1889 ctx->base.set_constant_buffer = d3d12_set_constant_buffer; 1890 ctx->base.set_framebuffer_state = d3d12_set_framebuffer_state; 1891 ctx->base.set_clip_state = d3d12_set_clip_state; 1892 ctx->base.set_blend_color = d3d12_set_blend_color; 1893 ctx->base.set_sample_mask = d3d12_set_sample_mask; 1894 ctx->base.set_stencil_ref = d3d12_set_stencil_ref; 1895 1896 ctx->base.create_stream_output_target = d3d12_create_stream_output_target; 1897 ctx->base.stream_output_target_destroy = d3d12_stream_output_target_destroy; 1898 ctx->base.set_stream_output_targets = d3d12_set_stream_output_targets; 1899 1900 ctx->base.get_timestamp = d3d12_get_timestamp; 1901 1902 ctx->base.clear = d3d12_clear; 1903 ctx->base.clear_render_target = d3d12_clear_render_target; 1904 ctx->base.clear_depth_stencil = d3d12_clear_depth_stencil; 1905 ctx->base.draw_vbo = d3d12_draw_vbo; 1906 ctx->base.flush = d3d12_flush; 1907 ctx->base.flush_resource = d3d12_flush_resource; 1908 1909 ctx->gfx_pipeline_state.sample_mask = ~0; 1910 1911 d3d12_context_surface_init(&ctx->base); 1912 d3d12_context_resource_init(&ctx->base); 1913 d3d12_context_query_init(&ctx->base); 1914 d3d12_context_blit_init(&ctx->base); 1915 1916 1917 slab_create_child(&ctx->transfer_pool, &d3d12_screen(pscreen)->transfer_pool); 1918 1919 ctx->base.stream_uploader = u_upload_create_default(&ctx->base); 1920 ctx->base.const_uploader = u_upload_create_default(&ctx->base); 1921 u_suballocator_init(&ctx->so_allocator, &ctx->base, 4096, 0, 1922 PIPE_USAGE_DEFAULT, 1923 0, true); 1924 1925 struct primconvert_config cfg; 1926 cfg.primtypes_mask = 1 << PIPE_PRIM_POINTS | 1927 1 << PIPE_PRIM_LINES | 1928 1 << PIPE_PRIM_LINE_STRIP | 1929 1 << PIPE_PRIM_TRIANGLES | 1930 1 << PIPE_PRIM_TRIANGLE_STRIP; 1931 cfg.fixed_prim_restart = true; 1932 ctx->primconvert = util_primconvert_create_config(&ctx->base, &cfg); 1933 if (!ctx->primconvert) { 1934 debug_printf("D3D12: failed to create primconvert\n"); 1935 return NULL; 1936 } 1937 1938 d3d12_gfx_pipeline_state_cache_init(ctx); 1939 d3d12_root_signature_cache_init(ctx); 1940 d3d12_gs_variant_cache_init(ctx); 1941 1942 util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT); 1943 if (!d3d12_mod) { 1944 debug_printf("D3D12: failed to load D3D12.DLL\n"); 1945 return NULL; 1946 } 1947 ctx->D3D12SerializeVersionedRootSignature = 1948 (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)util_dl_get_proc_address(d3d12_mod, "D3D12SerializeVersionedRootSignature"); 1949 1950 if (FAILED(screen->dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, 1951 IID_PPV_ARGS(&ctx->cmdqueue_fence)))) { 1952 FREE(ctx); 1953 return NULL; 1954 } 1955 1956 for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) { 1957 if (!d3d12_init_batch(ctx, &ctx->batches[i])) { 1958 FREE(ctx); 1959 return NULL; 1960 } 1961 } 1962 d3d12_start_batch(ctx, &ctx->batches[0]); 1963 1964 ctx->sampler_pool = d3d12_descriptor_pool_new(screen, 1965 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 1966 64); 1967 if (!ctx->sampler_pool) { 1968 FREE(ctx); 1969 return NULL; 1970 } 1971 d3d12_init_null_sampler(ctx); 1972 1973 ctx->validation_tools = d3d12_validator_create(); 1974 1975 ctx->blitter = util_blitter_create(&ctx->base); 1976 if (!ctx->blitter) 1977 return NULL; 1978 1979 ctx->resource_state_manager = new ResourceStateManager(); 1980 1981 if (!d3d12_init_polygon_stipple(&ctx->base)) { 1982 debug_printf("D3D12: failed to initialize polygon stipple resources\n"); 1983 FREE(ctx); 1984 return NULL; 1985 } 1986 1987 return &ctx->base; 1988} 1989 1990bool 1991d3d12_need_zero_one_depth_range(struct d3d12_context *ctx) 1992{ 1993 struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 1994 1995 /** 1996 * OpenGL Compatibility spec, section 15.2.3 (Shader Outputs) says 1997 * the following: 1998 * 1999 * For fixed-point depth buffers, the final fragment depth written by 2000 * a fragment shader is first clamped to [0, 1] and then converted to 2001 * fixed-point as if it were a window z value (see section 13.8.1). 2002 * For floating-point depth buffers, conversion is not performed but 2003 * clamping is. Note that the depth range computation is not applied 2004 * here, only the conversion to fixed-point. 2005 * 2006 * However, the D3D11.3 Functional Spec, section 17.10 (Depth Clamp) says 2007 * the following: 2008 * 2009 * Depth values that reach the Output Merger, whether coming from 2010 * interpolation or from Pixel Shader output (replacing the 2011 * interpolated z), are always clamped: 2012 * z = min(Viewport.MaxDepth,max(Viewport.MinDepth,z)) 2013 * following the D3D11 Floating Point Rules(3.1) for min/max. 2014 * 2015 * This means that we can't always use the fixed-function viewport-mapping 2016 * D3D provides. 2017 * 2018 * There's only one case where the difference matters: When the fragment 2019 * shader writes a non-implicit value to gl_FragDepth. In all other 2020 * cases, the fragment either shouldn't have been rasterized in the 2021 * first place, or the implicit gl_FragCoord.z-value should already have 2022 * been clamped to the depth-range. 2023 * 2024 * For simplicity, let's assume that an explicitly written frag-result 2025 * doesn't simply forward the value of gl_FragCoord.z. If it does, we'll 2026 * end up generating needless code, but the result will be correct. 2027 */ 2028 2029 return fs->initial->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH); 2030} 2031