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
fill_cbv_descriptors(struct d3d12_context * ctx,struct d3d12_shader * shader,int stage)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
fill_srv_descriptors(struct d3d12_context * ctx,struct d3d12_shader * shader,unsigned stage)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
fill_sampler_descriptors(struct d3d12_context * ctx,const struct d3d12_shader_selector * shader_sel,unsigned stage)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
fill_state_vars(struct d3d12_context * ctx,const struct pipe_draw_info * dinfo,const struct pipe_draw_start_count_bias * draw,struct d3d12_shader * shader,uint32_t * values)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
check_descriptors_left(struct d3d12_context * ctx)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
update_graphics_root_parameters(struct d3d12_context * ctx,const struct pipe_draw_info * dinfo,const struct pipe_draw_start_count_bias * draw,D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],int root_desc_indices[MAX_DESCRIPTOR_TABLES])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
validate_stream_output_targets(struct d3d12_context * ctx)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
topology(enum pipe_prim_type prim_type)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
ib_format(unsigned index_size)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
twoface_emulation(struct d3d12_context * ctx,struct d3d12_rasterizer_state * rast,const struct pipe_draw_info * dinfo,const struct pipe_draw_start_count_bias * draw)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
transition_surface_subresources_state(struct d3d12_context * ctx,struct pipe_surface * psurf,struct pipe_resource * pres,D3D12_RESOURCE_STATES state)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
prim_supported(enum pipe_prim_type prim_type)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 *
d3d12_last_vertex_stage(struct d3d12_context * ctx)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
d3d12_draw_vbo(struct pipe_context * pctx,const struct pipe_draw_info * dinfo,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)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((enum pipe_prim_type)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((enum pipe_prim_type)dinfo->mode, (unsigned *)&draws[0].count))
471          return;
472 
473       ctx->initial_api_prim = (enum pipe_prim_type)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((enum pipe_prim_type)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 = (enum pipe_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((enum pipe_prim_type)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