Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_draw.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_compiler.h"
25
#include "d3d12_context.h"
26
#include "d3d12_format.h"
27
#include "d3d12_query.h"
28
#include "d3d12_resource.h"
29
#include "d3d12_root_signature.h"
30
#include "d3d12_screen.h"
31
#include "d3d12_surface.h"
32
33
#include "util/u_debug.h"
34
#include "util/u_draw.h"
35
#include "util/u_helpers.h"
36
#include "util/u_inlines.h"
37
#include "util/u_prim.h"
38
#include "util/u_prim_restart.h"
39
#include "util/u_math.h"
40
41
extern "C" {
42
#include "indices/u_primconvert.h"
43
}
44
45
static const D3D12_RECT MAX_SCISSOR = { D3D12_VIEWPORT_BOUNDS_MIN,
46
D3D12_VIEWPORT_BOUNDS_MIN,
47
D3D12_VIEWPORT_BOUNDS_MAX,
48
D3D12_VIEWPORT_BOUNDS_MAX };
49
50
static D3D12_GPU_DESCRIPTOR_HANDLE
51
fill_cbv_descriptors(struct d3d12_context *ctx,
52
struct d3d12_shader *shader,
53
int stage)
54
{
55
struct d3d12_batch *batch = d3d12_current_batch(ctx);
56
struct d3d12_descriptor_handle table_start;
57
d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
58
59
for (unsigned i = 0; i < shader->num_cb_bindings; i++) {
60
unsigned binding = shader->cb_bindings[i].binding;
61
struct pipe_constant_buffer *buffer = &ctx->cbufs[stage][binding];
62
63
D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {};
64
if (buffer && buffer->buffer) {
65
struct d3d12_resource *res = d3d12_resource(buffer->buffer);
66
d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE);
67
cbv_desc.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset;
68
cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16,
69
align(buffer->buffer_size, 256));
70
d3d12_batch_reference_resource(batch, res);
71
}
72
73
struct d3d12_descriptor_handle handle;
74
d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle);
75
d3d12_screen(ctx->base.screen)->dev->CreateConstantBufferView(&cbv_desc, handle.cpu_handle);
76
}
77
78
return table_start.gpu_handle;
79
}
80
81
static D3D12_GPU_DESCRIPTOR_HANDLE
82
fill_srv_descriptors(struct d3d12_context *ctx,
83
struct d3d12_shader *shader,
84
unsigned stage)
85
{
86
struct d3d12_batch *batch = d3d12_current_batch(ctx);
87
struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
88
D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
89
struct d3d12_descriptor_handle table_start;
90
91
d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
92
93
for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)
94
{
95
struct d3d12_sampler_view *view;
96
97
if (i == shader->pstipple_binding) {
98
view = (struct d3d12_sampler_view*)ctx->pstipple.sampler_view;
99
} else {
100
view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][i];
101
}
102
103
unsigned desc_idx = i - shader->begin_srv_binding;
104
if (view != NULL) {
105
descs[desc_idx] = view->handle.cpu_handle;
106
d3d12_batch_reference_sampler_view(batch, view);
107
108
D3D12_RESOURCE_STATES state = (stage == PIPE_SHADER_FRAGMENT) ?
109
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE :
110
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
111
if (view->base.texture->target == PIPE_BUFFER) {
112
d3d12_transition_resource_state(ctx, d3d12_resource(view->base.texture),
113
state,
114
D3D12_BIND_INVALIDATE_NONE);
115
} else {
116
d3d12_transition_subresources_state(ctx, d3d12_resource(view->base.texture),
117
view->base.u.tex.first_level, view->mip_levels,
118
view->base.u.tex.first_layer, view->array_size,
119
d3d12_get_format_start_plane(view->base.format),
120
d3d12_get_format_num_planes(view->base.format),
121
state,
122
D3D12_BIND_INVALIDATE_NONE);
123
}
124
} else {
125
descs[desc_idx] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle;
126
}
127
}
128
129
d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);
130
131
return table_start.gpu_handle;
132
}
133
134
static D3D12_GPU_DESCRIPTOR_HANDLE
135
fill_sampler_descriptors(struct d3d12_context *ctx,
136
const struct d3d12_shader_selector *shader_sel,
137
unsigned stage)
138
{
139
const struct d3d12_shader *shader = shader_sel->current;
140
struct d3d12_batch *batch = d3d12_current_batch(ctx);
141
D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
142
struct d3d12_descriptor_handle table_start;
143
144
d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start);
145
146
for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)
147
{
148
struct d3d12_sampler_state *sampler;
149
150
if (i == shader->pstipple_binding) {
151
sampler = ctx->pstipple.sampler_cso;
152
} else {
153
sampler = ctx->samplers[stage][i];
154
}
155
156
unsigned desc_idx = i - shader->begin_srv_binding;
157
if (sampler != NULL) {
158
if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad)
159
descs[desc_idx] = sampler->handle_without_shadow.cpu_handle;
160
else
161
descs[desc_idx] = sampler->handle.cpu_handle;
162
} else
163
descs[desc_idx] = ctx->null_sampler.cpu_handle;
164
}
165
166
d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);
167
return table_start.gpu_handle;
168
}
169
170
static unsigned
171
fill_state_vars(struct d3d12_context *ctx,
172
const struct pipe_draw_info *dinfo,
173
const struct pipe_draw_start_count_bias *draw,
174
struct d3d12_shader *shader,
175
uint32_t *values)
176
{
177
unsigned size = 0;
178
179
for (unsigned j = 0; j < shader->num_state_vars; ++j) {
180
uint32_t *ptr = values + size;
181
182
switch (shader->state_vars[j].var) {
183
case D3D12_STATE_VAR_Y_FLIP:
184
ptr[0] = fui(ctx->flip_y);
185
size += 4;
186
break;
187
case D3D12_STATE_VAR_PT_SPRITE:
188
ptr[0] = fui(1.0 / ctx->viewports[0].Width);
189
ptr[1] = fui(1.0 / ctx->viewports[0].Height);
190
ptr[2] = fui(ctx->gfx_pipeline_state.rast->base.point_size);
191
ptr[3] = fui(D3D12_MAX_POINT_SIZE);
192
size += 4;
193
break;
194
case D3D12_STATE_VAR_FIRST_VERTEX:
195
ptr[0] = dinfo->index_size ? draw->index_bias : draw->start;
196
size += 4;
197
break;
198
case D3D12_STATE_VAR_DEPTH_TRANSFORM:
199
ptr[0] = fui(2.0f * ctx->viewport_states[0].scale[2]);
200
ptr[1] = fui(ctx->viewport_states[0].translate[2] - ctx->viewport_states[0].scale[2]);
201
size += 4;
202
break;
203
default:
204
unreachable("unknown state variable");
205
}
206
}
207
208
return size;
209
}
210
211
static bool
212
check_descriptors_left(struct d3d12_context *ctx)
213
{
214
struct d3d12_batch *batch = d3d12_current_batch(ctx);
215
unsigned needed_descs = 0;
216
217
for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
218
struct d3d12_shader_selector *shader = ctx->gfx_stages[i];
219
220
if (!shader)
221
continue;
222
223
needed_descs += shader->current->num_cb_bindings;
224
needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;
225
}
226
227
if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs)
228
return false;
229
230
needed_descs = 0;
231
for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
232
struct d3d12_shader_selector *shader = ctx->gfx_stages[i];
233
234
if (!shader)
235
continue;
236
237
needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;
238
}
239
240
if (d3d12_descriptor_heap_get_remaining_handles(batch->sampler_heap) < needed_descs)
241
return false;
242
243
return true;
244
}
245
246
#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 3)
247
248
static unsigned
249
update_graphics_root_parameters(struct d3d12_context *ctx,
250
const struct pipe_draw_info *dinfo,
251
const struct pipe_draw_start_count_bias *draw,
252
D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],
253
int root_desc_indices[MAX_DESCRIPTOR_TABLES])
254
{
255
unsigned num_params = 0;
256
unsigned num_root_desciptors = 0;
257
258
for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
259
if (!ctx->gfx_stages[i])
260
continue;
261
262
struct d3d12_shader_selector *shader_sel = ctx->gfx_stages[i];
263
struct d3d12_shader *shader = shader_sel->current;
264
uint64_t dirty = ctx->shader_dirty[i];
265
assert(shader);
266
267
if (shader->num_cb_bindings > 0) {
268
if (dirty & D3D12_SHADER_DIRTY_CONSTBUF) {
269
assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);
270
root_desc_tables[num_root_desciptors] = fill_cbv_descriptors(ctx, shader, i);
271
root_desc_indices[num_root_desciptors++] = num_params;
272
}
273
num_params++;
274
}
275
if (shader->end_srv_binding > 0) {
276
if (dirty & D3D12_SHADER_DIRTY_SAMPLER_VIEWS) {
277
assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);
278
root_desc_tables[num_root_desciptors] = fill_srv_descriptors(ctx, shader, i);
279
root_desc_indices[num_root_desciptors++] = num_params;
280
}
281
num_params++;
282
if (dirty & D3D12_SHADER_DIRTY_SAMPLERS) {
283
assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);
284
root_desc_tables[num_root_desciptors] = fill_sampler_descriptors(ctx, shader_sel, i);
285
root_desc_indices[num_root_desciptors++] = num_params;
286
}
287
num_params++;
288
}
289
/* TODO Don't always update state vars */
290
if (shader->num_state_vars > 0) {
291
uint32_t constants[D3D12_MAX_STATE_VARS * 4];
292
unsigned size = fill_state_vars(ctx, dinfo, draw, shader, constants);
293
ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0);
294
num_params++;
295
}
296
}
297
return num_root_desciptors;
298
}
299
300
static bool
301
validate_stream_output_targets(struct d3d12_context *ctx)
302
{
303
unsigned factor = 0;
304
305
if (ctx->gfx_pipeline_state.num_so_targets &&
306
ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY])
307
factor = ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]->key.gs.stream_output_factor;
308
309
if (factor > 1)
310
return d3d12_enable_fake_so_buffers(ctx, factor);
311
else
312
return d3d12_disable_fake_so_buffers(ctx);
313
}
314
315
static D3D_PRIMITIVE_TOPOLOGY
316
topology(enum pipe_prim_type prim_type)
317
{
318
switch (prim_type) {
319
case PIPE_PRIM_POINTS:
320
return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
321
322
case PIPE_PRIM_LINES:
323
return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
324
325
case PIPE_PRIM_LINE_STRIP:
326
return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
327
328
case PIPE_PRIM_TRIANGLES:
329
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
330
331
case PIPE_PRIM_TRIANGLE_STRIP:
332
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
333
334
case PIPE_PRIM_LINES_ADJACENCY:
335
return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
336
337
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
338
return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;
339
340
case PIPE_PRIM_TRIANGLES_ADJACENCY:
341
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;
342
343
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
344
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;
345
346
/*
347
case PIPE_PRIM_PATCHES:
348
return D3D_PRIMITIVE_TOPOLOGY_PATCHLIST;
349
*/
350
351
case PIPE_PRIM_QUADS:
352
case PIPE_PRIM_QUAD_STRIP:
353
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; /* HACK: this is just wrong! */
354
355
default:
356
debug_printf("pipe_prim_type: %s\n", u_prim_name(prim_type));
357
unreachable("unexpected enum pipe_prim_type");
358
}
359
}
360
361
static DXGI_FORMAT
362
ib_format(unsigned index_size)
363
{
364
switch (index_size) {
365
case 1: return DXGI_FORMAT_R8_UINT;
366
case 2: return DXGI_FORMAT_R16_UINT;
367
case 4: return DXGI_FORMAT_R32_UINT;
368
369
default:
370
unreachable("unexpected index-buffer size");
371
}
372
}
373
374
static void
375
twoface_emulation(struct d3d12_context *ctx,
376
struct d3d12_rasterizer_state *rast,
377
const struct pipe_draw_info *dinfo,
378
const struct pipe_draw_start_count_bias *draw)
379
{
380
/* draw backfaces */
381
ctx->base.bind_rasterizer_state(&ctx->base, rast->twoface_back);
382
d3d12_draw_vbo(&ctx->base, dinfo, 0, NULL, draw, 1);
383
384
/* restore real state */
385
ctx->base.bind_rasterizer_state(&ctx->base, rast);
386
}
387
388
static void
389
transition_surface_subresources_state(struct d3d12_context *ctx,
390
struct pipe_surface *psurf,
391
struct pipe_resource *pres,
392
D3D12_RESOURCE_STATES state)
393
{
394
struct d3d12_resource *res = d3d12_resource(pres);
395
unsigned start_layer, num_layers;
396
if (!d3d12_subresource_id_uses_layer(res->base.target)) {
397
start_layer = 0;
398
num_layers = 1;
399
} else {
400
start_layer = psurf->u.tex.first_layer;
401
num_layers = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;
402
}
403
d3d12_transition_subresources_state(ctx, res,
404
psurf->u.tex.level, 1,
405
start_layer, num_layers,
406
d3d12_get_format_start_plane(psurf->format),
407
d3d12_get_format_num_planes(psurf->format),
408
state,
409
D3D12_BIND_INVALIDATE_FULL);
410
}
411
412
static bool
413
prim_supported(enum pipe_prim_type prim_type)
414
{
415
switch (prim_type) {
416
case PIPE_PRIM_POINTS:
417
case PIPE_PRIM_LINES:
418
case PIPE_PRIM_LINE_STRIP:
419
case PIPE_PRIM_TRIANGLES:
420
case PIPE_PRIM_TRIANGLE_STRIP:
421
case PIPE_PRIM_LINES_ADJACENCY:
422
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
423
case PIPE_PRIM_TRIANGLES_ADJACENCY:
424
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
425
return true;
426
427
default:
428
return false;
429
}
430
}
431
432
static inline struct d3d12_shader_selector *
433
d3d12_last_vertex_stage(struct d3d12_context *ctx)
434
{
435
struct d3d12_shader_selector *sel = ctx->gfx_stages[PIPE_SHADER_GEOMETRY];
436
if (!sel || sel->is_gs_variant)
437
sel = ctx->gfx_stages[PIPE_SHADER_VERTEX];
438
return sel;
439
}
440
441
void
442
d3d12_draw_vbo(struct pipe_context *pctx,
443
const struct pipe_draw_info *dinfo,
444
unsigned drawid_offset,
445
const struct pipe_draw_indirect_info *indirect,
446
const struct pipe_draw_start_count_bias *draws,
447
unsigned num_draws)
448
{
449
if (num_draws > 1) {
450
util_draw_multi(pctx, dinfo, drawid_offset, indirect, draws, num_draws);
451
return;
452
}
453
454
if (!indirect && (!draws[0].count || !dinfo->instance_count))
455
return;
456
457
struct d3d12_context *ctx = d3d12_context(pctx);
458
struct d3d12_screen *screen = d3d12_screen(pctx->screen);
459
struct d3d12_batch *batch;
460
struct pipe_resource *index_buffer = NULL;
461
unsigned index_offset = 0;
462
enum d3d12_surface_conversion_mode conversion_modes[PIPE_MAX_COLOR_BUFS] = {};
463
464
if (!prim_supported(dinfo->mode) ||
465
dinfo->index_size == 1 ||
466
(dinfo->primitive_restart && dinfo->restart_index != 0xffff &&
467
dinfo->restart_index != 0xffffffff)) {
468
469
if (!dinfo->primitive_restart &&
470
!u_trim_pipe_prim(dinfo->mode, (unsigned *)&draws[0].count))
471
return;
472
473
ctx->initial_api_prim = dinfo->mode;
474
util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base);
475
util_primconvert_draw_vbo(ctx->primconvert, dinfo, drawid_offset, indirect, draws, num_draws);
476
return;
477
}
478
479
for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
480
if (ctx->fb.cbufs[i]) {
481
struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
482
conversion_modes[i] = d3d12_surface_update_pre_draw(surface, d3d12_rtv_format(ctx, i));
483
if (conversion_modes[i] != D3D12_SURFACE_CONVERSION_NONE)
484
ctx->cmdlist_dirty |= D3D12_DIRTY_FRAMEBUFFER;
485
}
486
}
487
488
struct d3d12_rasterizer_state *rast = ctx->gfx_pipeline_state.rast;
489
if (rast->twoface_back) {
490
enum pipe_prim_type saved_mode = ctx->initial_api_prim;
491
twoface_emulation(ctx, rast, dinfo, &draws[0]);
492
ctx->initial_api_prim = saved_mode;
493
}
494
495
if (ctx->pstipple.enabled)
496
ctx->shader_dirty[PIPE_SHADER_FRAGMENT] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS |
497
D3D12_SHADER_DIRTY_SAMPLERS;
498
499
/* this should *really* be fixed at a higher level than here! */
500
enum pipe_prim_type reduced_prim = u_reduced_prim(dinfo->mode);
501
if (reduced_prim == PIPE_PRIM_TRIANGLES &&
502
ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_FRONT_AND_BACK)
503
return;
504
505
if (ctx->gfx_pipeline_state.prim_type != dinfo->mode) {
506
ctx->gfx_pipeline_state.prim_type = dinfo->mode;
507
ctx->state_dirty |= D3D12_DIRTY_PRIM_MODE;
508
}
509
510
d3d12_select_shader_variants(ctx, dinfo);
511
d3d12_validate_queries(ctx);
512
for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
513
struct d3d12_shader *shader = ctx->gfx_stages[i] ? ctx->gfx_stages[i]->current : NULL;
514
if (ctx->gfx_pipeline_state.stages[i] != shader) {
515
ctx->gfx_pipeline_state.stages[i] = shader;
516
ctx->state_dirty |= D3D12_DIRTY_SHADER;
517
}
518
}
519
520
/* Reset to an invalid value after it's been used */
521
ctx->initial_api_prim = PIPE_PRIM_MAX;
522
523
/* Copy the stream output info from the current vertex/geometry shader */
524
if (ctx->state_dirty & D3D12_DIRTY_SHADER) {
525
struct d3d12_shader_selector *sel = d3d12_last_vertex_stage(ctx);
526
if (sel) {
527
ctx->gfx_pipeline_state.so_info = sel->so_info;
528
} else {
529
memset(&ctx->gfx_pipeline_state.so_info, 0, sizeof(sel->so_info));
530
}
531
}
532
if (!validate_stream_output_targets(ctx)) {
533
debug_printf("validate_stream_output_targets() failed\n");
534
return;
535
}
536
537
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ib_strip_cut_value =
538
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
539
if (dinfo->index_size > 0) {
540
assert(dinfo->index_size != 1);
541
542
if (dinfo->has_user_indices) {
543
if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer,
544
&index_offset, 4)) {
545
debug_printf("util_upload_index_buffer() failed\n");
546
return;
547
}
548
} else {
549
index_buffer = dinfo->index.resource;
550
}
551
552
if (dinfo->primitive_restart) {
553
assert(dinfo->restart_index == 0xffff ||
554
dinfo->restart_index == 0xffffffff);
555
ib_strip_cut_value = dinfo->restart_index == 0xffff ?
556
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF :
557
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;
558
}
559
}
560
561
if (ctx->gfx_pipeline_state.ib_strip_cut_value != ib_strip_cut_value) {
562
ctx->gfx_pipeline_state.ib_strip_cut_value = ib_strip_cut_value;
563
ctx->state_dirty |= D3D12_DIRTY_STRIP_CUT_VALUE;
564
}
565
566
if (!ctx->gfx_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_SHADER) {
567
ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx);
568
if (ctx->gfx_pipeline_state.root_signature != root_signature) {
569
ctx->gfx_pipeline_state.root_signature = root_signature;
570
ctx->state_dirty |= D3D12_DIRTY_ROOT_SIGNATURE;
571
for (int i = 0; i < D3D12_GFX_SHADER_STAGES; ++i)
572
ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_ALL;
573
}
574
}
575
576
if (!ctx->current_pso || ctx->state_dirty & D3D12_DIRTY_PSO) {
577
ctx->current_pso = d3d12_get_gfx_pipeline_state(ctx);
578
assert(ctx->current_pso);
579
}
580
581
ctx->cmdlist_dirty |= ctx->state_dirty;
582
583
if (!check_descriptors_left(ctx))
584
d3d12_flush_cmdlist(ctx);
585
batch = d3d12_current_batch(ctx);
586
587
if (ctx->cmdlist_dirty & D3D12_DIRTY_ROOT_SIGNATURE) {
588
d3d12_batch_reference_object(batch, ctx->gfx_pipeline_state.root_signature);
589
ctx->cmdlist->SetGraphicsRootSignature(ctx->gfx_pipeline_state.root_signature);
590
}
591
592
if (ctx->cmdlist_dirty & D3D12_DIRTY_PSO) {
593
assert(ctx->current_pso);
594
d3d12_batch_reference_object(batch, ctx->current_pso);
595
ctx->cmdlist->SetPipelineState(ctx->current_pso);
596
}
597
598
D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES];
599
int root_desc_indices[MAX_DESCRIPTOR_TABLES];
600
unsigned num_root_desciptors = update_graphics_root_parameters(ctx, dinfo, &draws[0], root_desc_tables, root_desc_indices);
601
602
bool need_zero_one_depth_range = d3d12_need_zero_one_depth_range(ctx);
603
if (need_zero_one_depth_range != ctx->need_zero_one_depth_range) {
604
ctx->cmdlist_dirty |= D3D12_DIRTY_VIEWPORT;
605
ctx->need_zero_one_depth_range = need_zero_one_depth_range;
606
}
607
608
if (ctx->cmdlist_dirty & D3D12_DIRTY_VIEWPORT) {
609
if (ctx->need_zero_one_depth_range) {
610
D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS];
611
for (unsigned i = 0; i < ctx->num_viewports; ++i) {
612
viewports[i] = ctx->viewports[i];
613
viewports[i].MinDepth = 0.0f;
614
viewports[i].MaxDepth = 1.0f;
615
}
616
ctx->cmdlist->RSSetViewports(ctx->num_viewports, viewports);
617
} else
618
ctx->cmdlist->RSSetViewports(ctx->num_viewports, ctx->viewports);
619
}
620
621
if (ctx->cmdlist_dirty & D3D12_DIRTY_SCISSOR) {
622
if (ctx->gfx_pipeline_state.rast->base.scissor && ctx->num_viewports > 0)
623
ctx->cmdlist->RSSetScissorRects(ctx->num_viewports, ctx->scissors);
624
else
625
ctx->cmdlist->RSSetScissorRects(1, &MAX_SCISSOR);
626
}
627
628
if (ctx->cmdlist_dirty & D3D12_DIRTY_BLEND_COLOR) {
629
unsigned blend_factor_flags = ctx->gfx_pipeline_state.blend->blend_factor_flags;
630
if (blend_factor_flags & (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ANY)) {
631
ctx->cmdlist->OMSetBlendFactor(ctx->blend_factor);
632
} else if (blend_factor_flags & D3D12_BLEND_FACTOR_ALPHA) {
633
float alpha_const[4] = { ctx->blend_factor[3], ctx->blend_factor[3],
634
ctx->blend_factor[3], ctx->blend_factor[3] };
635
ctx->cmdlist->OMSetBlendFactor(alpha_const);
636
}
637
}
638
639
if (ctx->cmdlist_dirty & D3D12_DIRTY_STENCIL_REF)
640
ctx->cmdlist->OMSetStencilRef(ctx->stencil_ref.ref_value[0]);
641
642
if (ctx->cmdlist_dirty & D3D12_DIRTY_PRIM_MODE)
643
ctx->cmdlist->IASetPrimitiveTopology(topology(dinfo->mode));
644
645
for (unsigned i = 0; i < ctx->num_vbs; ++i) {
646
if (ctx->vbs[i].buffer.resource) {
647
struct d3d12_resource *res = d3d12_resource(ctx->vbs[i].buffer.resource);
648
d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE);
649
if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS)
650
d3d12_batch_reference_resource(batch, res);
651
}
652
}
653
if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS)
654
ctx->cmdlist->IASetVertexBuffers(0, ctx->num_vbs, ctx->vbvs);
655
656
if (index_buffer) {
657
D3D12_INDEX_BUFFER_VIEW ibv;
658
struct d3d12_resource *res = d3d12_resource(index_buffer);
659
ibv.BufferLocation = d3d12_resource_gpu_virtual_address(res) + index_offset;
660
ibv.SizeInBytes = res->base.width0 - index_offset;
661
ibv.Format = ib_format(dinfo->index_size);
662
d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_INDEX_BUFFER, D3D12_BIND_INVALIDATE_NONE);
663
if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER ||
664
memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) {
665
ctx->ibv = ibv;
666
d3d12_batch_reference_resource(batch, res);
667
ctx->cmdlist->IASetIndexBuffer(&ibv);
668
}
669
670
if (dinfo->has_user_indices)
671
pipe_resource_reference(&index_buffer, NULL);
672
}
673
674
if (ctx->cmdlist_dirty & D3D12_DIRTY_FRAMEBUFFER) {
675
D3D12_CPU_DESCRIPTOR_HANDLE render_targets[PIPE_MAX_COLOR_BUFS] = {};
676
D3D12_CPU_DESCRIPTOR_HANDLE *depth_desc = NULL, tmp_desc;
677
for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
678
if (ctx->fb.cbufs[i]) {
679
struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
680
render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i]);
681
d3d12_batch_reference_surface_texture(batch, surface);
682
} else
683
render_targets[i] = screen->null_rtv.cpu_handle;
684
}
685
if (ctx->fb.zsbuf) {
686
struct d3d12_surface *surface = d3d12_surface(ctx->fb.zsbuf);
687
tmp_desc = surface->desc_handle.cpu_handle;
688
d3d12_batch_reference_surface_texture(batch, surface);
689
depth_desc = &tmp_desc;
690
}
691
ctx->cmdlist->OMSetRenderTargets(ctx->fb.nr_cbufs, render_targets, FALSE, depth_desc);
692
}
693
694
struct pipe_stream_output_target **so_targets = ctx->fake_so_buffer_factor ? ctx->fake_so_targets
695
: ctx->so_targets;
696
D3D12_STREAM_OUTPUT_BUFFER_VIEW *so_buffer_views = ctx->fake_so_buffer_factor ? ctx->fake_so_buffer_views
697
: ctx->so_buffer_views;
698
for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) {
699
struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)so_targets[i];
700
701
if (!target)
702
continue;
703
704
struct d3d12_resource *so_buffer = d3d12_resource(target->base.buffer);
705
struct d3d12_resource *fill_buffer = d3d12_resource(target->fill_buffer);
706
707
d3d12_resource_make_writeable(pctx, target->base.buffer);
708
709
if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) {
710
d3d12_batch_reference_resource(batch, so_buffer);
711
d3d12_batch_reference_resource(batch, fill_buffer);
712
}
713
714
d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE);
715
d3d12_transition_resource_state(ctx, fill_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE);
716
}
717
if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT)
718
ctx->cmdlist->SOSetTargets(0, 4, so_buffer_views);
719
720
for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
721
struct pipe_surface *psurf = ctx->fb.cbufs[i];
722
if (!psurf)
723
continue;
724
725
struct pipe_resource *pres = conversion_modes[i] == D3D12_SURFACE_CONVERSION_BGRA_UINT ?
726
d3d12_surface(psurf)->rgba_texture : psurf->texture;
727
transition_surface_subresources_state(ctx, psurf, pres,
728
D3D12_RESOURCE_STATE_RENDER_TARGET);
729
}
730
if (ctx->fb.zsbuf) {
731
struct pipe_surface *psurf = ctx->fb.zsbuf;
732
transition_surface_subresources_state(ctx, psurf, psurf->texture,
733
D3D12_RESOURCE_STATE_DEPTH_WRITE);
734
}
735
736
d3d12_apply_resource_states(ctx);
737
738
for (unsigned i = 0; i < num_root_desciptors; ++i)
739
ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]);
740
741
if (dinfo->index_size > 0)
742
ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count,
743
draws[0].start, draws[0].index_bias,
744
dinfo->start_instance);
745
else
746
ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count,
747
draws[0].start, dinfo->start_instance);
748
749
ctx->state_dirty = 0;
750
751
if (index_buffer)
752
ctx->cmdlist_dirty = 0;
753
else
754
ctx->cmdlist_dirty &= D3D12_DIRTY_INDEX_BUFFER;
755
756
for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i)
757
ctx->shader_dirty[i] = 0;
758
759
for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
760
if (ctx->fb.cbufs[i]) {
761
struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
762
d3d12_surface_update_post_draw(surface, conversion_modes[i]);
763
}
764
}
765
}
766
767