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