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