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