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