2
* Copyright © Microsoft Corporation
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:
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
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
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"
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"
50
#include "D3D12ResourceState.h"
52
#include <dxguids/dxguids.h>
55
#include "indices/u_primconvert.h"
61
#include "dxil_validator.h"
65
d3d12_context_destroy(struct pipe_context *pctx)
67
struct d3d12_context *ctx = d3d12_context(pctx);
70
if (ctx->dxil_validator)
71
dxil_destroy_validator(ctx->dxil_validator);
74
if (ctx->timestamp_query)
75
pctx->destroy_query(pctx, ctx->timestamp_query);
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);
93
u_suballocator_destroy(&ctx->query_allocator);
95
if (pctx->stream_uploader)
96
u_upload_destroy(pctx->stream_uploader);
97
if (pctx->const_uploader)
98
u_upload_destroy(pctx->const_uploader);
100
delete ctx->resource_state_manager;
106
d3d12_create_vertex_elements_state(struct pipe_context *pctx,
107
unsigned num_elements,
108
const struct pipe_vertex_element *elements)
110
struct d3d12_vertex_elements_state *cso = CALLOC_STRUCT(d3d12_vertex_elements_state);
114
for (unsigned i = 0; i < num_elements; ++i) {
115
cso->elements[i].SemanticName = "TEXCOORD";
116
cso->elements[i].SemanticIndex = i;
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;
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;
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;
134
cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
135
cso->elements[i].InstanceDataStepRate = 0;
139
cso->num_elements = num_elements;
144
d3d12_bind_vertex_elements_state(struct pipe_context *pctx,
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;
153
d3d12_delete_vertex_elements_state(struct pipe_context *pctx,
160
blend_factor_rgb(enum pipe_blendfactor 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 */
183
unreachable("unexpected blend factor");
187
blend_factor_alpha(enum pipe_blendfactor 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;
210
unreachable("unexpected blend factor");
214
need_blend_factor_rgb(enum pipe_blendfactor 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;
225
return D3D12_BLEND_FACTOR_NONE;
230
need_blend_factor_alpha(enum pipe_blendfactor 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;
240
return D3D12_BLEND_FACTOR_NONE;
244
static D3D12_BLEND_OP
245
blend_op(enum pipe_blend_func 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;
254
unreachable("unexpected blend function");
257
static D3D12_COMPARISON_FUNC
258
compare_op(enum pipe_compare_func 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;
270
unreachable("unexpected compare");
273
static D3D12_LOGIC_OP
274
logic_op(enum pipe_logicop 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;
294
unreachable("unexpected logicop function");
298
color_write_mask(unsigned colormask)
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;
315
d3d12_create_blend_state(struct pipe_context *pctx,
316
const struct pipe_blend_state *blend_state)
318
struct d3d12_blend_state *state = CALLOC_STRUCT(d3d12_blend_state);
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);
329
state->desc.AlphaToCoverageEnable = blend_state->alpha_to_coverage;
332
if (blend_state->independent_blend_enable) {
333
state->desc.IndependentBlendEnable = TRUE;
334
num_targets = PIPE_MAX_COLOR_BUFS;
337
for (int i = 0; i < num_targets; ++i) {
338
const struct pipe_rt_blend_state *rt = blend_state->rt + i;
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);
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);
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");
360
if (util_blend_state_is_dual(blend_state, i))
361
state->is_dual_src = true;
364
state->desc.RenderTarget[i].RenderTargetWriteMask = color_write_mask(rt->colormask);
371
d3d12_bind_blend_state(struct pipe_context *pctx, void *blend_state)
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;
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;
385
d3d12_delete_blend_state(struct pipe_context *pctx, void *blend_state)
387
d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), blend_state);
391
static D3D12_STENCIL_OP
392
stencil_op(enum pipe_stencil_op 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;
404
unreachable("unexpected op");
407
static D3D12_DEPTH_STENCILOP_DESC
408
stencil_op_state(const struct pipe_stencil_state *src)
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);
419
d3d12_create_depth_stencil_alpha_state(struct pipe_context *pctx,
420
const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)
422
struct d3d12_depth_stencil_alpha_state *dsa = CALLOC_STRUCT(d3d12_depth_stencil_alpha_state);
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);
431
/* TODO Add support for GL_depth_bound_tests */
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;
440
if (depth_stencil_alpha->stencil[0].enabled) {
441
dsa->desc.StencilEnable = TRUE;
442
dsa->desc.FrontFace = stencil_op_state(depth_stencil_alpha->stencil);
445
if (depth_stencil_alpha->stencil[1].enabled)
446
dsa->desc.BackFace = stencil_op_state(depth_stencil_alpha->stencil + 1);
448
dsa->desc.BackFace = dsa->desc.FrontFace;
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;
458
d3d12_bind_depth_stencil_alpha_state(struct pipe_context *pctx,
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;
467
d3d12_delete_depth_stencil_alpha_state(struct pipe_context *pctx,
470
d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), dsa_state);
474
static D3D12_FILL_MODE
475
fill_mode(unsigned 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;
486
unreachable("unsupported fill-mode");
491
d3d12_create_rasterizer_state(struct pipe_context *pctx,
492
const struct pipe_rasterizer_state *rs_state)
494
struct d3d12_rasterizer_state *cso = CALLOC_STRUCT(d3d12_rasterizer_state);
498
cso->base = *rs_state;
500
assert(rs_state->depth_clip_near == rs_state->depth_clip_far);
502
switch (rs_state->cull_face) {
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);
509
/* create a modified CSO for the back-state, so we can draw with
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);
517
if (!cso->twoface_back) {
522
cso->desc.CullMode = D3D12_CULL_MODE_NONE;
523
cso->desc.FillMode = fill_mode(rs_state->fill_front);
527
case PIPE_FACE_FRONT:
528
cso->desc.CullMode = D3D12_CULL_MODE_FRONT;
529
cso->desc.FillMode = fill_mode(rs_state->fill_back);
533
cso->desc.CullMode = D3D12_CULL_MODE_BACK;
534
cso->desc.FillMode = fill_mode(rs_state->fill_front);
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;
544
unreachable("unsupported cull-mode");
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 */
558
d3d12_bind_rasterizer_state(struct pipe_context *pctx, void *rs_state)
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;
566
d3d12_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state)
568
d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), rs_state);
572
static D3D12_TEXTURE_ADDRESS_MODE
573
sampler_address_mode(enum pipe_tex_wrap wrap, enum pipe_tex_filter filter)
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 */
587
unreachable("unexpected wrap");
591
get_filter(const struct pipe_sampler_state *state)
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,
612
static const D3D12_FILTER anisotropic_lut[2] = {
613
D3D12_FILTER_ANISOTROPIC,
614
D3D12_FILTER_COMPARISON_ANISOTROPIC,
617
if (state->max_anisotropy > 1) {
618
return anisotropic_lut[state->compare_mode];
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;
630
d3d12_create_sampler_state(struct pipe_context *pctx,
631
const struct pipe_sampler_state *state)
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 = {};
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;
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) {
658
unreachable("unexpected mip filter");
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;
666
unreachable("unexpected comparison mode");
668
desc.MaxAnisotropy = state->max_anisotropy;
669
desc.Filter = get_filter(state);
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);
680
// TODO Normalized Coordinates?
681
d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ss->handle);
682
screen->dev->CreateSampler(&desc, ss->handle.cpu_handle);
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;
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;
699
d3d12_bind_sampler_states(struct pipe_context *pctx,
700
enum pipe_shader_type shader,
702
unsigned num_samplers,
705
struct d3d12_context *ctx = d3d12_context(pctx);
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");
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);
718
#undef STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC
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];
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;
734
memset(&wrap, 0, sizeof (dxil_wrap_sampler_state));
738
ctx->num_samplers[shader] = start_slot + num_samplers;
739
ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SAMPLERS;
743
d3d12_delete_sampler_state(struct pipe_context *pctx,
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,
750
if (state->is_shadow_sampler)
751
util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle,
752
state->handle_without_shadow);
756
static D3D12_SRV_DIMENSION
757
view_dimension(enum pipe_texture_target target, unsigned samples)
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;
774
unreachable("unexpected target");
778
static D3D12_SHADER_COMPONENT_MAPPING
779
component_mapping(enum pipe_swizzle swizzle, D3D12_SHADER_COMPONENT_MAPPING id)
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;
790
unreachable("unexpected swizzle");
795
d3d12_init_sampler_view_descriptor(struct d3d12_sampler_view *sampler_view)
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);
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);
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;
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)
824
ID3D12Resource *d3d12_res = d3d12_resource_underlying(res, &offset);
825
assert(offset == 0 || res->base.b.target == PIPE_BUFFER);
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);
834
desc.Texture1D.MostDetailedMip = state->u.tex.first_level;
835
desc.Texture1D.MipLevels = sampler_view->mip_levels;
836
desc.Texture1D.ResourceMinLODClamp = 0.0f;
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;
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);
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;
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);
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;
868
case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY:
869
desc.Texture2DMSArray.FirstArraySlice = state->u.tex.first_layer;
870
desc.Texture2DMSArray.ArraySize = array_size;
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);
877
desc.Texture3D.MostDetailedMip = state->u.tex.first_level;
878
desc.Texture3D.MipLevels = sampler_view->mip_levels;
879
desc.Texture3D.ResourceMinLODClamp = 0.0f;
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);
886
desc.TextureCube.MostDetailedMip = state->u.tex.first_level;
887
desc.TextureCube.MipLevels = sampler_view->mip_levels;
888
desc.TextureCube.ResourceMinLODClamp = 0.0f;
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;
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);
904
unreachable("Invalid SRV dimension");
907
screen->dev->CreateShaderResourceView(d3d12_res, &desc,
908
sampler_view->handle.cpu_handle);
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)
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);
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);
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]
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];
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);
946
d3d12_init_sampler_view_descriptor(sampler_view);
948
return &sampler_view->base;
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);
957
res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]++;
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);
966
assert(res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0);
967
res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]--;
972
d3d12_set_sampler_views(struct pipe_context *pctx,
973
enum pipe_shader_type shader_type,
976
unsigned unbind_num_trailing_slots,
978
struct pipe_sampler_view **views)
980
struct d3d12_context *ctx = d3d12_context(pctx);
981
unsigned shader_bit = (1 << shader_type);
982
ctx->has_int_samplers &= ~shader_bit;
984
for (unsigned i = 0; i < num_views; ++i) {
985
struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + i];
987
d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view);
989
struct pipe_sampler_view *new_view = views[i];
991
d3d12_increment_sampler_view_bind_count(pctx, shader_type, new_view);
993
if (take_ownership) {
994
pipe_sampler_view_reference(&old_view, NULL);
997
pipe_sampler_view_reference(&old_view, 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;
1015
wss.is_int_sampler = 0;
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;
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];
1032
d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view);
1033
pipe_sampler_view_reference(&old_view, NULL);
1035
ctx->num_sampler_views[shader_type] = start_slot + num_views;
1036
ctx->shader_dirty[shader_type] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS;
1040
d3d12_destroy_sampler_view(struct pipe_context *pctx,
1041
struct pipe_sampler_view *pview)
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);
1050
delete_shader(struct d3d12_context *ctx, enum pipe_shader_type stage,
1051
struct d3d12_shader_selector *shader)
1053
d3d12_gfx_pipeline_state_cache_invalidate_shader(ctx, stage, shader);
1055
/* Make sure the pipeline state no longer reference the deleted shader */
1056
struct d3d12_shader *iter = shader->first;
1058
if (ctx->gfx_pipeline_state.stages[stage] == iter) {
1059
ctx->gfx_pipeline_state.stages[stage] = NULL;
1062
iter = iter->next_variant;
1065
d3d12_shader_free(shader);
1069
bind_stage(struct d3d12_context *ctx, enum pipe_shader_type stage,
1070
struct d3d12_shader_selector *shader)
1072
assert(stage < D3D12_GFX_SHADER_STAGES);
1073
ctx->gfx_stages[stage] = shader;
1077
d3d12_create_vs_state(struct pipe_context *pctx,
1078
const struct pipe_shader_state *shader)
1080
return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX, shader);
1084
d3d12_bind_vs_state(struct pipe_context *pctx,
1087
bind_stage(d3d12_context(pctx), PIPE_SHADER_VERTEX,
1088
(struct d3d12_shader_selector *) vss);
1092
d3d12_delete_vs_state(struct pipe_context *pctx,
1095
delete_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX,
1096
(struct d3d12_shader_selector *) vs);
1100
d3d12_create_fs_state(struct pipe_context *pctx,
1101
const struct pipe_shader_state *shader)
1103
return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, shader);
1107
d3d12_bind_fs_state(struct pipe_context *pctx,
1110
bind_stage(d3d12_context(pctx), PIPE_SHADER_FRAGMENT,
1111
(struct d3d12_shader_selector *) fss);
1115
d3d12_delete_fs_state(struct pipe_context *pctx,
1118
delete_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT,
1119
(struct d3d12_shader_selector *) fs);
1123
d3d12_create_gs_state(struct pipe_context *pctx,
1124
const struct pipe_shader_state *shader)
1126
return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, shader);
1130
d3d12_bind_gs_state(struct pipe_context *pctx, void *gss)
1132
bind_stage(d3d12_context(pctx), PIPE_SHADER_GEOMETRY,
1133
(struct d3d12_shader_selector *) gss);
1137
d3d12_delete_gs_state(struct pipe_context *pctx, void *gs)
1139
delete_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY,
1140
(struct d3d12_shader_selector *) gs);
1144
d3d12_create_tcs_state(struct pipe_context *pctx,
1145
const struct pipe_shader_state *shader)
1147
return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL, shader);
1151
d3d12_bind_tcs_state(struct pipe_context *pctx, void *tcss)
1153
bind_stage(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL,
1154
(struct d3d12_shader_selector *)tcss);
1158
d3d12_delete_tcs_state(struct pipe_context *pctx, void *tcs)
1160
delete_shader(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL,
1161
(struct d3d12_shader_selector *)tcs);
1165
d3d12_create_tes_state(struct pipe_context *pctx,
1166
const struct pipe_shader_state *shader)
1168
return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL, shader);
1172
d3d12_bind_tes_state(struct pipe_context *pctx, void *tess)
1174
bind_stage(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL,
1175
(struct d3d12_shader_selector *)tess);
1179
d3d12_delete_tes_state(struct pipe_context *pctx, void *tes)
1181
delete_shader(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL,
1182
(struct d3d12_shader_selector *)tes);
1186
d3d12_create_compute_state(struct pipe_context *pctx,
1187
const struct pipe_compute_state *shader)
1189
return d3d12_create_compute_shader(d3d12_context(pctx), shader);
1193
d3d12_bind_compute_state(struct pipe_context *pctx, void *css)
1195
d3d12_context(pctx)->compute_state = (struct d3d12_shader_selector *)css;
1199
d3d12_delete_compute_state(struct pipe_context *pctx, void *cs)
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);
1205
/* Make sure the pipeline state no longer reference the deleted shader */
1206
struct d3d12_shader *iter = shader->first;
1208
if (ctx->compute_pipeline_state.stage == iter) {
1209
ctx->compute_pipeline_state.stage = NULL;
1212
iter = iter->next_variant;
1215
d3d12_shader_free(shader);
1219
d3d12_init_polygon_stipple(struct pipe_context *pctx)
1221
struct d3d12_context *ctx = d3d12_context(pctx);
1223
ctx->pstipple.texture = util_pstipple_create_stipple_texture(pctx, NULL);
1224
if (!ctx->pstipple.texture)
1227
ctx->pstipple.sampler_view = util_pstipple_create_sampler_view(pctx, ctx->pstipple.texture);
1228
if (!ctx->pstipple.sampler_view)
1231
ctx->pstipple.sampler_cso = (struct d3d12_sampler_state *)util_pstipple_create_sampler(pctx);
1232
if (!ctx->pstipple.sampler_cso)
1239
d3d12_set_polygon_stipple(struct pipe_context *pctx,
1240
const struct pipe_poly_stipple *ps)
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);
1248
memset(undef, UINT32_MAX, sizeof(undef));
1250
if (!memcmp(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple)))
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);
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)
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,
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)
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;
1283
ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS;
1287
d3d12_set_viewport_states(struct pipe_context *pctx,
1288
unsigned start_slot,
1289
unsigned num_viewports,
1290
const struct pipe_viewport_state *state)
1292
struct d3d12_context *ctx = d3d12_context(pctx);
1294
for (unsigned i = 0; i < num_viewports; ++i) {
1295
if (state[i].scale[1] < 0) {
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;
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;
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;
1307
float near_depth = state[i].translate[2] - state[i].scale[2];
1308
float far_depth = state[i].translate[2] + state[i].scale[2];
1310
bool reverse_depth_range = near_depth > far_depth;
1311
if (reverse_depth_range) {
1312
float tmp = near_depth;
1313
near_depth = far_depth;
1315
ctx->reverse_depth_range |= (1 << (start_slot + i));
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];
1322
ctx->num_viewports = start_slot + num_viewports;
1323
ctx->state_dirty |= D3D12_DIRTY_VIEWPORT;
1328
d3d12_set_scissor_states(struct pipe_context *pctx,
1329
unsigned start_slot, unsigned num_scissors,
1330
const struct pipe_scissor_state *states)
1332
struct d3d12_context *ctx = d3d12_context(pctx);
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];
1341
ctx->state_dirty |= D3D12_DIRTY_SCISSOR;
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]--;
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]++;
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)
1365
struct d3d12_context *ctx = d3d12_context(pctx);
1366
struct d3d12_resource *old_buf = d3d12_resource(ctx->cbufs[shader][index].buffer);
1368
d3d12_decrement_constant_buffer_bind_count(ctx, shader, old_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));
1379
struct pipe_resource *buffer = buf->buffer;
1381
d3d12_increment_constant_buffer_bind_count(ctx, shader, d3d12_resource(buffer));
1383
if (take_ownership) {
1384
pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL);
1385
ctx->cbufs[shader][index].buffer = buffer;
1387
pipe_resource_reference(&ctx->cbufs[shader][index].buffer, buffer);
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;
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;
1401
ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_CONSTBUF;
1405
d3d12_set_framebuffer_state(struct pipe_context *pctx,
1406
const struct pipe_framebuffer_state *state)
1408
struct d3d12_context *ctx = d3d12_context(pctx);
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;
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);
1424
ctx->gfx_pipeline_state.rtv_formats[i] = DXGI_FORMAT_UNKNOWN;
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);
1432
ctx->gfx_pipeline_state.dsv_format = DXGI_FORMAT_UNKNOWN;
1435
samples = state->samples;
1437
ctx->gfx_pipeline_state.samples = MAX2(samples, 1);
1439
ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER;
1440
if (!prev_cbufs_or_zsbuf || !new_cbufs_or_zsbuf)
1441
ctx->state_dirty |= D3D12_DIRTY_VIEWPORT;
1445
d3d12_set_blend_color(struct pipe_context *pctx,
1446
const struct pipe_blend_color *color)
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;
1454
d3d12_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
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;
1462
d3d12_set_stencil_ref(struct pipe_context *pctx,
1463
const struct pipe_stencil_ref ref)
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;
1474
d3d12_set_clip_state(struct pipe_context *pctx,
1475
const struct pipe_clip_state *pcs)
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)
1485
struct d3d12_resource *res = d3d12_resource(pres);
1486
struct d3d12_stream_output_target *cso = CALLOC_STRUCT(d3d12_stream_output_target);
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;
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);
1505
d3d12_stream_output_target_destroy(struct pipe_context *ctx,
1506
struct pipe_stream_output_target *state)
1508
pipe_resource_reference(&state->buffer, NULL);
1514
fill_stream_output_buffer_view(D3D12_STREAM_OUTPUT_BUFFER_VIEW *view,
1515
struct d3d12_stream_output_target *target)
1517
struct d3d12_resource *res = d3d12_resource(target->base.buffer);
1518
struct d3d12_resource *fill_res = d3d12_resource(target->fill_buffer);
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;
1526
update_so_fill_buffer_count(struct d3d12_context *ctx,
1527
struct pipe_resource *fill_buffer,
1528
unsigned fill_buffer_offset,
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);
1535
pipe_buffer_unmap(&ctx->base, transfer);
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)
1544
struct d3d12_context *ctx = d3d12_context(pctx);
1546
assert(num_targets <= ARRAY_SIZE(ctx->so_targets));
1548
d3d12_disable_fake_so_buffers(ctx);
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;
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]);
1561
fill_stream_output_buffer_view(&ctx->so_buffer_views[i], target);
1562
pipe_so_target_reference(&ctx->so_targets[i], targets[i]);
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);
1571
ctx->gfx_pipeline_state.num_so_targets = num_targets;
1572
ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
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]--;
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]++;
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)
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];
1601
d3d12_decrement_ssbo_bind_count(ctx, shader, d3d12_resource(slot->buffer));
1602
pipe_resource_reference(&slot->buffer, NULL);
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));
1611
memset(slot, 0, sizeof(*slot));
1615
ctx->num_ssbo_views[shader] = MAX2(ctx->num_ssbo_views[shader], count + start_slot);
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;
1625
ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SSBO;
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]--;
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]++;
1644
is_valid_uav_cast(enum pipe_format resource_format, enum pipe_format view_format)
1646
if (view_format != PIPE_FORMAT_R32_UINT &&
1647
view_format != PIPE_FORMAT_R32_SINT &&
1648
view_format != PIPE_FORMAT_R32_FLOAT)
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:
1662
static enum pipe_format
1663
get_shader_image_emulation_format(enum pipe_format resource_format)
1665
#define CASE(f) case DXGI_FORMAT_##f##_TYPELESS: return PIPE_FORMAT_##f##_UINT
1666
switch (d3d12_get_typeless_format(resource_format)) {
1677
case DXGI_FORMAT_R11G11B10_FLOAT:
1678
return PIPE_FORMAT_R11G11B10_FLOAT;
1680
unreachable("Unexpected shader image resource format");
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)
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);
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);
1703
d3d12_increment_image_bind_count(ctx, shader, d3d12_resource(images[i].resource));
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);
1714
memset(slot, 0, sizeof(*slot));
1718
ctx->num_image_views[shader] = MAX2(ctx->num_image_views[shader], count + start_slot);
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;
1728
ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_IMAGE;
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;
1740
if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0) {
1741
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS;
1744
if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SSBO] > 0) {
1745
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO;
1748
if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0) {
1749
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE;
1755
d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor)
1757
if (ctx->fake_so_buffer_factor == factor)
1760
d3d12_disable_fake_so_buffers(ctx);
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;
1766
fake_target = CALLOC_STRUCT(d3d12_stream_output_target);
1769
pipe_reference_init(&fake_target->base.reference, 1);
1770
fake_target->base.context = &ctx->base;
1772
d3d12_resource_wait_idle(ctx, d3d12_resource(target->base.buffer), false);
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;
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,
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);
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);
1804
ctx->fake_so_buffer_factor = factor;
1805
ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
1811
d3d12_disable_fake_so_buffers(struct d3d12_context *ctx)
1813
if (ctx->fake_so_buffer_factor == 0)
1816
d3d12_flush_cmdlist_and_wait(ctx);
1818
bool cs_state_saved = false;
1819
d3d12_compute_transform_save_restore save;
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];
1825
if (fake_target == NULL)
1828
if (!cs_state_saved) {
1829
cs_state_saved = true;
1830
d3d12_save_compute_transform_state(ctx, &save);
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));
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;
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;
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);
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);
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)
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;
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;
1875
ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key));
1877
ctx->transform_state_vars[0] = ctx->fake_so_buffer_factor;
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);
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);
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);
1897
pipe_so_target_reference(&ctx->fake_so_targets[i], NULL);
1898
ctx->fake_so_buffer_views[i].SizeInBytes = 0;
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);
1907
ctx->fake_so_buffer_factor = 0;
1908
ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT;
1911
d3d12_restore_compute_transform_state(ctx, &save);
1917
d3d12_flush_cmdlist(struct d3d12_context *ctx)
1919
d3d12_end_batch(ctx, d3d12_current_batch(ctx));
1921
ctx->current_batch_idx++;
1922
if (ctx->current_batch_idx == ARRAY_SIZE(ctx->batches))
1923
ctx->current_batch_idx = 0;
1925
d3d12_start_batch(ctx, d3d12_current_batch(ctx));
1929
d3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx)
1931
struct d3d12_batch *batch = d3d12_current_batch(ctx);
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);
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)
1945
TransitionableResourceState *xres = d3d12_resource_state(res);
1947
if (bind_invalidate == D3D12_BIND_INVALIDATE_FULL)
1948
d3d12_invalidate_context_bindings(ctx, res);
1950
ctx->resource_state_manager->TransitionResource(xres, state);
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)
1962
TransitionableResourceState *xres = d3d12_resource_state(res);
1964
if(bind_invalidate == D3D12_BIND_INVALIDATE_FULL)
1965
d3d12_invalidate_context_bindings(ctx, res);
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);
1982
d3d12_apply_resource_states(struct d3d12_context *ctx, bool is_implicit_dispatch)
1984
ctx->resource_state_manager->ApplyAllResourceTransitions(ctx->cmdlist, ctx->submit_id, is_implicit_dispatch);
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)
1995
struct d3d12_context *ctx = d3d12_context(pctx);
1996
struct d3d12_surface *surf = d3d12_surface(psurf);
1998
if (!render_condition_enabled && ctx->current_predication)
1999
ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
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);
2007
enum pipe_format format = psurf->texture->format;
2008
float clear_color[4];
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];
2017
for (int c = 0; c < 4; ++c)
2018
clear_color[c] = color->f[c];
2021
if (!(util_format_colormask(util_format_description(psurf->texture->format)) &
2023
clear_color[3] = 1.0f;
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);
2031
d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf);
2033
if (!render_condition_enabled && ctx->current_predication) {
2034
d3d12_enable_predication(ctx);
2039
d3d12_clear_depth_stencil(struct pipe_context *pctx,
2040
struct pipe_surface *psurf,
2041
unsigned clear_flags,
2044
unsigned dstx, unsigned dsty,
2045
unsigned width, unsigned height,
2046
bool render_condition_enabled)
2048
struct d3d12_context *ctx = d3d12_context(pctx);
2049
struct d3d12_surface *surf = d3d12_surface(psurf);
2051
if (!render_condition_enabled && ctx->current_predication)
2052
ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
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;
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);
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);
2072
d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf);
2074
if (!render_condition_enabled && ctx->current_predication) {
2075
d3d12_enable_predication(ctx);
2080
d3d12_clear(struct pipe_context *pctx,
2082
const struct pipe_scissor_state *scissor_state,
2083
const union pipe_color_union *color,
2084
double depth, unsigned stencil)
2086
struct d3d12_context *ctx = d3d12_context(pctx);
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,
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,
2104
0, 0, psurf->width, psurf->height,
2110
d3d12_flush(struct pipe_context *pipe,
2111
struct pipe_fence_handle **fence,
2114
struct d3d12_context *ctx = d3d12_context(pipe);
2115
struct d3d12_batch *batch = d3d12_current_batch(ctx);
2117
d3d12_flush_cmdlist(ctx);
2120
d3d12_fence_reference((struct d3d12_fence **)fence, batch->fence);
2124
d3d12_flush_resource(struct pipe_context *pctx,
2125
struct pipe_resource *pres)
2127
struct d3d12_context *ctx = d3d12_context(pctx);
2128
struct d3d12_resource *res = d3d12_resource(pres);
2130
d3d12_transition_resource_state(ctx, res,
2131
D3D12_RESOURCE_STATE_COMMON,
2132
D3D12_BIND_INVALIDATE_FULL);
2133
d3d12_apply_resource_states(ctx, false);
2137
d3d12_init_null_sampler(struct d3d12_context *ctx)
2139
struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
2141
d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ctx->null_sampler);
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;
2153
memset(desc.BorderColor, 0, sizeof(desc.BorderColor));
2154
screen->dev->CreateSampler(&desc, ctx->null_sampler.cpu_handle);
2158
d3d12_get_timestamp(struct pipe_context *pctx)
2160
struct d3d12_context *ctx = d3d12_context(pctx);
2162
if (!ctx->timestamp_query)
2163
ctx->timestamp_query = pctx->create_query(pctx, PIPE_QUERY_TIMESTAMP, 0);
2165
pipe_query_result result;
2166
pctx->end_query(pctx, ctx->timestamp_query);
2167
pctx->get_query_result(pctx, ctx->timestamp_query, true, &result);
2172
d3d12_rebind_buffer(struct d3d12_context *ctx, struct d3d12_resource *res)
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];
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;
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;
2194
assert(!ctx->fake_so_targets[i] || ctx->fake_so_targets[i]->buffer != &res->base.b);
2198
d3d12_invalidate_context_bindings(ctx, res);
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)
2209
struct d3d12_context *ctx = d3d12_context(pctx);
2210
struct d3d12_resource *dst = d3d12_resource(pdst);
2211
struct d3d12_resource *src = d3d12_resource(psrc);
2213
struct d3d12_bo *old_bo = dst->bo;
2214
d3d12_bo_reference(src->bo);
2216
p_atomic_inc(&dst->generation_id);
2217
d3d12_rebind_buffer(ctx, dst);
2218
d3d12_bo_unreference(old_bo);
2222
d3d12_memory_barrier(struct pipe_context *pctx, unsigned flags)
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;
2235
* PIPE_BARRIER_INDIRECT_BUFFER
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;
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.
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;
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);
2270
d3d12_get_sample_position(struct pipe_context *pctx, unsigned sample_count, unsigned sample_index,
2273
/* Sample patterns transcribed from
2274
* https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels
2276
static const int sample_pattern_1sample[2] = { 0, 0 };
2277
static const int sample_pattern_2samples[2][2] = {
2281
static const int sample_pattern_4samples[4][2] = {
2287
static const int sample_pattern_8samples[8][2] = {
2297
static const int sample_pattern_16samples[16][2] = {
2316
switch (sample_count) {
2319
samples = sample_pattern_1sample;
2322
samples = sample_pattern_2samples[sample_index];
2325
samples = sample_pattern_4samples[sample_index];
2328
samples = sample_pattern_8samples[sample_index];
2331
samples = sample_pattern_16samples[sample_index];
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;
2341
d3d12_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices)
2343
struct d3d12_context *ctx = d3d12_context(pctx);
2344
ctx->patch_vertices = patch_vertices;
2345
ctx->cmdlist_dirty |= D3D12_DIRTY_PRIM_MODE;
2349
d3d12_set_tess_state(struct pipe_context *pctx,
2350
const float default_outer_level[4],
2351
const float default_inner_level[2])
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));
2358
struct pipe_context *
2359
d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
2361
struct d3d12_screen *screen = d3d12_screen(pscreen);
2363
struct d3d12_context *ctx = CALLOC_STRUCT(d3d12_context);
2367
ctx->base.screen = pscreen;
2368
ctx->base.priv = priv;
2370
ctx->base.destroy = d3d12_context_destroy;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
2416
ctx->base.set_patch_vertices = d3d12_set_patch_vertices;
2417
ctx->base.set_tess_state = d3d12_set_tess_state;
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;
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;
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;
2438
ctx->base.set_shader_buffers = d3d12_set_shader_buffers;
2439
ctx->base.set_shader_images = d3d12_set_shader_images;
2441
ctx->base.get_timestamp = d3d12_get_timestamp;
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;
2451
ctx->base.memory_barrier = d3d12_memory_barrier;
2453
ctx->base.get_sample_position = d3d12_get_sample_position;
2455
ctx->gfx_pipeline_state.sample_mask = ~0;
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);
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);
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,
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");
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);
2494
util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT);
2496
debug_printf("D3D12: failed to load D3D12.DLL\n");
2499
ctx->D3D12SerializeVersionedRootSignature =
2500
(PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)util_dl_get_proc_address(d3d12_mod, "D3D12SerializeVersionedRootSignature");
2502
ctx->submit_id = (uint64_t)p_atomic_add_return(&screen->ctx_count, 1) << 32ull;
2504
for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) {
2505
if (!d3d12_init_batch(ctx, &ctx->batches[i])) {
2510
d3d12_start_batch(ctx, &ctx->batches[0]);
2512
ctx->sampler_pool = d3d12_descriptor_pool_new(screen,
2513
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
2515
if (!ctx->sampler_pool) {
2519
d3d12_init_null_sampler(ctx);
2522
if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL) ||
2523
(d3d12_debug & D3D12_DEBUG_DISASS))
2524
ctx->dxil_validator = dxil_create_validator(NULL);
2527
ctx->blitter = util_blitter_create(&ctx->base);
2531
ctx->resource_state_manager = new ResourceStateManager();
2533
if (!d3d12_init_polygon_stipple(&ctx->base)) {
2534
debug_printf("D3D12: failed to initialize polygon stipple resources\n");
2539
if (flags & PIPE_CONTEXT_PREFER_THREADED)
2540
return threaded_context_create(&ctx->base,
2541
&screen->transfer_pool,
2542
d3d12_replace_buffer_storage,
2544
&ctx->threaded_context);
2550
d3d12_need_zero_one_depth_range(struct d3d12_context *ctx)
2552
struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT];
2555
* OpenGL Compatibility spec, section 15.2.3 (Shader Outputs) says
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.
2565
* However, the D3D11.3 Functional Spec, section 17.10 (Depth Clamp) says
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.
2574
* This means that we can't always use the fixed-function viewport-mapping
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.
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.
2588
return fs->initial->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH);