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