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
41extern "C" {
42#include "indices/u_primconvert.h"
43}
44
45static 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
50static D3D12_GPU_DESCRIPTOR_HANDLE
51fill_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
81static D3D12_GPU_DESCRIPTOR_HANDLE
82fill_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
134static D3D12_GPU_DESCRIPTOR_HANDLE
135fill_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
170static unsigned
171fill_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
211static bool
212check_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
248static unsigned
249update_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
300static bool
301validate_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
315static D3D_PRIMITIVE_TOPOLOGY
316topology(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
361static DXGI_FORMAT
362ib_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
374static void
375twoface_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
388static void
389transition_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
412static bool
413prim_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
432static inline struct d3d12_shader_selector *
433d3d12_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
441void
442d3d12_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