2 * Copyright © Microsoft Corporation
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:
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
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
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"
43 #include "util/indices/u_primconvert.h"
44 #include "util/u_atomic.h"
45 #include "util/u_blitter.h"
46 #include "util/u_dual_blend.h"
47 #include "util/u_framebuffer.h"
48 #include "util/u_helpers.h"
49 #include "util/u_inlines.h"
50 #include "util/u_memory.h"
51 #include "util/u_upload_mgr.h"
52 #include "util/u_pstipple.h"
53 #include "util/u_dl.h"
54 #include "nir_to_dxil.h"
56 #include <dxguids/dxguids.h>
61 #include "dxil_validator.h"
65 d3d12_context_destroy(struct pipe_context *pctx)
67 struct d3d12_context *ctx = d3d12_context(pctx);
69 struct d3d12_screen *screen = d3d12_screen(pctx->screen);
70 mtx_lock(&screen->submit_mutex);
71 list_del(&ctx->context_list_entry);
72 mtx_unlock(&screen->submit_mutex);
75 if (ctx->dxil_validator)
76 dxil_destroy_validator(ctx->dxil_validator);
80 ctx->dev_config->Release();
82 if (ctx->timestamp_query)
83 pctx->destroy_query(pctx, ctx->timestamp_query);
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 util_dynarray_fini(&ctx->ended_queries);
106 FREE(ctx->pstipple.sampler_cso);
108 u_suballocator_destroy(&ctx->query_allocator);
110 if (pctx->stream_uploader)
111 u_upload_destroy(pctx->stream_uploader);
112 if (pctx->const_uploader)
113 u_upload_destroy(pctx->const_uploader);
119 d3d12_create_vertex_elements_state(struct pipe_context *pctx,
120 unsigned num_elements,
121 const struct pipe_vertex_element *elements)
123 struct d3d12_vertex_elements_state *cso = CALLOC_STRUCT(d3d12_vertex_elements_state);
127 for (unsigned i = 0; i < num_elements; ++i) {
128 cso->elements[i].SemanticName = "TEXCOORD";
129 cso->elements[i].SemanticIndex = i;
131 enum pipe_format format_helper =
132 d3d12_emulated_vtx_format((enum pipe_format)elements[i].src_format);
133 bool needs_emulation = format_helper != elements[i].src_format;
134 cso->needs_format_emulation |= needs_emulation;
135 cso->format_conversion[i] =
136 needs_emulation ? (enum pipe_format)elements[i].src_format : PIPE_FORMAT_NONE;
138 cso->elements[i].Format = d3d12_get_format(format_helper);
139 assert(cso->elements[i].Format != DXGI_FORMAT_UNKNOWN);
140 cso->elements[i].InputSlot = elements[i].vertex_buffer_index;
141 cso->elements[i].AlignedByteOffset = elements[i].src_offset;
143 if (elements[i].instance_divisor) {
144 cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
145 cso->elements[i].InstanceDataStepRate = elements[i].instance_divisor;
147 cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
148 cso->elements[i].InstanceDataStepRate = 0;
152 cso->num_elements = num_elements;
157 d3d12_bind_vertex_elements_state(struct pipe_context *pctx,
160 struct d3d12_context *ctx = d3d12_context(pctx);
161 ctx->gfx_pipeline_state.ves = (struct d3d12_vertex_elements_state *)ve;
162 ctx->state_dirty |= D3D12_DIRTY_VERTEX_ELEMENTS;
166 d3d12_delete_vertex_elements_state(struct pipe_context *pctx,
173 blend_factor_rgb(enum pipe_blendfactor factor)
176 case PIPE_BLENDFACTOR_ZERO: return D3D12_BLEND_ZERO;
177 case PIPE_BLENDFACTOR_ONE: return D3D12_BLEND_ONE;
178 case PIPE_BLENDFACTOR_SRC_COLOR: return D3D12_BLEND_SRC_COLOR;
179 case PIPE_BLENDFACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA;
180 case PIPE_BLENDFACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA;
181 case PIPE_BLENDFACTOR_DST_COLOR: return D3D12_BLEND_DEST_COLOR;
182 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT;
183 case PIPE_BLENDFACTOR_CONST_COLOR: return D3D12_BLEND_BLEND_FACTOR;
184 case PIPE_BLENDFACTOR_SRC1_COLOR: return D3D12_BLEND_SRC1_COLOR;
185 case PIPE_BLENDFACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA;
186 case PIPE_BLENDFACTOR_INV_SRC_COLOR: return D3D12_BLEND_INV_SRC_COLOR;
187 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA;
188 case PIPE_BLENDFACTOR_INV_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA;
189 case PIPE_BLENDFACTOR_INV_DST_COLOR: return D3D12_BLEND_INV_DEST_COLOR;
190 case PIPE_BLENDFACTOR_INV_CONST_COLOR: return D3D12_BLEND_INV_BLEND_FACTOR;
191 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return D3D12_BLEND_INV_SRC1_COLOR;
192 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA;
193 case PIPE_BLENDFACTOR_CONST_ALPHA: return D3D12_BLEND_BLEND_FACTOR; /* Doesn't exist in D3D12 */
194 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return D3D12_BLEND_INV_BLEND_FACTOR; /* Doesn't exist in D3D12 */
196 unreachable("unexpected blend factor");
200 blend_factor_alpha(enum pipe_blendfactor factor)
203 case PIPE_BLENDFACTOR_ZERO: return D3D12_BLEND_ZERO;
204 case PIPE_BLENDFACTOR_ONE: return D3D12_BLEND_ONE;
205 case PIPE_BLENDFACTOR_SRC_COLOR:
206 case PIPE_BLENDFACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA;
207 case PIPE_BLENDFACTOR_DST_COLOR:
208 case PIPE_BLENDFACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA;
209 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT;
210 case PIPE_BLENDFACTOR_CONST_COLOR:
211 case PIPE_BLENDFACTOR_CONST_ALPHA: return D3D12_BLEND_BLEND_FACTOR;
212 case PIPE_BLENDFACTOR_SRC1_COLOR:
213 case PIPE_BLENDFACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA;
214 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
215 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA;
216 case PIPE_BLENDFACTOR_INV_DST_COLOR:
217 case PIPE_BLENDFACTOR_INV_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA;
218 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
219 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA;
220 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
221 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return D3D12_BLEND_INV_BLEND_FACTOR;
223 unreachable("unexpected blend factor");
227 need_blend_factor_rgb(enum pipe_blendfactor factor)
230 case PIPE_BLENDFACTOR_CONST_COLOR:
231 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
232 return D3D12_BLEND_FACTOR_COLOR;
233 case PIPE_BLENDFACTOR_CONST_ALPHA:
234 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
235 return D3D12_BLEND_FACTOR_ALPHA;
238 return D3D12_BLEND_FACTOR_NONE;
243 need_blend_factor_alpha(enum pipe_blendfactor factor)
246 case PIPE_BLENDFACTOR_CONST_COLOR:
247 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
248 case PIPE_BLENDFACTOR_CONST_ALPHA:
249 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
250 return D3D12_BLEND_FACTOR_ANY;
253 return D3D12_BLEND_FACTOR_NONE;
257 static D3D12_BLEND_OP
258 blend_op(enum pipe_blend_func func)
261 case PIPE_BLEND_ADD: return D3D12_BLEND_OP_ADD;
262 case PIPE_BLEND_SUBTRACT: return D3D12_BLEND_OP_SUBTRACT;
263 case PIPE_BLEND_REVERSE_SUBTRACT: return D3D12_BLEND_OP_REV_SUBTRACT;
264 case PIPE_BLEND_MIN: return D3D12_BLEND_OP_MIN;
265 case PIPE_BLEND_MAX: return D3D12_BLEND_OP_MAX;
267 unreachable("unexpected blend function");
270 static D3D12_COMPARISON_FUNC
271 compare_op(enum pipe_compare_func op)
274 case PIPE_FUNC_NEVER: return D3D12_COMPARISON_FUNC_NEVER;
275 case PIPE_FUNC_LESS: return D3D12_COMPARISON_FUNC_LESS;
276 case PIPE_FUNC_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL;
277 case PIPE_FUNC_LEQUAL: return D3D12_COMPARISON_FUNC_LESS_EQUAL;
278 case PIPE_FUNC_GREATER: return D3D12_COMPARISON_FUNC_GREATER;
279 case PIPE_FUNC_NOTEQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL;
280 case PIPE_FUNC_GEQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
281 case PIPE_FUNC_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS;
283 unreachable("unexpected compare");
286 static D3D12_LOGIC_OP
287 logic_op(enum pipe_logicop func)
290 case PIPE_LOGICOP_CLEAR: return D3D12_LOGIC_OP_CLEAR;
291 case PIPE_LOGICOP_NOR: return D3D12_LOGIC_OP_NOR;
292 case PIPE_LOGICOP_AND_INVERTED: return D3D12_LOGIC_OP_AND_INVERTED;
293 case PIPE_LOGICOP_COPY_INVERTED: return D3D12_LOGIC_OP_COPY_INVERTED;
294 case PIPE_LOGICOP_AND_REVERSE: return D3D12_LOGIC_OP_AND_REVERSE;
295 case PIPE_LOGICOP_INVERT: return D3D12_LOGIC_OP_INVERT;
296 case PIPE_LOGICOP_XOR: return D3D12_LOGIC_OP_XOR;
297 case PIPE_LOGICOP_NAND: return D3D12_LOGIC_OP_NAND;
298 case PIPE_LOGICOP_AND: return D3D12_LOGIC_OP_AND;
299 case PIPE_LOGICOP_EQUIV: return D3D12_LOGIC_OP_EQUIV;
300 case PIPE_LOGICOP_NOOP: return D3D12_LOGIC_OP_NOOP;
301 case PIPE_LOGICOP_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED;
302 case PIPE_LOGICOP_COPY: return D3D12_LOGIC_OP_COPY;
303 case PIPE_LOGICOP_OR_REVERSE: return D3D12_LOGIC_OP_OR_REVERSE;
304 case PIPE_LOGICOP_OR: return D3D12_LOGIC_OP_OR;
305 case PIPE_LOGICOP_SET: return D3D12_LOGIC_OP_SET;
307 unreachable("unexpected logicop function");
311 color_write_mask(unsigned colormask)
315 if (colormask & PIPE_MASK_R)
316 mask |= D3D12_COLOR_WRITE_ENABLE_RED;
317 if (colormask & PIPE_MASK_G)
318 mask |= D3D12_COLOR_WRITE_ENABLE_GREEN;
319 if (colormask & PIPE_MASK_B)
320 mask |= D3D12_COLOR_WRITE_ENABLE_BLUE;
321 if (colormask & PIPE_MASK_A)
322 mask |= D3D12_COLOR_WRITE_ENABLE_ALPHA;
328 d3d12_create_blend_state(struct pipe_context *pctx,
329 const struct pipe_blend_state *blend_state)
331 struct d3d12_blend_state *state = CALLOC_STRUCT(d3d12_blend_state);
335 if (blend_state->logicop_enable) {
336 state->desc.RenderTarget[0].LogicOpEnable = TRUE;
337 state->desc.RenderTarget[0].LogicOp = logic_op((pipe_logicop) blend_state->logicop_func);
342 state->desc.AlphaToCoverageEnable = blend_state->alpha_to_coverage;
345 if (blend_state->independent_blend_enable) {
346 state->desc.IndependentBlendEnable = TRUE;
347 num_targets = PIPE_MAX_COLOR_BUFS;
350 for (int i = 0; i < num_targets; ++i) {
351 const struct pipe_rt_blend_state *rt = blend_state->rt + i;
353 if (rt->blend_enable) {
354 state->desc.RenderTarget[i].BlendEnable = TRUE;
355 state->desc.RenderTarget[i].SrcBlend = blend_factor_rgb((pipe_blendfactor) rt->rgb_src_factor);
356 state->desc.RenderTarget[i].DestBlend = blend_factor_rgb((pipe_blendfactor) rt->rgb_dst_factor);
357 state->desc.RenderTarget[i].BlendOp = blend_op((pipe_blend_func) rt->rgb_func);
358 state->desc.RenderTarget[i].SrcBlendAlpha = blend_factor_alpha((pipe_blendfactor) rt->alpha_src_factor);
359 state->desc.RenderTarget[i].DestBlendAlpha = blend_factor_alpha((pipe_blendfactor) rt->alpha_dst_factor);
360 state->desc.RenderTarget[i].BlendOpAlpha = blend_op((pipe_blend_func) rt->alpha_func);
362 state->blend_factor_flags |= need_blend_factor_rgb((pipe_blendfactor) rt->rgb_src_factor);
363 state->blend_factor_flags |= need_blend_factor_rgb((pipe_blendfactor) rt->rgb_dst_factor);
364 state->blend_factor_flags |= need_blend_factor_alpha((pipe_blendfactor) rt->alpha_src_factor);
365 state->blend_factor_flags |= need_blend_factor_alpha((pipe_blendfactor) rt->alpha_dst_factor);
367 if (state->blend_factor_flags == (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ALPHA) &&
368 (d3d12_debug & D3D12_DEBUG_VERBOSE)) {
369 /* We can't set a blend factor for both constant color and constant alpha */
370 debug_printf("D3D12: unsupported blend factors combination (const color and const alpha)\n");
373 if (util_blend_state_is_dual(blend_state, i))
374 state->is_dual_src = true;
377 state->desc.RenderTarget[i].RenderTargetWriteMask = color_write_mask(rt->colormask);
384 d3d12_bind_blend_state(struct pipe_context *pctx, void *blend_state)
386 struct d3d12_context *ctx = d3d12_context(pctx);
387 struct d3d12_blend_state *new_state = (struct d3d12_blend_state *) blend_state;
388 struct d3d12_blend_state *old_state = ctx->gfx_pipeline_state.blend;
390 ctx->gfx_pipeline_state.blend = new_state;
391 ctx->state_dirty |= D3D12_DIRTY_BLEND;
392 if (new_state == NULL || old_state == NULL ||
393 new_state->blend_factor_flags != old_state->blend_factor_flags)
394 ctx->state_dirty |= D3D12_DIRTY_BLEND_COLOR;
398 d3d12_delete_blend_state(struct pipe_context *pctx, void *blend_state)
400 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), blend_state);
404 static D3D12_STENCIL_OP
405 stencil_op(enum pipe_stencil_op op)
408 case PIPE_STENCIL_OP_KEEP: return D3D12_STENCIL_OP_KEEP;
409 case PIPE_STENCIL_OP_ZERO: return D3D12_STENCIL_OP_ZERO;
410 case PIPE_STENCIL_OP_REPLACE: return D3D12_STENCIL_OP_REPLACE;
411 case PIPE_STENCIL_OP_INCR: return D3D12_STENCIL_OP_INCR_SAT;
412 case PIPE_STENCIL_OP_DECR: return D3D12_STENCIL_OP_DECR_SAT;
413 case PIPE_STENCIL_OP_INCR_WRAP: return D3D12_STENCIL_OP_INCR;
414 case PIPE_STENCIL_OP_DECR_WRAP: return D3D12_STENCIL_OP_DECR;
415 case PIPE_STENCIL_OP_INVERT: return D3D12_STENCIL_OP_INVERT;
417 unreachable("unexpected op");
420 static D3D12_DEPTH_STENCILOP_DESC
421 stencil_op_state(const struct pipe_stencil_state *src)
423 D3D12_DEPTH_STENCILOP_DESC ret;
424 ret.StencilFailOp = stencil_op((pipe_stencil_op) src->fail_op);
425 ret.StencilPassOp = stencil_op((pipe_stencil_op) src->zpass_op);
426 ret.StencilDepthFailOp = stencil_op((pipe_stencil_op) src->zfail_op);
427 ret.StencilFunc = compare_op((pipe_compare_func) src->func);
432 d3d12_create_depth_stencil_alpha_state(struct pipe_context *pctx,
433 const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)
435 struct d3d12_depth_stencil_alpha_state *dsa = CALLOC_STRUCT(d3d12_depth_stencil_alpha_state);
439 if (depth_stencil_alpha->depth_enabled) {
440 dsa->desc.DepthEnable = TRUE;
441 dsa->desc.DepthFunc = compare_op((pipe_compare_func) depth_stencil_alpha->depth_func);
444 /* TODO Add support for GL_depth_bound_tests */
446 if (depth_stencil_alpha->depth.bounds_test) {
447 dsa->desc.DepthBoundsTestEnable = TRUE;
448 dsa->min_depth_bounds = depth_stencil_alpha->depth.bounds_min;
449 dsa->max_depth_bounds = depth_stencil_alpha->depth.bounds_max;
453 if (depth_stencil_alpha->stencil[0].enabled) {
454 dsa->desc.StencilEnable = TRUE;
455 dsa->desc.FrontFace = stencil_op_state(depth_stencil_alpha->stencil);
458 if (depth_stencil_alpha->stencil[1].enabled)
459 dsa->desc.BackFace = stencil_op_state(depth_stencil_alpha->stencil + 1);
461 dsa->desc.BackFace = dsa->desc.FrontFace;
463 dsa->desc.StencilReadMask = depth_stencil_alpha->stencil[0].valuemask; /* FIXME Back face mask */
464 dsa->desc.StencilWriteMask = depth_stencil_alpha->stencil[0].writemask; /* FIXME Back face mask */
465 dsa->desc.DepthWriteMask = (D3D12_DEPTH_WRITE_MASK) depth_stencil_alpha->depth_writemask;
471 d3d12_bind_depth_stencil_alpha_state(struct pipe_context *pctx,
474 struct d3d12_context *ctx = d3d12_context(pctx);
475 ctx->gfx_pipeline_state.zsa = (struct d3d12_depth_stencil_alpha_state *) dsa;
476 ctx->state_dirty |= D3D12_DIRTY_ZSA;
480 d3d12_delete_depth_stencil_alpha_state(struct pipe_context *pctx,
483 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), dsa_state);
487 static D3D12_FILL_MODE
488 fill_mode(unsigned mode)
491 case PIPE_POLYGON_MODE_FILL:
492 return D3D12_FILL_MODE_SOLID;
493 case PIPE_POLYGON_MODE_LINE:
494 return D3D12_FILL_MODE_WIREFRAME;
495 case PIPE_POLYGON_MODE_POINT:
496 return D3D12_FILL_MODE_SOLID;
499 unreachable("unsupported fill-mode");
504 d3d12_create_rasterizer_state(struct pipe_context *pctx,
505 const struct pipe_rasterizer_state *rs_state)
507 struct d3d12_rasterizer_state *cso = CALLOC_STRUCT(d3d12_rasterizer_state);
511 cso->base = *rs_state;
513 assert(rs_state->depth_clip_near == rs_state->depth_clip_far);
515 switch (rs_state->cull_face) {
517 if (rs_state->fill_front != rs_state->fill_back) {
518 cso->base.cull_face = PIPE_FACE_BACK;
519 cso->desc.CullMode = D3D12_CULL_MODE_BACK;
520 cso->desc.FillMode = fill_mode(rs_state->fill_front);
522 /* create a modified CSO for the back-state, so we can draw with
525 struct pipe_rasterizer_state templ = *rs_state;
526 templ.cull_face = PIPE_FACE_FRONT;
527 templ.fill_front = rs_state->fill_back;
528 cso->twoface_back = d3d12_create_rasterizer_state(pctx, &templ);
530 if (!cso->twoface_back) {
535 cso->desc.CullMode = D3D12_CULL_MODE_NONE;
536 cso->desc.FillMode = fill_mode(rs_state->fill_front);
540 case PIPE_FACE_FRONT:
541 cso->desc.CullMode = D3D12_CULL_MODE_FRONT;
542 cso->desc.FillMode = fill_mode(rs_state->fill_back);
546 cso->desc.CullMode = D3D12_CULL_MODE_BACK;
547 cso->desc.FillMode = fill_mode(rs_state->fill_front);
550 case PIPE_FACE_FRONT_AND_BACK:
551 /* this is wrong, and we shouldn't actually have to support this! */
552 cso->desc.CullMode = D3D12_CULL_MODE_NONE;
553 cso->desc.FillMode = D3D12_FILL_MODE_SOLID;
557 unreachable("unsupported cull-mode");
560 cso->desc.FrontCounterClockwise = rs_state->front_ccw;
561 cso->desc.DepthClipEnable = rs_state->depth_clip_near;
562 cso->desc.MultisampleEnable = rs_state->multisample;
563 cso->desc.AntialiasedLineEnable = rs_state->line_smooth;
564 cso->desc.ForcedSampleCount = 0; // TODO
565 cso->desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; /* Not Implemented */
571 d3d12_bind_rasterizer_state(struct pipe_context *pctx, void *rs_state)
573 struct d3d12_context *ctx = d3d12_context(pctx);
574 ctx->gfx_pipeline_state.rast = (struct d3d12_rasterizer_state *)rs_state;
575 ctx->state_dirty |= D3D12_DIRTY_RASTERIZER | D3D12_DIRTY_SCISSOR;
579 d3d12_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state)
581 d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), rs_state);
585 static D3D12_TEXTURE_ADDRESS_MODE
586 sampler_address_mode(enum pipe_tex_wrap wrap, enum pipe_tex_filter filter)
589 case PIPE_TEX_WRAP_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
590 case PIPE_TEX_WRAP_CLAMP: return filter == PIPE_TEX_FILTER_NEAREST ?
591 D3D12_TEXTURE_ADDRESS_MODE_CLAMP :
592 D3D12_TEXTURE_ADDRESS_MODE_BORDER;
593 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
594 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
595 case PIPE_TEX_WRAP_MIRROR_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
596 case PIPE_TEX_WRAP_MIRROR_CLAMP: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; /* not technically correct, but kinda works */
597 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE;
598 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; /* FIXME: Doesn't exist in D3D12 */
600 unreachable("unexpected wrap");
604 get_filter(const struct pipe_sampler_state *state)
606 static const D3D12_FILTER lut[16] = {
607 D3D12_FILTER_MIN_MAG_MIP_POINT,
608 D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR,
609 D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT,
610 D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR,
611 D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT,
612 D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
613 D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT,
614 D3D12_FILTER_MIN_MAG_MIP_LINEAR,
615 D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT,
616 D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR,
617 D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT,
618 D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR,
619 D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT,
620 D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
621 D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT,
622 D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR,
625 static const D3D12_FILTER anisotropic_lut[2] = {
626 D3D12_FILTER_ANISOTROPIC,
627 D3D12_FILTER_COMPARISON_ANISOTROPIC,
630 if (state->max_anisotropy > 1) {
631 return anisotropic_lut[state->compare_mode];
633 int idx = (state->mag_img_filter << 1) |
634 (state->min_img_filter << 2) |
635 (state->compare_mode << 3);
636 if (state->min_mip_filter != PIPE_TEX_MIPFILTER_NONE)
637 idx |= state->min_mip_filter;
643 d3d12_create_sampler_state(struct pipe_context *pctx,
644 const struct pipe_sampler_state *state)
646 struct d3d12_context *ctx = d3d12_context(pctx);
647 struct d3d12_screen *screen = d3d12_screen(pctx->screen);
648 struct d3d12_sampler_state *ss;
649 D3D12_SAMPLER_DESC desc = {};
653 ss = CALLOC_STRUCT(d3d12_sampler_state);
654 ss->filter = (pipe_tex_filter)state->min_img_filter;
655 ss->wrap_r = (pipe_tex_wrap)state->wrap_r;
656 ss->wrap_s = (pipe_tex_wrap)state->wrap_s;
657 ss->wrap_t = (pipe_tex_wrap)state->wrap_t;
658 ss->lod_bias = state->lod_bias;
659 ss->min_lod = state->min_lod;
660 ss->max_lod = state->max_lod;
661 memcpy(ss->border_color, state->border_color.f, sizeof(float) * 4);
662 ss->compare_func = (pipe_compare_func)state->compare_func;
664 if (state->min_mip_filter < PIPE_TEX_MIPFILTER_NONE) {
665 desc.MinLOD = state->min_lod;
666 desc.MaxLOD = state->max_lod;
667 } else if (state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
671 unreachable("unexpected mip filter");
674 if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
675 desc.ComparisonFunc = compare_op((pipe_compare_func) state->compare_func);
676 } else if (state->compare_mode == PIPE_TEX_COMPARE_NONE) {
677 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
679 unreachable("unexpected comparison mode");
681 desc.MaxAnisotropy = state->max_anisotropy;
682 desc.Filter = get_filter(state);
684 desc.AddressU = sampler_address_mode((pipe_tex_wrap) state->wrap_s,
685 (pipe_tex_filter) state->min_img_filter);
686 desc.AddressV = sampler_address_mode((pipe_tex_wrap) state->wrap_t,
687 (pipe_tex_filter) state->min_img_filter);
688 desc.AddressW = sampler_address_mode((pipe_tex_wrap) state->wrap_r,
689 (pipe_tex_filter) state->min_img_filter);
690 desc.MipLODBias = CLAMP(state->lod_bias, -16.0f, 15.99f);
691 memcpy(desc.BorderColor, state->border_color.f, sizeof(float) * 4);
693 // TODO Normalized Coordinates?
694 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ss->handle);
695 screen->dev->CreateSampler(&desc, ss->handle.cpu_handle);
697 if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
698 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
699 desc.Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
701 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool,
702 &ss->handle_without_shadow);
703 screen->dev->CreateSampler(&desc,
704 ss->handle_without_shadow.cpu_handle);
705 ss->is_shadow_sampler = true;
712 d3d12_bind_sampler_states(struct pipe_context *pctx,
713 enum pipe_shader_type shader,
715 unsigned num_samplers,
718 struct d3d12_context *ctx = d3d12_context(pctx);
720 #define STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(X) \
721 static_assert((enum compare_func)PIPE_FUNC_##X == COMPARE_FUNC_##X, #X " needs switch case");
723 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(LESS);
724 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(GREATER);
725 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(LEQUAL);
726 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(GEQUAL);
727 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(NOTEQUAL);
728 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(NEVER);
729 STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(ALWAYS);
731 #undef STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC
733 for (unsigned i = 0; i < num_samplers; ++i) {
734 d3d12_sampler_state *sampler = (struct d3d12_sampler_state*) samplers[i];
735 ctx->samplers[shader][start_slot + i] = sampler;
736 dxil_wrap_sampler_state &wrap = ctx->tex_wrap_states[shader][start_slot + i];
738 wrap.wrap[0] = sampler->wrap_s;
739 wrap.wrap[1] = sampler->wrap_t;
740 wrap.wrap[2] = sampler->wrap_r;
741 wrap.lod_bias = sampler->lod_bias;
742 wrap.min_lod = sampler->min_lod;
743 wrap.max_lod = sampler->max_lod;
744 memcpy(wrap.border_color, sampler->border_color, 4 * sizeof(float));
745 ctx->tex_compare_func[shader][start_slot + i] = (enum compare_func)sampler->compare_func;
747 memset(&wrap, 0, sizeof (dxil_wrap_sampler_state));
751 ctx->num_samplers[shader] = start_slot + num_samplers;
752 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SAMPLERS;
756 d3d12_delete_sampler_state(struct pipe_context *pctx,
759 struct d3d12_batch *batch = d3d12_current_batch(d3d12_context(pctx));
760 struct d3d12_sampler_state *state = (struct d3d12_sampler_state*) ss;
761 util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle,
763 if (state->is_shadow_sampler)
764 util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle,
765 state->handle_without_shadow);
769 static D3D12_SRV_DIMENSION
770 view_dimension(enum pipe_texture_target target, unsigned samples)
773 case PIPE_BUFFER: return D3D12_SRV_DIMENSION_BUFFER;
774 case PIPE_TEXTURE_1D: return D3D12_SRV_DIMENSION_TEXTURE1D;
775 case PIPE_TEXTURE_1D_ARRAY: return D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
776 case PIPE_TEXTURE_RECT:
777 case PIPE_TEXTURE_2D:
778 return samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMS :
779 D3D12_SRV_DIMENSION_TEXTURE2D;
780 case PIPE_TEXTURE_2D_ARRAY:
781 return samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY :
782 D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
783 case PIPE_TEXTURE_CUBE: return D3D12_SRV_DIMENSION_TEXTURECUBE;
784 case PIPE_TEXTURE_CUBE_ARRAY: return D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
785 case PIPE_TEXTURE_3D: return D3D12_SRV_DIMENSION_TEXTURE3D;
787 unreachable("unexpected target");
791 static D3D12_SHADER_COMPONENT_MAPPING
792 component_mapping(enum pipe_swizzle swizzle, D3D12_SHADER_COMPONENT_MAPPING id)
795 case PIPE_SWIZZLE_X: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0;
796 case PIPE_SWIZZLE_Y: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1;
797 case PIPE_SWIZZLE_Z: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2;
798 case PIPE_SWIZZLE_W: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3;
799 case PIPE_SWIZZLE_0: return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0;
800 case PIPE_SWIZZLE_1: return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1;
801 case PIPE_SWIZZLE_NONE: return id;
803 unreachable("unexpected swizzle");
808 d3d12_init_sampler_view_descriptor(struct d3d12_sampler_view *sampler_view)
810 struct pipe_sampler_view *state = &sampler_view->base;
811 struct pipe_resource *texture = state->texture;
812 struct d3d12_resource *res = d3d12_resource(texture);
813 struct d3d12_screen *screen = d3d12_screen(texture->screen);
815 struct d3d12_format_info format_info = d3d12_get_format_info(res->overall_format, state->format, state->target);
816 D3D12_SHADER_RESOURCE_VIEW_DESC desc = {};
817 desc.Format = d3d12_get_resource_srv_format(state->format, state->target);
818 desc.ViewDimension = view_dimension(state->target, texture->nr_samples);
820 /* Integer cube textures are not really supported, because TextureLoad doesn't exist
821 * for cube maps, and we sampling is not supported for integer textures, so we have to
822 * handle this SRV as if it were a 2D texture array */
823 if ((desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE ||
824 desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) &&
825 util_format_is_pure_integer(state->format)) {
826 desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
829 desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
830 component_mapping((pipe_swizzle)sampler_view->swizzle_override_r, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0),
831 component_mapping((pipe_swizzle)sampler_view->swizzle_override_g, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1),
832 component_mapping((pipe_swizzle)sampler_view->swizzle_override_b, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2),
833 component_mapping((pipe_swizzle)sampler_view->swizzle_override_a, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3)
837 ID3D12Resource *d3d12_res = d3d12_resource_underlying(res, &offset);
838 assert(offset == 0 || res->base.b.target == PIPE_BUFFER);
840 unsigned array_size = state->u.tex.last_layer - state->u.tex.first_layer + 1;
841 switch (desc.ViewDimension) {
842 case D3D12_SRV_DIMENSION_TEXTURE1D:
843 if (state->u.tex.first_layer > 0)
844 debug_printf("D3D12: can't create 1D SRV from layer %d\n",
845 state->u.tex.first_layer);
847 desc.Texture1D.MostDetailedMip = state->u.tex.first_level;
848 desc.Texture1D.MipLevels = sampler_view->mip_levels;
849 desc.Texture1D.ResourceMinLODClamp = 0.0f;
851 case D3D12_SRV_DIMENSION_TEXTURE1DARRAY:
852 desc.Texture1DArray.MostDetailedMip = state->u.tex.first_level;
853 desc.Texture1DArray.MipLevels = sampler_view->mip_levels;
854 desc.Texture1DArray.ResourceMinLODClamp = 0.0f;
855 desc.Texture1DArray.FirstArraySlice = state->u.tex.first_layer;
856 desc.Texture1DArray.ArraySize = array_size;
858 case D3D12_SRV_DIMENSION_TEXTURE2D:
859 if (state->u.tex.first_layer > 0)
860 debug_printf("D3D12: can't create 2D SRV from layer %d\n",
861 state->u.tex.first_layer);
863 desc.Texture2D.MostDetailedMip = state->u.tex.first_level;
864 desc.Texture2D.MipLevels = sampler_view->mip_levels;
865 desc.Texture2D.PlaneSlice = format_info.plane_slice;
866 desc.Texture2D.ResourceMinLODClamp = 0.0f;
868 case D3D12_SRV_DIMENSION_TEXTURE2DMS:
869 if (state->u.tex.first_layer > 0)
870 debug_printf("D3D12: can't create 2DMS SRV from layer %d\n",
871 state->u.tex.first_layer);
873 case D3D12_SRV_DIMENSION_TEXTURE2DARRAY:
874 desc.Texture2DArray.MostDetailedMip = state->u.tex.first_level;
875 desc.Texture2DArray.MipLevels = sampler_view->mip_levels;
876 desc.Texture2DArray.ResourceMinLODClamp = 0.0f;
877 desc.Texture2DArray.FirstArraySlice = state->u.tex.first_layer;
878 desc.Texture2DArray.PlaneSlice = format_info.plane_slice;
879 desc.Texture2DArray.ArraySize = array_size;
881 case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY:
882 desc.Texture2DMSArray.FirstArraySlice = state->u.tex.first_layer;
883 desc.Texture2DMSArray.ArraySize = array_size;
885 case D3D12_SRV_DIMENSION_TEXTURE3D:
886 if (state->u.tex.first_layer > 0)
887 debug_printf("D3D12: can't create 3D SRV from layer %d\n",
888 state->u.tex.first_layer);
890 desc.Texture3D.MostDetailedMip = state->u.tex.first_level;
891 desc.Texture3D.MipLevels = sampler_view->mip_levels;
892 desc.Texture3D.ResourceMinLODClamp = 0.0f;
894 case D3D12_SRV_DIMENSION_TEXTURECUBE:
895 if (state->u.tex.first_layer > 0)
896 debug_printf("D3D12: can't create CUBE SRV from layer %d\n",
897 state->u.tex.first_layer);
899 desc.TextureCube.MostDetailedMip = state->u.tex.first_level;
900 desc.TextureCube.MipLevels = sampler_view->mip_levels;
901 desc.TextureCube.ResourceMinLODClamp = 0.0f;
903 case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY:
904 assert(array_size % 6 == 0);
905 desc.TextureCubeArray.MostDetailedMip = state->u.tex.first_level;
906 desc.TextureCubeArray.MipLevels = sampler_view->mip_levels;
907 desc.TextureCubeArray.First2DArrayFace = state->u.tex.first_layer;
908 desc.TextureCubeArray.NumCubes = array_size / 6;
909 desc.TextureCubeArray.ResourceMinLODClamp = 0.0f;
911 case D3D12_SRV_DIMENSION_BUFFER:
912 desc.Buffer.StructureByteStride = 0;
913 desc.Buffer.FirstElement = offset / util_format_get_blocksize(state->format);
914 desc.Buffer.NumElements = texture->width0 / util_format_get_blocksize(state->format);
917 unreachable("Invalid SRV dimension");
920 screen->dev->CreateShaderResourceView(d3d12_res, &desc,
921 sampler_view->handle.cpu_handle);
924 static struct pipe_sampler_view *
925 d3d12_create_sampler_view(struct pipe_context *pctx,
926 struct pipe_resource *texture,
927 const struct pipe_sampler_view *state)
929 struct d3d12_screen *screen = d3d12_screen(pctx->screen);
930 struct d3d12_resource *res = d3d12_resource(texture);
931 struct d3d12_sampler_view *sampler_view = CALLOC_STRUCT(d3d12_sampler_view);
933 sampler_view->base = *state;
934 sampler_view->base.texture = NULL;
935 pipe_resource_reference(&sampler_view->base.texture, texture);
936 sampler_view->base.reference.count = 1;
937 sampler_view->base.context = pctx;
938 sampler_view->mip_levels = state->u.tex.last_level - state->u.tex.first_level + 1;
939 sampler_view->array_size = texture->array_size;
940 sampler_view->texture_generation_id = p_atomic_read(&res->generation_id);
942 struct d3d12_format_info format_info = d3d12_get_format_info(res->overall_format, state->format, state->target);
943 pipe_swizzle swizzle[4] = {
944 format_info.swizzle[sampler_view->base.swizzle_r],
945 format_info.swizzle[sampler_view->base.swizzle_g],
946 format_info.swizzle[sampler_view->base.swizzle_b],
947 format_info.swizzle[sampler_view->base.swizzle_a]
950 sampler_view->swizzle_override_r = swizzle[0];
951 sampler_view->swizzle_override_g = swizzle[1];
952 sampler_view->swizzle_override_b = swizzle[2];
953 sampler_view->swizzle_override_a = swizzle[3];
955 mtx_lock(&screen->descriptor_pool_mutex);
956 d3d12_descriptor_pool_alloc_handle(screen->view_pool, &sampler_view->handle);
957 mtx_unlock(&screen->descriptor_pool_mutex);
959 d3d12_init_sampler_view_descriptor(sampler_view);
961 return &sampler_view->base;
965 d3d12_increment_sampler_view_bind_count(struct pipe_context *ctx,
966 enum pipe_shader_type shader_type,
967 struct pipe_sampler_view *view) {
968 struct d3d12_resource *res = d3d12_resource(view->texture);
970 res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]++;
974 d3d12_decrement_sampler_view_bind_count(struct pipe_context *ctx,
975 enum pipe_shader_type shader_type,
976 struct pipe_sampler_view *view) {
977 struct d3d12_resource *res = d3d12_resource(view->texture);
979 assert(res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0);
980 res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]--;
985 d3d12_set_sampler_views(struct pipe_context *pctx,
986 enum pipe_shader_type shader_type,
989 unsigned unbind_num_trailing_slots,
991 struct pipe_sampler_view **views)
993 struct d3d12_context *ctx = d3d12_context(pctx);
994 unsigned shader_bit = (1 << shader_type);
995 ctx->has_int_samplers &= ~shader_bit;
997 for (unsigned i = 0; i < num_views; ++i) {
998 struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + i];
1000 d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view);
1002 struct pipe_sampler_view *new_view = views[i];
1004 d3d12_increment_sampler_view_bind_count(pctx, shader_type, new_view);
1006 if (take_ownership) {
1007 pipe_sampler_view_reference(&old_view, NULL);
1008 old_view = views[i];
1010 pipe_sampler_view_reference(&old_view, views[i]);
1014 dxil_wrap_sampler_state &wss = ctx->tex_wrap_states[shader_type][start_slot + i];
1015 dxil_texture_swizzle_state &swizzle_state = ctx->tex_swizzle_state[shader_type][i];
1016 if (util_format_is_pure_integer(views[i]->format)) {
1017 ctx->has_int_samplers |= shader_bit;
1018 wss.is_int_sampler = 1;
1019 wss.last_level = views[i]->texture->last_level;
1020 /* When we emulate a integer cube texture (array) by using a texture 2d Array
1021 * the coordinates are evaluated to always reside withing the acceptable range
1022 * because the 3d ray for picking the texel is always pointing at one cube face,
1023 * hence we can skip the boundary condition handling when the texture operations are
1024 * lowered to texel fetches later. */
1025 wss.skip_boundary_conditions = views[i]->target == PIPE_TEXTURE_CUBE ||
1026 views[i]->target == PIPE_TEXTURE_CUBE_ARRAY;
1028 wss.is_int_sampler = 0;
1030 /* We need the swizzle state for compare texture lowering, because it
1031 * encode the use of the shadow texture lookup result as either luminosity,
1032 * intensity, or alpha. and we need the swizzle state for applying the
1033 * boundary color correctly */
1034 struct d3d12_sampler_view *ss = d3d12_sampler_view(views[i]);
1035 swizzle_state.swizzle_r = ss->swizzle_override_r;
1036 swizzle_state.swizzle_g = ss->swizzle_override_g;
1037 swizzle_state.swizzle_b = ss->swizzle_override_b;
1038 swizzle_state.swizzle_a = ss->swizzle_override_a;
1042 for (unsigned i = 0; i < unbind_num_trailing_slots; i++) {
1043 struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + num_views + i];
1045 d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view);
1046 pipe_sampler_view_reference(&old_view, NULL);
1048 ctx->num_sampler_views[shader_type] = start_slot + num_views;
1049 ctx->shader_dirty[shader_type] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS;
1053 d3d12_destroy_sampler_view(struct pipe_context *pctx,
1054 struct pipe_sampler_view *pview)
1056 struct d3d12_sampler_view *view = d3d12_sampler_view(pview);
1057 d3d12_descriptor_handle_free(&view->handle);
1058 pipe_resource_reference(&view->base.texture, NULL);
1063 delete_shader(struct d3d12_context *ctx, enum pipe_shader_type stage,
1064 struct d3d12_shader_selector *shader)
1066 d3d12_gfx_pipeline_state_cache_invalidate_shader(ctx, stage, shader);
1068 /* Make sure the pipeline state no longer reference the deleted shader */
1069 struct d3d12_shader *iter = shader->first;
1071 if (ctx->gfx_pipeline_state.stages[stage] == iter) {
1072 ctx->gfx_pipeline_state.stages[stage] = NULL;
1075 iter = iter->next_variant;
1078 d3d12_shader_free(shader);
1082 bind_stage(struct d3d12_context *ctx, enum pipe_shader_type stage,
1083 struct d3d12_shader_selector *shader)
1085 assert(stage < D3D12_GFX_SHADER_STAGES);
1086 ctx->gfx_stages[stage] = shader;
1090 d3d12_create_vs_state(struct pipe_context *pctx,
1091 const struct pipe_shader_state *shader)
1093 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX, shader);
1097 d3d12_bind_vs_state(struct pipe_context *pctx,
1100 bind_stage(d3d12_context(pctx), PIPE_SHADER_VERTEX,
1101 (struct d3d12_shader_selector *) vss);
1105 d3d12_delete_vs_state(struct pipe_context *pctx,
1108 delete_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX,
1109 (struct d3d12_shader_selector *) vs);
1113 d3d12_create_fs_state(struct pipe_context *pctx,
1114 const struct pipe_shader_state *shader)
1116 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, shader);
1120 d3d12_bind_fs_state(struct pipe_context *pctx,
1123 bind_stage(d3d12_context(pctx), PIPE_SHADER_FRAGMENT,
1124 (struct d3d12_shader_selector *) fss);
1128 d3d12_delete_fs_state(struct pipe_context *pctx,
1131 delete_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT,
1132 (struct d3d12_shader_selector *) fs);
1136 d3d12_create_gs_state(struct pipe_context *pctx,
1137 const struct pipe_shader_state *shader)
1139 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, shader);
1143 d3d12_bind_gs_state(struct pipe_context *pctx, void *gss)
1145 bind_stage(d3d12_context(pctx), PIPE_SHADER_GEOMETRY,
1146 (struct d3d12_shader_selector *) gss);
1150 d3d12_delete_gs_state(struct pipe_context *pctx, void *gs)
1152 delete_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY,
1153 (struct d3d12_shader_selector *) gs);
1157 d3d12_create_tcs_state(struct pipe_context *pctx,
1158 const struct pipe_shader_state *shader)
1160 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL, shader);
1164 d3d12_bind_tcs_state(struct pipe_context *pctx, void *tcss)
1166 bind_stage(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL,
1167 (struct d3d12_shader_selector *)tcss);
1171 d3d12_delete_tcs_state(struct pipe_context *pctx, void *tcs)
1173 delete_shader(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL,
1174 (struct d3d12_shader_selector *)tcs);
1178 d3d12_create_tes_state(struct pipe_context *pctx,
1179 const struct pipe_shader_state *shader)
1181 return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL, shader);
1185 d3d12_bind_tes_state(struct pipe_context *pctx, void *tess)
1187 bind_stage(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL,
1188 (struct d3d12_shader_selector *)tess);
1192 d3d12_delete_tes_state(struct pipe_context *pctx, void *tes)
1194 delete_shader(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL,
1195 (struct d3d12_shader_selector *)tes);
1199 d3d12_create_compute_state(struct pipe_context *pctx,
1200 const struct pipe_compute_state *shader)
1202 return d3d12_create_compute_shader(d3d12_context(pctx), shader);
1206 d3d12_bind_compute_state(struct pipe_context *pctx, void *css)
1208 d3d12_context(pctx)->compute_state = (struct d3d12_shader_selector *)css;
1212 d3d12_delete_compute_state(struct pipe_context *pctx, void *cs)
1214 struct d3d12_context *ctx = d3d12_context(pctx);
1215 struct d3d12_shader_selector *shader = (struct d3d12_shader_selector *)cs;
1216 d3d12_compute_pipeline_state_cache_invalidate_shader(ctx, shader);
1218 /* Make sure the pipeline state no longer reference the deleted shader */
1219 struct d3d12_shader *iter = shader->first;
1221 if (ctx->compute_pipeline_state.stage == iter) {
1222 ctx->compute_pipeline_state.stage = NULL;
1225 iter = iter->next_variant;
1228 d3d12_shader_free(shader);
1232 d3d12_init_polygon_stipple(struct pipe_context *pctx)
1234 struct d3d12_context *ctx = d3d12_context(pctx);
1236 ctx->pstipple.texture = util_pstipple_create_stipple_texture(pctx, NULL);
1237 if (!ctx->pstipple.texture)
1240 ctx->pstipple.sampler_view = util_pstipple_create_sampler_view(pctx, ctx->pstipple.texture);
1241 if (!ctx->pstipple.sampler_view)
1244 ctx->pstipple.sampler_cso = (struct d3d12_sampler_state *)util_pstipple_create_sampler(pctx);
1245 if (!ctx->pstipple.sampler_cso)
1252 d3d12_set_polygon_stipple(struct pipe_context *pctx,
1253 const struct pipe_poly_stipple *ps)
1255 static bool initialized = false;
1256 static const uint32_t zero[32] = {0};
1257 static uint32_t undef[32] = {0};
1258 struct d3d12_context *ctx = d3d12_context(pctx);
1261 memset(undef, UINT32_MAX, sizeof(undef));
1263 if (!memcmp(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple)))
1266 memcpy(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple));
1267 ctx->pstipple.enabled = !!memcmp(ps->stipple, undef, sizeof(ps->stipple)) &&
1268 !!memcmp(ps->stipple, zero, sizeof(ps->stipple));
1269 if (ctx->pstipple.enabled)
1270 util_pstipple_update_stipple_texture(pctx, ctx->pstipple.texture, ps->stipple);
1274 d3d12_set_vertex_buffers(struct pipe_context *pctx,
1275 unsigned start_slot,
1276 unsigned num_buffers,
1277 unsigned unbind_num_trailing_slots,
1278 bool take_ownership,
1279 const struct pipe_vertex_buffer *buffers)
1281 struct d3d12_context *ctx = d3d12_context(pctx);
1282 util_set_vertex_buffers_count(ctx->vbs, &ctx->num_vbs,
1283 buffers, start_slot, num_buffers,
1284 unbind_num_trailing_slots,
1287 for (unsigned i = 0; i < ctx->num_vbs; ++i) {
1288 const struct pipe_vertex_buffer* buf = ctx->vbs + i;
1289 if (!buf->buffer.resource)
1291 struct d3d12_resource *res = d3d12_resource(buf->buffer.resource);
1292 ctx->vbvs[i].BufferLocation = d3d12_resource_gpu_virtual_address(res) + buf->buffer_offset;
1293 ctx->vbvs[i].StrideInBytes = buf->stride;
1294 ctx->vbvs[i].SizeInBytes = res->base.b.width0 - buf->buffer_offset;
1296 ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS;
1300 d3d12_set_viewport_states(struct pipe_context *pctx,
1301 unsigned start_slot,
1302 unsigned num_viewports,
1303 const struct pipe_viewport_state *state)
1305 struct d3d12_context *ctx = d3d12_context(pctx);
1307 for (unsigned i = 0; i < num_viewports; ++i) {
1308 if (state[i].scale[1] < 0) {
1310 ctx->viewports[start_slot + i].TopLeftY = state[i].translate[1] + state[i].scale[1];
1311 ctx->viewports[start_slot + i].Height = -state[i].scale[1] * 2;
1313 ctx->flip_y = -1.0f;
1314 ctx->viewports[start_slot + i].TopLeftY = state[i].translate[1] - state[i].scale[1];
1315 ctx->viewports[start_slot + i].Height = state[i].scale[1] * 2;
1317 ctx->viewports[start_slot + i].TopLeftX = state[i].translate[0] - state[i].scale[0];
1318 ctx->viewports[start_slot + i].Width = state[i].scale[0] * 2;
1320 float near_depth = state[i].translate[2];
1321 float far_depth = state[i].translate[2] + state[i].scale[2];
1323 /* When the rasterizer is configured for "full" depth clipping ([-1, 1])
1324 * the viewport that we get is set to cover the positive half of clip space.
1325 * E.g. a [0, 1] viewport from the GL API will come to the driver as [0.5, 1].
1326 * Since we halve clipping space from [-1, 1] to [0, 1], we need to double the
1327 * viewport, treating translate as the center instead of the near plane. When
1328 * the rasterizer is configured for "half" depth clipping ([0, 1]), the viewport
1329 * covers the entire clip range, so no fixup is needed.
1331 * Note: If halfz mode changes, both the rasterizer and viewport are dirtied,
1332 * and on the next draw we will get the rasterizer state first, and viewport
1333 * second, because ST_NEW_RASTERIZER comes before ST_NEW_VIEWPORT.
1335 if (ctx->gfx_pipeline_state.rast && !ctx->gfx_pipeline_state.rast->base.clip_halfz) {
1336 near_depth -= state[i].scale[2];
1339 bool reverse_depth_range = near_depth > far_depth;
1340 if (reverse_depth_range) {
1341 float tmp = near_depth;
1342 near_depth = far_depth;
1344 ctx->reverse_depth_range |= (1 << (start_slot + i));
1346 ctx->reverse_depth_range &= ~(1 << (start_slot + i));
1347 ctx->viewports[start_slot + i].MinDepth = near_depth;
1348 ctx->viewports[start_slot + i].MaxDepth = far_depth;
1349 ctx->viewport_states[start_slot + i] = state[i];
1351 ctx->num_viewports = start_slot + num_viewports;
1352 ctx->state_dirty |= D3D12_DIRTY_VIEWPORT;
1357 d3d12_set_scissor_states(struct pipe_context *pctx,
1358 unsigned start_slot, unsigned num_scissors,
1359 const struct pipe_scissor_state *states)
1361 struct d3d12_context *ctx = d3d12_context(pctx);
1363 for (unsigned i = 0; i < num_scissors; i++) {
1364 ctx->scissors[start_slot + i].left = states[i].minx;
1365 ctx->scissors[start_slot + i].top = states[i].miny;
1366 ctx->scissors[start_slot + i].right = states[i].maxx;
1367 ctx->scissors[start_slot + i].bottom = states[i].maxy;
1368 ctx->scissor_states[start_slot + i] = states[i];
1370 ctx->state_dirty |= D3D12_DIRTY_SCISSOR;
1374 d3d12_decrement_constant_buffer_bind_count(struct d3d12_context *ctx,
1375 enum pipe_shader_type shader,
1376 struct d3d12_resource *res) {
1377 assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0);
1378 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV]--;
1382 d3d12_increment_constant_buffer_bind_count(struct d3d12_context *ctx,
1383 enum pipe_shader_type shader,
1384 struct d3d12_resource *res) {
1385 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV]++;
1389 d3d12_set_constant_buffer(struct pipe_context *pctx,
1390 enum pipe_shader_type shader, uint index,
1391 bool take_ownership,
1392 const struct pipe_constant_buffer *buf)
1394 struct d3d12_context *ctx = d3d12_context(pctx);
1395 struct d3d12_resource *old_buf = d3d12_resource(ctx->cbufs[shader][index].buffer);
1397 d3d12_decrement_constant_buffer_bind_count(ctx, shader, old_buf);
1400 unsigned offset = buf->buffer_offset;
1401 if (buf->user_buffer) {
1402 u_upload_data(pctx->const_uploader, 0, buf->buffer_size,
1403 D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT,
1404 buf->user_buffer, &offset, &ctx->cbufs[shader][index].buffer);
1405 d3d12_increment_constant_buffer_bind_count(ctx, shader,
1406 d3d12_resource(ctx->cbufs[shader][index].buffer));
1408 struct pipe_resource *buffer = buf->buffer;
1410 d3d12_increment_constant_buffer_bind_count(ctx, shader, d3d12_resource(buffer));
1412 if (take_ownership) {
1413 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL);
1414 ctx->cbufs[shader][index].buffer = buffer;
1416 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, buffer);
1420 ctx->cbufs[shader][index].buffer_offset = offset;
1421 ctx->cbufs[shader][index].buffer_size = buf->buffer_size;
1422 ctx->cbufs[shader][index].user_buffer = NULL;
1425 pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL);
1426 ctx->cbufs[shader][index].buffer_offset = 0;
1427 ctx->cbufs[shader][index].buffer_size = 0;
1428 ctx->cbufs[shader][index].user_buffer = NULL;
1430 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_CONSTBUF;
1434 d3d12_set_framebuffer_state(struct pipe_context *pctx,
1435 const struct pipe_framebuffer_state *state)
1437 struct d3d12_context *ctx = d3d12_context(pctx);
1440 bool prev_cbufs_or_zsbuf = ctx->fb.nr_cbufs || ctx->fb.zsbuf;
1441 util_copy_framebuffer_state(&d3d12_context(pctx)->fb, state);
1442 bool new_cbufs_or_zsbuf = ctx->fb.nr_cbufs || ctx->fb.zsbuf;
1444 ctx->gfx_pipeline_state.num_cbufs = state->nr_cbufs;
1445 ctx->gfx_pipeline_state.has_float_rtv = false;
1446 for (int i = 0; i < state->nr_cbufs; ++i) {
1447 if (state->cbufs[i]) {
1448 if (util_format_is_float(state->cbufs[i]->format))
1449 ctx->gfx_pipeline_state.has_float_rtv = true;
1450 ctx->gfx_pipeline_state.rtv_formats[i] = d3d12_get_format(state->cbufs[i]->format);
1451 samples = MAX2(samples, (int)state->cbufs[i]->texture->nr_samples);
1453 ctx->gfx_pipeline_state.rtv_formats[i] = DXGI_FORMAT_UNKNOWN;
1458 ctx->gfx_pipeline_state.dsv_format = d3d12_get_resource_rt_format(state->zsbuf->format);
1459 samples = MAX2(samples, (int)ctx->fb.zsbuf->texture->nr_samples);
1461 ctx->gfx_pipeline_state.dsv_format = DXGI_FORMAT_UNKNOWN;
1464 samples = state->samples;
1466 ctx->gfx_pipeline_state.samples = MAX2(samples, 1);
1468 ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER;
1469 if (!prev_cbufs_or_zsbuf || !new_cbufs_or_zsbuf)
1470 ctx->state_dirty |= D3D12_DIRTY_VIEWPORT;
1474 d3d12_set_blend_color(struct pipe_context *pctx,
1475 const struct pipe_blend_color *color)
1477 struct d3d12_context *ctx = d3d12_context(pctx);
1478 memcpy(ctx->blend_factor, color->color, sizeof(float) * 4);
1479 ctx->state_dirty |= D3D12_DIRTY_BLEND_COLOR;
1483 d3d12_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
1485 struct d3d12_context *ctx = d3d12_context(pctx);
1486 ctx->gfx_pipeline_state.sample_mask = sample_mask;
1487 ctx->state_dirty |= D3D12_DIRTY_SAMPLE_MASK;
1491 d3d12_set_stencil_ref(struct pipe_context *pctx,
1492 const struct pipe_stencil_ref ref)
1494 struct d3d12_context *ctx = d3d12_context(pctx);
1495 if ((ref.ref_value[0] != ref.ref_value[1]) &&
1496 (d3d12_debug & D3D12_DEBUG_VERBOSE))
1497 debug_printf("D3D12: Different values for front and back stencil reference are not supported\n");
1498 ctx->stencil_ref = ref;
1499 ctx->state_dirty |= D3D12_DIRTY_STENCIL_REF;
1503 d3d12_set_clip_state(struct pipe_context *pctx,
1504 const struct pipe_clip_state *pcs)
1508 static struct pipe_stream_output_target *
1509 d3d12_create_stream_output_target(struct pipe_context *pctx,
1510 struct pipe_resource *pres,
1511 unsigned buffer_offset,
1512 unsigned buffer_size)
1514 struct d3d12_resource *res = d3d12_resource(pres);
1515 struct d3d12_stream_output_target *cso = CALLOC_STRUCT(d3d12_stream_output_target);
1520 pipe_reference_init(&cso->base.reference, 1);
1521 pipe_resource_reference(&cso->base.buffer, pres);
1522 cso->base.buffer_offset = buffer_offset;
1523 cso->base.buffer_size = buffer_size;
1524 cso->base.context = pctx;
1526 if (res->bo && res->bo->buffer && d3d12_buffer(res->bo->buffer)->map)
1527 util_range_add(pres, &res->valid_buffer_range, buffer_offset,
1528 buffer_offset + buffer_size);
1534 d3d12_stream_output_target_destroy(struct pipe_context *ctx,
1535 struct pipe_stream_output_target *state)
1537 pipe_resource_reference(&state->buffer, NULL);
1543 fill_stream_output_buffer_view(D3D12_STREAM_OUTPUT_BUFFER_VIEW *view,
1544 struct d3d12_stream_output_target *target)
1546 struct d3d12_resource *res = d3d12_resource(target->base.buffer);
1547 struct d3d12_resource *fill_res = d3d12_resource(target->fill_buffer);
1549 view->SizeInBytes = target->base.buffer_size;
1550 view->BufferLocation = d3d12_resource_gpu_virtual_address(res) + target->base.buffer_offset;
1551 view->BufferFilledSizeLocation = d3d12_resource_gpu_virtual_address(fill_res) + target->fill_buffer_offset;
1555 update_so_fill_buffer_count(struct d3d12_context *ctx,
1556 struct pipe_resource *fill_buffer,
1557 unsigned fill_buffer_offset,
1560 struct pipe_transfer *transfer = NULL;
1561 uint32_t *ptr = (uint32_t *)pipe_buffer_map_range(&ctx->base, fill_buffer,
1562 fill_buffer_offset, sizeof(uint32_t), PIPE_MAP_WRITE, &transfer);
1564 pipe_buffer_unmap(&ctx->base, transfer);
1568 d3d12_set_stream_output_targets(struct pipe_context *pctx,
1569 unsigned num_targets,
1570 struct pipe_stream_output_target **targets,
1571 const unsigned *offsets)
1573 struct d3d12_context *ctx = d3d12_context(pctx);
1575 assert(num_targets <= ARRAY_SIZE(ctx->so_targets));
1577 d3d12_disable_fake_so_buffers(ctx);
1579 for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; i++) {
1580 struct d3d12_stream_output_target *target =
1581 i < num_targets ? (struct d3d12_stream_output_target *)targets[i] : NULL;
1584 /* Sub-allocate a new fill buffer each time to avoid GPU/CPU synchronization */
1585 if (offsets[i] != ~0u) {
1586 u_suballocator_alloc(&ctx->so_allocator, sizeof(uint32_t) * 5, 16,
1587 &target->fill_buffer_offset, &target->fill_buffer);
1588 update_so_fill_buffer_count(ctx, target->fill_buffer, target->fill_buffer_offset, offsets[i]);
1590 fill_stream_output_buffer_view(&ctx->so_buffer_views[i], target);
1591 pipe_so_target_reference(&ctx->so_targets[i], targets[i]);
1593 ctx->so_buffer_views[i].BufferLocation = 0;
1594 ctx->so_buffer_views[i].BufferFilledSizeLocation = 0;
1595 ctx->so_buffer_views[i].SizeInBytes = 0;
1596 pipe_so_target_reference(&ctx->so_targets[i], NULL);
1600 ctx->gfx_pipeline_state.num_so_targets = num_targets;
1601 ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
1605 d3d12_decrement_ssbo_bind_count(struct d3d12_context *ctx,
1606 enum pipe_shader_type shader,
1607 struct d3d12_resource *res) {
1608 assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO] > 0);
1609 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO]--;
1613 d3d12_increment_ssbo_bind_count(struct d3d12_context *ctx,
1614 enum pipe_shader_type shader,
1615 struct d3d12_resource *res) {
1616 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO]++;
1620 d3d12_set_shader_buffers(struct pipe_context *pctx,
1621 enum pipe_shader_type shader,
1622 unsigned start_slot, unsigned count,
1623 const struct pipe_shader_buffer *buffers,
1624 unsigned writable_bitmask)
1626 struct d3d12_context *ctx = d3d12_context(pctx);
1627 for (unsigned i = 0; i < count; ++i) {
1628 struct pipe_shader_buffer *slot = &ctx->ssbo_views[shader][i + start_slot];
1630 d3d12_decrement_ssbo_bind_count(ctx, shader, d3d12_resource(slot->buffer));
1631 pipe_resource_reference(&slot->buffer, NULL);
1634 if (buffers && buffers[i].buffer) {
1635 pipe_resource_reference(&slot->buffer, buffers[i].buffer);
1636 slot->buffer_offset = buffers[i].buffer_offset;
1637 slot->buffer_size = buffers[i].buffer_size;
1638 d3d12_increment_ssbo_bind_count(ctx, shader, d3d12_resource(buffers[i].buffer));
1640 memset(slot, 0, sizeof(*slot));
1644 ctx->num_ssbo_views[shader] = MAX2(ctx->num_ssbo_views[shader], count + start_slot);
1646 ctx->num_ssbo_views[shader] = 0;
1647 for (int i = start_slot + count - 1; i >= (int)start_slot; --i) {
1648 if (ctx->ssbo_views[shader][i].buffer) {
1649 ctx->num_ssbo_views[shader] = i;
1654 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SSBO;
1658 d3d12_decrement_image_bind_count(struct d3d12_context *ctx,
1659 enum pipe_shader_type shader,
1660 struct d3d12_resource *res) {
1661 assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0);
1662 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE]--;
1666 d3d12_increment_image_bind_count(struct d3d12_context *ctx,
1667 enum pipe_shader_type shader,
1668 struct d3d12_resource *res) {
1669 res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE]++;
1673 is_valid_uav_cast(enum pipe_format resource_format, enum pipe_format view_format)
1675 if (view_format != PIPE_FORMAT_R32_UINT &&
1676 view_format != PIPE_FORMAT_R32_SINT &&
1677 view_format != PIPE_FORMAT_R32_FLOAT)
1679 switch (d3d12_get_typeless_format(resource_format)) {
1680 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
1681 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
1682 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
1683 case DXGI_FORMAT_R16G16_TYPELESS:
1684 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
1691 static enum pipe_format
1692 get_shader_image_emulation_format(enum pipe_format resource_format)
1694 #define CASE(f) case DXGI_FORMAT_##f##_TYPELESS: return PIPE_FORMAT_##f##_UINT
1695 switch (d3d12_get_typeless_format(resource_format)) {
1706 case DXGI_FORMAT_R11G11B10_FLOAT:
1707 return PIPE_FORMAT_R11G11B10_FLOAT;
1709 unreachable("Unexpected shader image resource format");
1714 d3d12_set_shader_images(struct pipe_context *pctx,
1715 enum pipe_shader_type shader,
1716 unsigned start_slot, unsigned count,
1717 unsigned unbind_num_trailing_slots,
1718 const struct pipe_image_view *images)
1720 struct d3d12_context *ctx = d3d12_context(pctx);
1721 for (unsigned i = 0; i < count + unbind_num_trailing_slots; ++i) {
1722 struct pipe_image_view *slot = &ctx->image_views[shader][i + start_slot];
1723 if (slot->resource) {
1724 d3d12_decrement_image_bind_count(ctx, shader, d3d12_resource(slot->resource));
1725 pipe_resource_reference(&slot->resource, NULL);
1728 ctx->image_view_emulation_formats[shader][i] = PIPE_FORMAT_NONE;
1729 if (i < count && images && images[i].resource) {
1730 pipe_resource_reference(&slot->resource, images[i].resource);
1732 d3d12_increment_image_bind_count(ctx, shader, d3d12_resource(images[i].resource));
1734 if (images[i].resource->target != PIPE_BUFFER &&
1735 !is_valid_uav_cast(images[i].resource->format, images[i].format) &&
1736 d3d12_get_typeless_format(images[i].format) !=
1737 d3d12_get_typeless_format(images[i].resource->format)) {
1738 /* Can't use D3D casting, have to use shader lowering instead */
1739 ctx->image_view_emulation_formats[shader][i] =
1740 get_shader_image_emulation_format(images[i].resource->format);
1743 memset(slot, 0, sizeof(*slot));
1747 ctx->num_image_views[shader] = MAX2(ctx->num_image_views[shader], count + start_slot);
1749 ctx->num_image_views[shader] = 0;
1750 for (int i = start_slot + count - 1; i >= (int)start_slot; --i) {
1751 if (ctx->image_views[shader][i].resource) {
1752 ctx->num_image_views[shader] = i;
1757 ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_IMAGE;
1761 d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resource *res) {
1762 // For each shader type, if the resource is currently bound as CBV, SRV, or UAV
1763 // set the context shader_dirty bit.
1764 for (uint i = 0; i < PIPE_SHADER_TYPES; ++i) {
1765 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0) {
1766 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF;
1769 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0) {
1770 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS;
1773 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SSBO] > 0) {
1774 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO;
1777 if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0) {
1778 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE;
1784 d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor)
1786 if (ctx->fake_so_buffer_factor == factor)
1789 d3d12_disable_fake_so_buffers(ctx);
1791 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) {
1792 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i];
1793 struct d3d12_stream_output_target *fake_target;
1795 fake_target = CALLOC_STRUCT(d3d12_stream_output_target);
1798 pipe_reference_init(&fake_target->base.reference, 1);
1799 fake_target->base.context = &ctx->base;
1801 d3d12_resource_wait_idle(ctx, d3d12_resource(target->base.buffer), false);
1803 /* Check if another target is using the same buffer */
1804 for (unsigned j = 0; j < i; ++j) {
1805 if (ctx->so_targets[j] && ctx->so_targets[j]->buffer == target->base.buffer) {
1806 struct d3d12_stream_output_target *prev_target =
1807 (struct d3d12_stream_output_target *)ctx->fake_so_targets[j];
1808 pipe_resource_reference(&fake_target->base.buffer, prev_target->base.buffer);
1809 pipe_resource_reference(&fake_target->fill_buffer, prev_target->fill_buffer);
1810 fake_target->fill_buffer_offset = prev_target->fill_buffer_offset;
1815 /* Create new SO buffer 6x (2 triangles instead of 1 point) the original size if not */
1816 if (!fake_target->base.buffer) {
1817 fake_target->base.buffer = pipe_buffer_create(ctx->base.screen,
1818 PIPE_BIND_STREAM_OUTPUT,
1820 target->base.buffer->width0 * factor);
1821 u_suballocator_alloc(&ctx->so_allocator, sizeof(uint32_t) * 5, 256,
1822 &fake_target->fill_buffer_offset, &fake_target->fill_buffer);
1823 update_so_fill_buffer_count(ctx, fake_target->fill_buffer, fake_target->fill_buffer_offset, 0);
1826 fake_target->base.buffer_offset = target->base.buffer_offset * factor;
1827 /* TODO: This will mess with SO statistics/overflow queries, but we're already missing things there */
1828 fake_target->base.buffer_size = target->base.buffer_size * factor;
1829 ctx->fake_so_targets[i] = &fake_target->base;
1830 fill_stream_output_buffer_view(&ctx->fake_so_buffer_views[i], fake_target);
1833 ctx->fake_so_buffer_factor = factor;
1834 ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
1840 d3d12_disable_fake_so_buffers(struct d3d12_context *ctx)
1842 if (ctx->fake_so_buffer_factor == 0)
1845 d3d12_flush_cmdlist_and_wait(ctx);
1847 bool cs_state_saved = false;
1848 d3d12_compute_transform_save_restore save;
1850 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) {
1851 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i];
1852 struct d3d12_stream_output_target *fake_target = (struct d3d12_stream_output_target *)ctx->fake_so_targets[i];
1854 if (fake_target == NULL)
1857 if (!cs_state_saved) {
1858 cs_state_saved = true;
1859 d3d12_save_compute_transform_state(ctx, &save);
1862 d3d12_compute_transform_key key;
1863 memset(&key, 0, sizeof(key));
1864 key.type = d3d12_compute_transform_type::fake_so_buffer_vertex_count;
1865 ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key));
1867 ctx->transform_state_vars[0] = ctx->gfx_pipeline_state.so_info.stride[i];
1868 ctx->transform_state_vars[1] = ctx->fake_so_buffer_factor;
1870 pipe_shader_buffer new_cs_ssbos[3];
1871 new_cs_ssbos[0].buffer = fake_target->fill_buffer;
1872 new_cs_ssbos[0].buffer_offset = fake_target->fill_buffer_offset;
1873 new_cs_ssbos[0].buffer_size = fake_target->fill_buffer->width0 - fake_target->fill_buffer_offset;
1875 new_cs_ssbos[1].buffer = target->fill_buffer;
1876 new_cs_ssbos[1].buffer_offset = target->fill_buffer_offset;
1877 new_cs_ssbos[1].buffer_size = target->fill_buffer->width0 - target->fill_buffer_offset;
1878 ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 2, new_cs_ssbos, 2);
1880 pipe_grid_info grid = {};
1881 grid.block[0] = grid.block[1] = grid.block[2] = 1;
1882 grid.grid[0] = grid.grid[1] = grid.grid[2] = 1;
1883 ctx->base.launch_grid(&ctx->base, &grid);
1885 key.type = d3d12_compute_transform_type::fake_so_buffer_copy_back;
1886 key.fake_so_buffer_copy_back.stride = ctx->gfx_pipeline_state.so_info.stride[i];
1887 for (unsigned j = 0; j < ctx->gfx_pipeline_state.so_info.num_outputs; ++j) {
1888 auto& output = ctx->gfx_pipeline_state.so_info.output[j];
1889 if (output.output_buffer != i)
1892 if (key.fake_so_buffer_copy_back.num_ranges > 0) {
1893 auto& last_range = key.fake_so_buffer_copy_back.ranges[key.fake_so_buffer_copy_back.num_ranges - 1];
1894 if (output.dst_offset * 4 == last_range.offset + last_range.size) {
1895 last_range.size += output.num_components * 4;
1900 auto& new_range = key.fake_so_buffer_copy_back.ranges[key.fake_so_buffer_copy_back.num_ranges++];
1901 new_range.offset = output.dst_offset * 4;
1902 new_range.size = output.num_components * 4;
1904 ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key));
1906 ctx->transform_state_vars[0] = ctx->fake_so_buffer_factor;
1908 new_cs_ssbos[0].buffer = target->base.buffer;
1909 new_cs_ssbos[0].buffer_offset = target->base.buffer_offset;
1910 new_cs_ssbos[0].buffer_size = target->base.buffer_size;
1911 new_cs_ssbos[1].buffer = fake_target->base.buffer;
1912 new_cs_ssbos[1].buffer_offset = fake_target->base.buffer_offset;
1913 new_cs_ssbos[1].buffer_size = fake_target->base.buffer_size;
1914 ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 2, new_cs_ssbos, 2);
1916 pipe_constant_buffer cbuf = {};
1917 cbuf.buffer = fake_target->fill_buffer;
1918 cbuf.buffer_offset = fake_target->fill_buffer_offset;
1919 cbuf.buffer_size = fake_target->fill_buffer->width0 - cbuf.buffer_offset;
1920 ctx->base.set_constant_buffer(&ctx->base, PIPE_SHADER_COMPUTE, 1, false, &cbuf);
1922 grid.indirect = fake_target->fill_buffer;
1923 grid.indirect_offset = fake_target->fill_buffer_offset + 4;
1924 ctx->base.launch_grid(&ctx->base, &grid);
1926 pipe_so_target_reference(&ctx->fake_so_targets[i], NULL);
1927 ctx->fake_so_buffer_views[i].SizeInBytes = 0;
1929 /* Make sure the buffer is not copied twice */
1930 for (unsigned j = i + 1; j <= ctx->gfx_pipeline_state.num_so_targets; ++j) {
1931 if (ctx->so_targets[j] && ctx->so_targets[j]->buffer == target->base.buffer)
1932 pipe_so_target_reference(&ctx->fake_so_targets[j], NULL);
1936 ctx->fake_so_buffer_factor = 0;
1937 ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
1940 d3d12_restore_compute_transform_state(ctx, &save);
1946 d3d12_flush_cmdlist(struct d3d12_context *ctx)
1948 d3d12_end_batch(ctx, d3d12_current_batch(ctx));
1950 ctx->current_batch_idx++;
1951 if (ctx->current_batch_idx == ARRAY_SIZE(ctx->batches))
1952 ctx->current_batch_idx = 0;
1954 d3d12_start_batch(ctx, d3d12_current_batch(ctx));
1958 d3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx)
1960 struct d3d12_batch *batch = d3d12_current_batch(ctx);
1962 d3d12_foreach_submitted_batch(ctx, old_batch)
1963 d3d12_reset_batch(ctx, old_batch, PIPE_TIMEOUT_INFINITE);
1964 d3d12_flush_cmdlist(ctx);
1965 d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE);
1969 d3d12_clear_render_target(struct pipe_context *pctx,
1970 struct pipe_surface *psurf,
1971 const union pipe_color_union *color,
1972 unsigned dstx, unsigned dsty,
1973 unsigned width, unsigned height,
1974 bool render_condition_enabled)
1976 struct d3d12_context *ctx = d3d12_context(pctx);
1977 struct d3d12_surface *surf = d3d12_surface(psurf);
1979 if (!render_condition_enabled && ctx->current_predication)
1980 ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
1982 struct d3d12_resource *res = d3d12_resource(psurf->texture);
1983 d3d12_transition_resource_state(ctx, res,
1984 D3D12_RESOURCE_STATE_RENDER_TARGET,
1985 D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
1986 d3d12_apply_resource_states(ctx, false);
1988 enum pipe_format format = psurf->texture->format;
1989 float clear_color[4];
1991 if (util_format_is_pure_uint(format)) {
1992 for (int c = 0; c < 4; ++c)
1993 clear_color[c] = color->ui[c];
1994 } else if (util_format_is_pure_sint(format)) {
1995 for (int c = 0; c < 4; ++c)
1996 clear_color[c] = color->i[c];
1998 for (int c = 0; c < 4; ++c)
1999 clear_color[c] = color->f[c];
2002 if (!(util_format_colormask(util_format_description(psurf->texture->format)) &
2004 clear_color[3] = 1.0f;
2006 D3D12_RECT rect = { (int)dstx, (int)dsty,
2007 (int)dstx + (int)width,
2008 (int)dsty + (int)height };
2009 ctx->cmdlist->ClearRenderTargetView(surf->desc_handle.cpu_handle,
2010 clear_color, 1, &rect);
2012 d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf);
2014 if (!render_condition_enabled && ctx->current_predication) {
2015 d3d12_enable_predication(ctx);
2020 d3d12_clear_depth_stencil(struct pipe_context *pctx,
2021 struct pipe_surface *psurf,
2022 unsigned clear_flags,
2025 unsigned dstx, unsigned dsty,
2026 unsigned width, unsigned height,
2027 bool render_condition_enabled)
2029 struct d3d12_context *ctx = d3d12_context(pctx);
2030 struct d3d12_surface *surf = d3d12_surface(psurf);
2032 if (!render_condition_enabled && ctx->current_predication)
2033 ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
2035 D3D12_CLEAR_FLAGS flags = (D3D12_CLEAR_FLAGS)0;
2036 if (clear_flags & PIPE_CLEAR_DEPTH)
2037 flags |= D3D12_CLEAR_FLAG_DEPTH;
2038 if (clear_flags & PIPE_CLEAR_STENCIL)
2039 flags |= D3D12_CLEAR_FLAG_STENCIL;
2041 struct d3d12_resource *res = d3d12_resource(ctx->fb.zsbuf->texture);
2042 d3d12_transition_resource_state(ctx, res,
2043 D3D12_RESOURCE_STATE_DEPTH_WRITE,
2044 D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
2045 d3d12_apply_resource_states(ctx, false);
2047 D3D12_RECT rect = { (int)dstx, (int)dsty,
2048 (int)dstx + (int)width,
2049 (int)dsty + (int)height };
2050 ctx->cmdlist->ClearDepthStencilView(surf->desc_handle.cpu_handle, flags,
2051 depth, stencil, 1, &rect);
2053 d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf);
2055 if (!render_condition_enabled && ctx->current_predication) {
2056 d3d12_enable_predication(ctx);
2061 d3d12_clear(struct pipe_context *pctx,
2063 const struct pipe_scissor_state *scissor_state,
2064 const union pipe_color_union *color,
2065 double depth, unsigned stencil)
2067 struct d3d12_context *ctx = d3d12_context(pctx);
2069 if (buffers & PIPE_CLEAR_COLOR) {
2070 for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
2071 if (buffers & (PIPE_CLEAR_COLOR0 << i)) {
2072 struct pipe_surface *psurf = ctx->fb.cbufs[i];
2073 d3d12_clear_render_target(pctx, psurf, color,
2074 0, 0, psurf->width, psurf->height,
2080 if (buffers & PIPE_CLEAR_DEPTHSTENCIL && ctx->fb.zsbuf) {
2081 struct pipe_surface *psurf = ctx->fb.zsbuf;
2082 d3d12_clear_depth_stencil(pctx, psurf,
2083 buffers & PIPE_CLEAR_DEPTHSTENCIL,
2085 0, 0, psurf->width, psurf->height,
2091 d3d12_flush(struct pipe_context *pipe,
2092 struct pipe_fence_handle **fence,
2095 struct d3d12_context *ctx = d3d12_context(pipe);
2096 struct d3d12_batch *batch = d3d12_current_batch(ctx);
2098 d3d12_flush_cmdlist(ctx);
2101 d3d12_fence_reference((struct d3d12_fence **)fence, batch->fence);
2105 d3d12_flush_resource(struct pipe_context *pctx,
2106 struct pipe_resource *pres)
2108 struct d3d12_context *ctx = d3d12_context(pctx);
2109 struct d3d12_resource *res = d3d12_resource(pres);
2111 d3d12_transition_resource_state(ctx, res,
2112 D3D12_RESOURCE_STATE_COMMON,
2113 D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
2114 d3d12_apply_resource_states(ctx, false);
2118 d3d12_signal(struct pipe_context *pipe,
2119 struct pipe_fence_handle *pfence)
2121 struct d3d12_screen *screen = d3d12_screen(pipe->screen);
2122 struct d3d12_fence *fence = d3d12_fence(pfence);
2123 d3d12_flush_cmdlist(d3d12_context(pipe));
2124 screen->cmdqueue->Signal(fence->cmdqueue_fence, fence->value);
2128 d3d12_wait(struct pipe_context *pipe, struct pipe_fence_handle *pfence)
2130 struct d3d12_screen *screen = d3d12_screen(pipe->screen);
2131 struct d3d12_fence *fence = d3d12_fence(pfence);
2132 d3d12_flush_cmdlist(d3d12_context(pipe));
2133 screen->cmdqueue->Wait(fence->cmdqueue_fence, fence->value);
2137 d3d12_init_null_sampler(struct d3d12_context *ctx)
2139 struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
2141 d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ctx->null_sampler);
2143 D3D12_SAMPLER_DESC desc;
2144 desc.Filter = D3D12_FILTER_ANISOTROPIC;
2145 desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
2146 desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
2147 desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
2148 desc.MipLODBias = 0.0f;
2149 desc.MaxAnisotropy = 0;
2150 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
2153 memset(desc.BorderColor, 0, sizeof(desc.BorderColor));
2154 screen->dev->CreateSampler(&desc, ctx->null_sampler.cpu_handle);
2158 d3d12_get_timestamp(struct pipe_context *pctx)
2160 struct d3d12_context *ctx = d3d12_context(pctx);
2162 if (!ctx->timestamp_query)
2163 ctx->timestamp_query = pctx->create_query(pctx, PIPE_QUERY_TIMESTAMP, 0);
2165 pipe_query_result result;
2166 pctx->end_query(pctx, ctx->timestamp_query);
2167 pctx->get_query_result(pctx, ctx->timestamp_query, true, &result);
2172 d3d12_rebind_buffer(struct d3d12_context *ctx, struct d3d12_resource *res)
2174 if (res->base.b.bind & PIPE_BIND_VERTEX_BUFFER) {
2175 for (unsigned i = 0; i < ctx->num_vbs; ++i) {
2176 struct pipe_vertex_buffer *buf = &ctx->vbs[i];
2178 if (!buf->is_user_buffer && &res->base.b == buf->buffer.resource) {
2179 ctx->vbvs[i].BufferLocation = d3d12_resource_gpu_virtual_address(res) + buf->buffer_offset;
2180 ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS;
2185 if (res->base.b.bind & PIPE_BIND_STREAM_OUTPUT) {
2186 for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) {
2187 struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i];
2188 assert(!target || target->fill_buffer != &res->base.b);
2189 if (target && target->base.buffer == &res->base.b) {
2190 fill_stream_output_buffer_view(&ctx->so_buffer_views[i], target);
2191 ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
2194 assert(!ctx->fake_so_targets[i] || ctx->fake_so_targets[i]->buffer != &res->base.b);
2198 d3d12_invalidate_context_bindings(ctx, res);
2202 d3d12_replace_buffer_storage(struct pipe_context *pctx,
2203 struct pipe_resource *pdst,
2204 struct pipe_resource *psrc,
2205 unsigned minimum_num_rebinds,
2206 uint32_t rebind_mask,
2207 uint32_t delete_buffer_id)
2209 struct d3d12_context *ctx = d3d12_context(pctx);
2210 struct d3d12_resource *dst = d3d12_resource(pdst);
2211 struct d3d12_resource *src = d3d12_resource(psrc);
2213 struct d3d12_bo *old_bo = dst->bo;
2214 d3d12_bo_reference(src->bo);
2216 p_atomic_inc(&dst->generation_id);
2217 d3d12_rebind_buffer(ctx, dst);
2218 d3d12_bo_unreference(old_bo);
2222 d3d12_memory_barrier(struct pipe_context *pctx, unsigned flags)
2224 struct d3d12_context *ctx = d3d12_context(pctx);
2225 if (flags & PIPE_BARRIER_VERTEX_BUFFER)
2226 ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS;
2227 if (flags & PIPE_BARRIER_INDEX_BUFFER)
2228 ctx->state_dirty |= D3D12_DIRTY_INDEX_BUFFER;
2229 if (flags & PIPE_BARRIER_FRAMEBUFFER)
2230 ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER;
2231 if (flags & PIPE_BARRIER_STREAMOUT_BUFFER)
2232 ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
2235 * PIPE_BARRIER_INDIRECT_BUFFER
2238 for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
2239 if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
2240 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF;
2241 if (flags & PIPE_BARRIER_TEXTURE)
2242 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS;
2243 if (flags & PIPE_BARRIER_SHADER_BUFFER)
2244 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO;
2245 if (flags & PIPE_BARRIER_IMAGE)
2246 ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE;
2249 /* Indicate that UAVs shouldn't override transitions. Ignore barriers that are only
2250 * for UAVs or other fixed-function state that doesn't need a draw to resolve.
2252 const unsigned ignored_barrier_flags =
2253 PIPE_BARRIER_IMAGE |
2254 PIPE_BARRIER_SHADER_BUFFER |
2255 PIPE_BARRIER_UPDATE |
2256 PIPE_BARRIER_MAPPED_BUFFER |
2257 PIPE_BARRIER_QUERY_BUFFER;
2258 d3d12_current_batch(ctx)->pending_memory_barrier = (flags & ~ignored_barrier_flags) != 0;
2260 if (flags & (PIPE_BARRIER_IMAGE | PIPE_BARRIER_SHADER_BUFFER)) {
2261 D3D12_RESOURCE_BARRIER uavBarrier;
2262 uavBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
2263 uavBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
2264 uavBarrier.UAV.pResource = nullptr;
2265 ctx->cmdlist->ResourceBarrier(1, &uavBarrier);
2270 d3d12_get_sample_position(struct pipe_context *pctx, unsigned sample_count, unsigned sample_index,
2273 /* Sample patterns transcribed from
2274 * https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels
2276 static const int sample_pattern_1sample[2] = { 0, 0 };
2277 static const int sample_pattern_2samples[2][2] = {
2281 static const int sample_pattern_4samples[4][2] = {
2287 static const int sample_pattern_8samples[8][2] = {
2297 static const int sample_pattern_16samples[16][2] = {
2316 switch (sample_count) {
2319 samples = sample_pattern_1sample;
2322 samples = sample_pattern_2samples[sample_index];
2325 samples = sample_pattern_4samples[sample_index];
2328 samples = sample_pattern_8samples[sample_index];
2331 samples = sample_pattern_16samples[sample_index];
2335 /* GL coords go from 0 -> 1, D3D from -0.5 -> 0.5 */
2336 for (unsigned i = 0; i < 2; ++i)
2337 positions[i] = (float)(samples[i] + 8) / 16.0f;
2341 d3d12_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices)
2343 struct d3d12_context *ctx = d3d12_context(pctx);
2344 ctx->patch_vertices = patch_vertices;
2345 ctx->cmdlist_dirty |= D3D12_DIRTY_PRIM_MODE;
2349 d3d12_set_tess_state(struct pipe_context *pctx,
2350 const float default_outer_level[4],
2351 const float default_inner_level[2])
2353 struct d3d12_context *ctx = d3d12_context(pctx);
2354 memcpy(ctx->default_outer_tess_factor, default_outer_level, sizeof(ctx->default_outer_tess_factor));
2355 memcpy(ctx->default_inner_tess_factor, default_inner_level, sizeof(ctx->default_inner_tess_factor));
2358 static enum pipe_reset_status
2359 d3d12_get_reset_status(struct pipe_context *pctx)
2361 struct d3d12_screen *screen = d3d12_screen(pctx->screen);
2362 HRESULT hr = screen->dev->GetDeviceRemovedReason();
2364 case DXGI_ERROR_DEVICE_HUNG:
2365 case DXGI_ERROR_INVALID_CALL:
2366 return PIPE_GUILTY_CONTEXT_RESET;
2367 case DXGI_ERROR_DEVICE_RESET:
2368 return PIPE_INNOCENT_CONTEXT_RESET;
2370 return SUCCEEDED(hr) ? PIPE_NO_RESET : PIPE_UNKNOWN_CONTEXT_RESET;
2374 #ifdef HAVE_GALLIUM_D3D12_VIDEO
2375 struct pipe_video_codec*
2376 d3d12_video_create_codec(struct pipe_context *context,
2377 const struct pipe_video_codec *templat)
2379 if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
2380 return d3d12_video_encoder_create_encoder(context, templat);
2381 } else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
2382 return d3d12_video_create_decoder(context, templat);
2383 } else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
2384 return d3d12_video_processor_create(context, templat);
2386 debug_printf("D3D12: Unsupported video codec entrypoint %d\n", templat->entrypoint);
2392 struct pipe_context *
2393 d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
2395 struct d3d12_screen *screen = d3d12_screen(pscreen);
2396 if (FAILED(screen->dev->GetDeviceRemovedReason())) {
2397 /* Attempt recovery, but this may fail */
2398 screen->deinit(screen);
2399 if (!screen->init(screen)) {
2400 debug_printf("D3D12: failed to reset screen\n");
2405 struct d3d12_context *ctx = CALLOC_STRUCT(d3d12_context);
2409 ctx->base.screen = pscreen;
2410 ctx->base.priv = priv;
2412 ctx->base.destroy = d3d12_context_destroy;
2414 ctx->base.create_vertex_elements_state = d3d12_create_vertex_elements_state;
2415 ctx->base.bind_vertex_elements_state = d3d12_bind_vertex_elements_state;
2416 ctx->base.delete_vertex_elements_state = d3d12_delete_vertex_elements_state;
2418 ctx->base.create_blend_state = d3d12_create_blend_state;
2419 ctx->base.bind_blend_state = d3d12_bind_blend_state;
2420 ctx->base.delete_blend_state = d3d12_delete_blend_state;
2422 ctx->base.create_depth_stencil_alpha_state = d3d12_create_depth_stencil_alpha_state;
2423 ctx->base.bind_depth_stencil_alpha_state = d3d12_bind_depth_stencil_alpha_state;
2424 ctx->base.delete_depth_stencil_alpha_state = d3d12_delete_depth_stencil_alpha_state;
2426 ctx->base.create_rasterizer_state = d3d12_create_rasterizer_state;
2427 ctx->base.bind_rasterizer_state = d3d12_bind_rasterizer_state;
2428 ctx->base.delete_rasterizer_state = d3d12_delete_rasterizer_state;
2430 ctx->base.create_sampler_state = d3d12_create_sampler_state;
2431 ctx->base.bind_sampler_states = d3d12_bind_sampler_states;
2432 ctx->base.delete_sampler_state = d3d12_delete_sampler_state;
2434 ctx->base.create_sampler_view = d3d12_create_sampler_view;
2435 ctx->base.set_sampler_views = d3d12_set_sampler_views;
2436 ctx->base.sampler_view_destroy = d3d12_destroy_sampler_view;
2438 ctx->base.create_vs_state = d3d12_create_vs_state;
2439 ctx->base.bind_vs_state = d3d12_bind_vs_state;
2440 ctx->base.delete_vs_state = d3d12_delete_vs_state;
2442 ctx->base.create_fs_state = d3d12_create_fs_state;
2443 ctx->base.bind_fs_state = d3d12_bind_fs_state;
2444 ctx->base.delete_fs_state = d3d12_delete_fs_state;
2446 ctx->base.create_gs_state = d3d12_create_gs_state;
2447 ctx->base.bind_gs_state = d3d12_bind_gs_state;
2448 ctx->base.delete_gs_state = d3d12_delete_gs_state;
2450 ctx->base.create_tcs_state = d3d12_create_tcs_state;
2451 ctx->base.bind_tcs_state = d3d12_bind_tcs_state;
2452 ctx->base.delete_tcs_state = d3d12_delete_tcs_state;
2454 ctx->base.create_tes_state = d3d12_create_tes_state;
2455 ctx->base.bind_tes_state = d3d12_bind_tes_state;
2456 ctx->base.delete_tes_state = d3d12_delete_tes_state;
2458 ctx->base.set_patch_vertices = d3d12_set_patch_vertices;
2459 ctx->base.set_tess_state = d3d12_set_tess_state;
2461 ctx->base.create_compute_state = d3d12_create_compute_state;
2462 ctx->base.bind_compute_state = d3d12_bind_compute_state;
2463 ctx->base.delete_compute_state = d3d12_delete_compute_state;
2465 ctx->base.set_polygon_stipple = d3d12_set_polygon_stipple;
2466 ctx->base.set_vertex_buffers = d3d12_set_vertex_buffers;
2467 ctx->base.set_viewport_states = d3d12_set_viewport_states;
2468 ctx->base.set_scissor_states = d3d12_set_scissor_states;
2469 ctx->base.set_constant_buffer = d3d12_set_constant_buffer;
2470 ctx->base.set_framebuffer_state = d3d12_set_framebuffer_state;
2471 ctx->base.set_clip_state = d3d12_set_clip_state;
2472 ctx->base.set_blend_color = d3d12_set_blend_color;
2473 ctx->base.set_sample_mask = d3d12_set_sample_mask;
2474 ctx->base.set_stencil_ref = d3d12_set_stencil_ref;
2476 ctx->base.create_stream_output_target = d3d12_create_stream_output_target;
2477 ctx->base.stream_output_target_destroy = d3d12_stream_output_target_destroy;
2478 ctx->base.set_stream_output_targets = d3d12_set_stream_output_targets;
2480 ctx->base.set_shader_buffers = d3d12_set_shader_buffers;
2481 ctx->base.set_shader_images = d3d12_set_shader_images;
2483 ctx->base.get_timestamp = d3d12_get_timestamp;
2485 ctx->base.clear = d3d12_clear;
2486 ctx->base.clear_render_target = d3d12_clear_render_target;
2487 ctx->base.clear_depth_stencil = d3d12_clear_depth_stencil;
2488 ctx->base.draw_vbo = d3d12_draw_vbo;
2489 ctx->base.launch_grid = d3d12_launch_grid;
2490 ctx->base.flush = d3d12_flush;
2491 ctx->base.flush_resource = d3d12_flush_resource;
2493 ctx->base.fence_server_signal = d3d12_signal;
2494 ctx->base.fence_server_sync = d3d12_wait;
2496 ctx->base.memory_barrier = d3d12_memory_barrier;
2498 ctx->base.get_sample_position = d3d12_get_sample_position;
2500 ctx->base.get_device_reset_status = d3d12_get_reset_status;
2502 ctx->gfx_pipeline_state.sample_mask = ~0;
2504 d3d12_context_surface_init(&ctx->base);
2505 d3d12_context_resource_init(&ctx->base);
2506 d3d12_context_query_init(&ctx->base);
2507 d3d12_context_blit_init(&ctx->base);
2509 #ifdef HAVE_GALLIUM_D3D12_VIDEO
2510 // Add d3d12 video functions entrypoints
2511 ctx->base.create_video_codec = d3d12_video_create_codec;
2512 ctx->base.create_video_buffer = d3d12_video_buffer_create;
2513 ctx->base.video_buffer_from_handle = d3d12_video_buffer_from_handle;
2515 slab_create_child(&ctx->transfer_pool, &d3d12_screen(pscreen)->transfer_pool);
2516 slab_create_child(&ctx->transfer_pool_unsync, &d3d12_screen(pscreen)->transfer_pool);
2518 ctx->base.stream_uploader = u_upload_create_default(&ctx->base);
2519 ctx->base.const_uploader = u_upload_create_default(&ctx->base);
2520 u_suballocator_init(&ctx->so_allocator, &ctx->base, 4096, 0,
2524 struct primconvert_config cfg = {};
2525 cfg.primtypes_mask = 1 << PIPE_PRIM_POINTS |
2526 1 << PIPE_PRIM_LINES |
2527 1 << PIPE_PRIM_LINE_STRIP |
2528 1 << PIPE_PRIM_TRIANGLES |
2529 1 << PIPE_PRIM_TRIANGLE_STRIP;
2530 cfg.restart_primtypes_mask = cfg.primtypes_mask;
2531 cfg.fixed_prim_restart = true;
2532 ctx->primconvert = util_primconvert_create_config(&ctx->base, &cfg);
2533 if (!ctx->primconvert) {
2534 debug_printf("D3D12: failed to create primconvert\n");
2538 d3d12_gfx_pipeline_state_cache_init(ctx);
2539 d3d12_compute_pipeline_state_cache_init(ctx);
2540 d3d12_root_signature_cache_init(ctx);
2541 d3d12_cmd_signature_cache_init(ctx);
2542 d3d12_gs_variant_cache_init(ctx);
2543 d3d12_tcs_variant_cache_init(ctx);
2544 d3d12_compute_transform_cache_init(ctx);
2545 d3d12_context_state_table_init(ctx);
2547 ctx->D3D12SerializeVersionedRootSignature =
2548 (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)util_dl_get_proc_address(screen->d3d12_mod, "D3D12SerializeVersionedRootSignature");
2549 (void)screen->dev->QueryInterface(&ctx->dev_config);
2551 ctx->submit_id = (uint64_t)p_atomic_add_return(&screen->ctx_count, 1) << 32ull;
2553 for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) {
2554 if (!d3d12_init_batch(ctx, &ctx->batches[i])) {
2559 d3d12_start_batch(ctx, &ctx->batches[0]);
2561 ctx->sampler_pool = d3d12_descriptor_pool_new(screen,
2562 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
2564 if (!ctx->sampler_pool) {
2568 d3d12_init_null_sampler(ctx);
2571 if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL) ||
2572 (d3d12_debug & D3D12_DEBUG_DISASS))
2573 ctx->dxil_validator = dxil_create_validator(NULL);
2576 ctx->blitter = util_blitter_create(&ctx->base);
2580 if (!d3d12_init_polygon_stipple(&ctx->base)) {
2581 debug_printf("D3D12: failed to initialize polygon stipple resources\n");
2586 mtx_lock(&screen->submit_mutex);
2587 list_addtail(&ctx->context_list_entry, &screen->context_list);
2588 mtx_unlock(&screen->submit_mutex);
2590 if (flags & PIPE_CONTEXT_PREFER_THREADED)
2591 return threaded_context_create(&ctx->base,
2592 &screen->transfer_pool,
2593 d3d12_replace_buffer_storage,
2595 &ctx->threaded_context);
2601 d3d12_need_zero_one_depth_range(struct d3d12_context *ctx)
2603 struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT];
2606 * OpenGL Compatibility spec, section 15.2.3 (Shader Outputs) says
2609 * For fixed-point depth buffers, the final fragment depth written by
2610 * a fragment shader is first clamped to [0, 1] and then converted to
2611 * fixed-point as if it were a window z value (see section 13.8.1).
2612 * For floating-point depth buffers, conversion is not performed but
2613 * clamping is. Note that the depth range computation is not applied
2614 * here, only the conversion to fixed-point.
2616 * However, the D3D11.3 Functional Spec, section 17.10 (Depth Clamp) says
2619 * Depth values that reach the Output Merger, whether coming from
2620 * interpolation or from Pixel Shader output (replacing the
2621 * interpolated z), are always clamped:
2622 * z = min(Viewport.MaxDepth,max(Viewport.MinDepth,z))
2623 * following the D3D11 Floating Point Rules(3.1) for min/max.
2625 * This means that we can't always use the fixed-function viewport-mapping
2628 * There's only one case where the difference matters: When the fragment
2629 * shader writes a non-implicit value to gl_FragDepth. In all other
2630 * cases, the fragment either shouldn't have been rasterized in the
2631 * first place, or the implicit gl_FragCoord.z-value should already have
2632 * been clamped to the depth-range.
2634 * For simplicity, let's assume that an explicitly written frag-result
2635 * doesn't simply forward the value of gl_FragCoord.z. If it does, we'll
2636 * end up generating needless code, but the result will be correct.
2639 return fs->initial->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH);