~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/d3d12/d3d12_context.cpp

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

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