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