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