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