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