• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_cmd_signature.h"
25 #include "d3d12_compiler.h"
26 #include "d3d12_compute_transforms.h"
27 #include "d3d12_context.h"
28 #include "d3d12_format.h"
29 #include "d3d12_query.h"
30 #include "d3d12_resource.h"
31 #include "d3d12_root_signature.h"
32 #include "d3d12_screen.h"
33 #include "d3d12_surface.h"
34 
35 #include "util/u_debug.h"
36 #include "util/u_draw.h"
37 #include "util/u_helpers.h"
38 #include "util/u_inlines.h"
39 #include "util/u_prim.h"
40 #include "util/u_prim_restart.h"
41 #include "util/u_math.h"
42 
43 extern "C" {
44 #include "indices/u_primconvert.h"
45 }
46 
47 static const D3D12_RECT MAX_SCISSOR = { D3D12_VIEWPORT_BOUNDS_MIN,
48                                         D3D12_VIEWPORT_BOUNDS_MIN,
49                                         D3D12_VIEWPORT_BOUNDS_MAX,
50                                         D3D12_VIEWPORT_BOUNDS_MAX };
51 
52 static const D3D12_RECT MAX_SCISSOR_ARRAY[] = {
53    MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR,
54    MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR,
55    MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR,
56    MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR
57 };
58 static_assert(ARRAY_SIZE(MAX_SCISSOR_ARRAY) == PIPE_MAX_VIEWPORTS, "Wrong scissor count");
59 
60 static D3D12_GPU_DESCRIPTOR_HANDLE
fill_cbv_descriptors(struct d3d12_context * ctx,struct d3d12_shader * shader,int stage)61 fill_cbv_descriptors(struct d3d12_context *ctx,
62                      struct d3d12_shader *shader,
63                      int stage)
64 {
65    struct d3d12_batch *batch = d3d12_current_batch(ctx);
66    struct d3d12_descriptor_handle table_start;
67    d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
68 
69    for (unsigned i = 0; i < shader->num_cb_bindings; i++) {
70       unsigned binding = shader->cb_bindings[i].binding;
71       struct pipe_constant_buffer *buffer = &ctx->cbufs[stage][binding];
72 
73       D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {};
74       if (buffer && buffer->buffer) {
75          struct d3d12_resource *res = d3d12_resource(buffer->buffer);
76          d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
77          cbv_desc.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset;
78          cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16,
79             align(buffer->buffer_size, 256));
80          d3d12_batch_reference_resource(batch, res, false);
81       }
82 
83       struct d3d12_descriptor_handle handle;
84       d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle);
85       d3d12_screen(ctx->base.screen)->dev->CreateConstantBufferView(&cbv_desc, handle.cpu_handle);
86    }
87 
88    return table_start.gpu_handle;
89 }
90 
91 static D3D12_GPU_DESCRIPTOR_HANDLE
fill_srv_descriptors(struct d3d12_context * ctx,struct d3d12_shader * shader,unsigned stage)92 fill_srv_descriptors(struct d3d12_context *ctx,
93                      struct d3d12_shader *shader,
94                      unsigned stage)
95 {
96    struct d3d12_batch *batch = d3d12_current_batch(ctx);
97    struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
98    D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
99    struct d3d12_descriptor_handle table_start;
100 
101    d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
102 
103    for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)
104    {
105       struct d3d12_sampler_view *view;
106 
107       if (i == shader->pstipple_binding) {
108          view = (struct d3d12_sampler_view*)ctx->pstipple.sampler_view;
109       } else {
110          view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][i];
111       }
112 
113       unsigned desc_idx = i - shader->begin_srv_binding;
114       if (view != NULL) {
115          descs[desc_idx] = view->handle.cpu_handle;
116          d3d12_batch_reference_sampler_view(batch, view);
117 
118          struct d3d12_resource *res = d3d12_resource(view->base.texture);
119          /* If this is a buffer that's been replaced, re-create the descriptor */
120          if (view->texture_generation_id != res->generation_id) {
121             d3d12_init_sampler_view_descriptor(view);
122             view->texture_generation_id = res->generation_id;
123          }
124 
125          D3D12_RESOURCE_STATES state = (stage == PIPE_SHADER_FRAGMENT) ?
126                                        D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE :
127                                        D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
128          if (view->base.texture->target == PIPE_BUFFER) {
129             d3d12_transition_resource_state(ctx, d3d12_resource(view->base.texture),
130                                             state,
131                                             D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
132          } else {
133             d3d12_transition_subresources_state(ctx, d3d12_resource(view->base.texture),
134                                                 view->base.u.tex.first_level, view->mip_levels,
135                                                 view->base.u.tex.first_layer, view->array_size,
136                                                 d3d12_get_format_start_plane(view->base.format),
137                                                 d3d12_get_format_num_planes(view->base.format),
138                                                 state,
139                                                 D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
140          }
141       } else {
142          descs[desc_idx] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle;
143       }
144    }
145 
146    d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);
147 
148    return table_start.gpu_handle;
149 }
150 
151 static D3D12_GPU_DESCRIPTOR_HANDLE
fill_ssbo_descriptors(struct d3d12_context * ctx,const struct d3d12_shader * shader,int stage)152 fill_ssbo_descriptors(struct d3d12_context *ctx,
153                      const struct d3d12_shader *shader,
154                      int stage)
155 {
156    struct d3d12_batch *batch = d3d12_current_batch(ctx);
157    struct d3d12_descriptor_handle table_start;
158 
159    d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
160 
161    for (unsigned i = 0; i < shader->nir->info.num_ssbos; i++)
162    {
163       struct pipe_shader_buffer *view = &ctx->ssbo_views[stage][i];
164 
165       D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc;
166       uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
167       uav_desc.Format = DXGI_FORMAT_R32_TYPELESS;
168       uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
169       uav_desc.Buffer.StructureByteStride = 0;
170       uav_desc.Buffer.CounterOffsetInBytes = 0;
171       ID3D12Resource *d3d12_res = nullptr;
172       if (view->buffer) {
173          struct d3d12_resource *res = d3d12_resource(view->buffer);
174          uint64_t res_offset = 0;
175          d3d12_res = d3d12_resource_underlying(res, &res_offset);
176          d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
177          uav_desc.Buffer.FirstElement = (view->buffer_offset + res_offset) / 4;
178          uav_desc.Buffer.NumElements = DIV_ROUND_UP(view->buffer_size, 4);
179          d3d12_batch_reference_resource(batch, res, true);
180       }
181 
182       struct d3d12_descriptor_handle handle;
183       d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle);
184       d3d12_screen(ctx->base.screen)->dev->CreateUnorderedAccessView(d3d12_res, nullptr, &uav_desc, handle.cpu_handle);
185    }
186 
187    return table_start.gpu_handle;
188 }
189 
190 static D3D12_GPU_DESCRIPTOR_HANDLE
fill_sampler_descriptors(struct d3d12_context * ctx,const struct d3d12_shader_selector * shader_sel,unsigned stage)191 fill_sampler_descriptors(struct d3d12_context *ctx,
192                          const struct d3d12_shader_selector *shader_sel,
193                          unsigned stage)
194 {
195    const struct d3d12_shader *shader = shader_sel->current;
196    struct d3d12_batch *batch = d3d12_current_batch(ctx);
197    D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
198    struct d3d12_descriptor_handle table_start;
199 
200    d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start);
201 
202    for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)
203    {
204       struct d3d12_sampler_state *sampler;
205 
206       if (i == shader->pstipple_binding) {
207          sampler = ctx->pstipple.sampler_cso;
208       } else {
209          sampler = ctx->samplers[stage][i];
210       }
211 
212       unsigned desc_idx = i - shader->begin_srv_binding;
213       if (sampler != NULL) {
214          if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad)
215             descs[desc_idx] = sampler->handle_without_shadow.cpu_handle;
216          else
217             descs[desc_idx] = sampler->handle.cpu_handle;
218       } else
219          descs[desc_idx] = ctx->null_sampler.cpu_handle;
220    }
221 
222    d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);
223    return table_start.gpu_handle;
224 }
225 
226 static D3D12_UAV_DIMENSION
image_view_dimension(enum pipe_texture_target target)227 image_view_dimension(enum pipe_texture_target target)
228 {
229    switch (target) {
230    case PIPE_BUFFER: return D3D12_UAV_DIMENSION_BUFFER;
231    case PIPE_TEXTURE_1D: return D3D12_UAV_DIMENSION_TEXTURE1D;
232    case PIPE_TEXTURE_1D_ARRAY: return D3D12_UAV_DIMENSION_TEXTURE1DARRAY;
233    case PIPE_TEXTURE_RECT:
234    case PIPE_TEXTURE_2D:
235       return D3D12_UAV_DIMENSION_TEXTURE2D;
236    case PIPE_TEXTURE_2D_ARRAY:
237    case PIPE_TEXTURE_CUBE:
238    case PIPE_TEXTURE_CUBE_ARRAY:
239       return D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
240    case PIPE_TEXTURE_3D: return D3D12_UAV_DIMENSION_TEXTURE3D;
241    default:
242       unreachable("unexpected target");
243    }
244 }
245 
246 static D3D12_GPU_DESCRIPTOR_HANDLE
fill_image_descriptors(struct d3d12_context * ctx,const struct d3d12_shader * shader,int stage)247 fill_image_descriptors(struct d3d12_context *ctx,
248                        const struct d3d12_shader *shader,
249                        int stage)
250 {
251    struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
252    struct d3d12_batch *batch = d3d12_current_batch(ctx);
253    struct d3d12_descriptor_handle table_start;
254 
255    d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
256 
257    for (unsigned i = 0; i < shader->nir->info.num_images; i++)
258    {
259       struct pipe_image_view *view = &ctx->image_views[stage][i];
260 
261       if (view->resource) {
262          D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc;
263          struct d3d12_resource *res = d3d12_resource(view->resource);
264          uint64_t offset = 0;
265          ID3D12Resource *d3d12_res = d3d12_resource_underlying(res, &offset);
266 
267          enum pipe_format view_format = ctx->image_view_emulation_formats[stage][i];
268          if (view_format == PIPE_FORMAT_NONE)
269             view_format = view->format;
270          uav_desc.Format = d3d12_get_format(view_format);
271          uav_desc.ViewDimension = image_view_dimension(res->base.b.target);
272 
273          unsigned array_size = view->u.tex.last_layer - view->u.tex.first_layer + 1;
274          switch (uav_desc.ViewDimension) {
275          case D3D12_UAV_DIMENSION_TEXTURE1D:
276             if (view->u.tex.first_layer > 0)
277                debug_printf("D3D12: can't create 1D UAV from layer %d\n",
278                             view->u.tex.first_layer);
279             uav_desc.Texture1D.MipSlice = view->u.tex.level;
280             break;
281          case D3D12_UAV_DIMENSION_TEXTURE1DARRAY:
282             uav_desc.Texture1DArray.FirstArraySlice = view->u.tex.first_layer;
283             uav_desc.Texture1DArray.ArraySize = array_size;
284             uav_desc.Texture1DArray.MipSlice = view->u.tex.level;
285             break;
286          case D3D12_UAV_DIMENSION_TEXTURE2D:
287             if (view->u.tex.first_layer > 0)
288                debug_printf("D3D12: can't create 2D UAV from layer %d\n",
289                             view->u.tex.first_layer);
290             uav_desc.Texture2D.MipSlice = view->u.tex.level;
291             uav_desc.Texture2D.PlaneSlice = 0;
292             break;
293          case D3D12_UAV_DIMENSION_TEXTURE2DARRAY:
294             uav_desc.Texture2DArray.FirstArraySlice = view->u.tex.first_layer;
295             uav_desc.Texture2DArray.ArraySize = array_size;
296             uav_desc.Texture2DArray.MipSlice = view->u.tex.level;
297             uav_desc.Texture2DArray.PlaneSlice = 0;
298             break;
299          case D3D12_UAV_DIMENSION_TEXTURE3D:
300             uav_desc.Texture3D.MipSlice = view->u.tex.level;
301             uav_desc.Texture3D.FirstWSlice = view->u.tex.first_layer;
302             uav_desc.Texture3D.WSize = array_size;
303             break;
304          case D3D12_UAV_DIMENSION_BUFFER: {
305             uav_desc.Format = d3d12_get_format(shader->uav_bindings[i].format);
306             uint format_size = util_format_get_blocksize(shader->uav_bindings[i].format);
307             offset += view->u.buf.offset;
308             uav_desc.Buffer.CounterOffsetInBytes = 0;
309             uav_desc.Buffer.FirstElement = offset / format_size;
310             uav_desc.Buffer.NumElements = view->u.buf.size / format_size;
311             uav_desc.Buffer.StructureByteStride = 0;
312             uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
313             break;
314          }
315          default:
316             unreachable("Unexpected image view dimension");
317          }
318 
319          if (!batch->pending_memory_barrier) {
320             if (res->base.b.target == PIPE_BUFFER) {
321                d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
322             } else {
323                unsigned transition_first_layer = view->u.tex.first_layer;
324                unsigned transition_array_size = array_size;
325                if (res->base.b.target == PIPE_TEXTURE_3D) {
326                   transition_first_layer = 0;
327                   transition_array_size = 0;
328                }
329                d3d12_transition_subresources_state(ctx, res,
330                                                    view->u.tex.level, 1,
331                                                    transition_first_layer, transition_array_size,
332                                                    0, 1,
333                                                    D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
334                                                    D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
335             }
336          }
337          d3d12_batch_reference_resource(batch, res, true);
338 
339          struct d3d12_descriptor_handle handle;
340          d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle);
341          d3d12_screen(ctx->base.screen)->dev->CreateUnorderedAccessView(d3d12_res, nullptr, &uav_desc, handle.cpu_handle);
342       } else {
343          d3d12_descriptor_heap_append_handles(batch->view_heap, &screen->null_uavs[shader->uav_bindings[i].dimension].cpu_handle, 1);
344       }
345    }
346 
347    return table_start.gpu_handle;
348 }
349 
350 static unsigned
fill_graphics_state_vars(struct d3d12_context * ctx,const struct pipe_draw_info * dinfo,unsigned drawid,const struct pipe_draw_start_count_bias * draw,struct d3d12_shader * shader,uint32_t * values,struct d3d12_cmd_signature_key * cmd_sig_key)351 fill_graphics_state_vars(struct d3d12_context *ctx,
352                          const struct pipe_draw_info *dinfo,
353                          unsigned drawid,
354                          const struct pipe_draw_start_count_bias *draw,
355                          struct d3d12_shader *shader,
356                          uint32_t *values,
357                          struct d3d12_cmd_signature_key *cmd_sig_key)
358 {
359    unsigned size = 0;
360 
361    for (unsigned j = 0; j < shader->num_state_vars; ++j) {
362       uint32_t *ptr = values + size;
363 
364       switch (shader->state_vars[j].var) {
365       case D3D12_STATE_VAR_Y_FLIP:
366          ptr[0] = fui(ctx->flip_y);
367          size += 4;
368          break;
369       case D3D12_STATE_VAR_PT_SPRITE:
370          ptr[0] = fui(1.0 / ctx->viewports[0].Width);
371          ptr[1] = fui(1.0 / ctx->viewports[0].Height);
372          ptr[2] = fui(ctx->gfx_pipeline_state.rast->base.point_size);
373          ptr[3] = fui(D3D12_MAX_POINT_SIZE);
374          size += 4;
375          break;
376       case D3D12_STATE_VAR_DRAW_PARAMS:
377          ptr[0] = dinfo->index_size ? draw->index_bias : draw->start;
378          ptr[1] = dinfo->start_instance;
379          ptr[2] = drawid;
380          ptr[3] = dinfo->index_size ? -1 : 0;
381          cmd_sig_key->draw_or_dispatch_params = 1;
382          cmd_sig_key->root_sig = ctx->gfx_pipeline_state.root_signature;
383          cmd_sig_key->params_root_const_offset = size;
384          size += 4;
385          break;
386       case D3D12_STATE_VAR_DEPTH_TRANSFORM:
387          ptr[0] = fui(2.0f * ctx->viewport_states[0].scale[2]);
388          ptr[1] = fui(ctx->viewport_states[0].translate[2] - ctx->viewport_states[0].scale[2]);
389          size += 4;
390          break;
391       case D3D12_STATE_VAR_DEFAULT_INNER_TESS_LEVEL:
392          memcpy(ptr, ctx->default_inner_tess_factor, sizeof(ctx->default_inner_tess_factor));
393          size += 4;
394          break;
395       case D3D12_STATE_VAR_DEFAULT_OUTER_TESS_LEVEL:
396          memcpy(ptr, ctx->default_outer_tess_factor, sizeof(ctx->default_outer_tess_factor));
397          size += 4;
398          break;
399       case D3D12_STATE_VAR_PATCH_VERTICES_IN:
400          ptr[0] = ctx->patch_vertices;
401          size += 4;
402          break;
403       default:
404          unreachable("unknown state variable");
405       }
406    }
407 
408    return size;
409 }
410 
411 static unsigned
fill_compute_state_vars(struct d3d12_context * ctx,const struct pipe_grid_info * info,struct d3d12_shader * shader,uint32_t * values,struct d3d12_cmd_signature_key * cmd_sig_key)412 fill_compute_state_vars(struct d3d12_context *ctx,
413                         const struct pipe_grid_info *info,
414                         struct d3d12_shader *shader,
415                         uint32_t *values,
416                         struct d3d12_cmd_signature_key *cmd_sig_key)
417 {
418    unsigned size = 0;
419 
420    for (unsigned j = 0; j < shader->num_state_vars; ++j) {
421       uint32_t *ptr = values + size;
422 
423       switch (shader->state_vars[j].var) {
424       case D3D12_STATE_VAR_NUM_WORKGROUPS:
425          ptr[0] = info->grid[0];
426          ptr[1] = info->grid[1];
427          ptr[2] = info->grid[2];
428          cmd_sig_key->draw_or_dispatch_params = 1;
429          cmd_sig_key->root_sig = ctx->compute_pipeline_state.root_signature;
430          cmd_sig_key->params_root_const_offset = size;
431          size += 4;
432          break;
433       case D3D12_STATE_VAR_TRANSFORM_GENERIC0: {
434          unsigned idx = shader->state_vars[j].var - D3D12_STATE_VAR_TRANSFORM_GENERIC0;
435          ptr[0] = ctx->transform_state_vars[idx * 4];
436          ptr[1] = ctx->transform_state_vars[idx * 4 + 1];
437          ptr[2] = ctx->transform_state_vars[idx * 4 + 2];
438          ptr[3] = ctx->transform_state_vars[idx * 4 + 3];
439          size += 4;
440          break;
441       }
442       default:
443          unreachable("unknown state variable");
444       }
445    }
446 
447    return size;
448 }
449 
450 static bool
check_descriptors_left(struct d3d12_context * ctx,bool compute)451 check_descriptors_left(struct d3d12_context *ctx, bool compute)
452 {
453    struct d3d12_batch *batch = d3d12_current_batch(ctx);
454    unsigned needed_descs = 0;
455 
456    unsigned count = compute ? 1 : D3D12_GFX_SHADER_STAGES;
457    for (unsigned i = 0; i < count; ++i) {
458       struct d3d12_shader_selector *shader = compute ? ctx->compute_state : ctx->gfx_stages[i];
459 
460       if (!shader)
461          continue;
462 
463       needed_descs += shader->current->num_cb_bindings;
464       needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;
465       needed_descs += shader->current->nir->info.num_ssbos;
466       needed_descs += shader->current->nir->info.num_images;
467    }
468 
469    if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs)
470       return false;
471 
472    needed_descs = 0;
473    for (unsigned i = 0; i < count; ++i) {
474       struct d3d12_shader_selector *shader = compute ? ctx->compute_state : ctx->gfx_stages[i];
475 
476       if (!shader)
477          continue;
478 
479       needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;
480    }
481 
482    if (d3d12_descriptor_heap_get_remaining_handles(batch->sampler_heap) < needed_descs)
483       return false;
484 
485    return true;
486 }
487 
488 #define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 4)
489 
490 static void
update_shader_stage_root_parameters(struct d3d12_context * ctx,const struct d3d12_shader_selector * shader_sel,unsigned & num_params,unsigned & num_root_descriptors,D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],int root_desc_indices[MAX_DESCRIPTOR_TABLES])491 update_shader_stage_root_parameters(struct d3d12_context *ctx,
492                                     const struct d3d12_shader_selector *shader_sel,
493                                     unsigned &num_params,
494                                     unsigned &num_root_descriptors,
495                                     D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],
496                                     int root_desc_indices[MAX_DESCRIPTOR_TABLES])
497 {
498    auto stage = shader_sel->stage;
499    struct d3d12_shader *shader = shader_sel->current;
500    uint64_t dirty = ctx->shader_dirty[stage];
501    assert(shader);
502 
503    if (shader->num_cb_bindings > 0) {
504       if (dirty & D3D12_SHADER_DIRTY_CONSTBUF) {
505          assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES);
506          root_desc_tables[num_root_descriptors] = fill_cbv_descriptors(ctx, shader, stage);
507          root_desc_indices[num_root_descriptors++] = num_params;
508       }
509       num_params++;
510    }
511    if (shader->end_srv_binding > 0) {
512       if (dirty & D3D12_SHADER_DIRTY_SAMPLER_VIEWS) {
513          assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES);
514          root_desc_tables[num_root_descriptors] = fill_srv_descriptors(ctx, shader, stage);
515          root_desc_indices[num_root_descriptors++] = num_params;
516       }
517       num_params++;
518       if (dirty & D3D12_SHADER_DIRTY_SAMPLERS) {
519          assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES);
520          root_desc_tables[num_root_descriptors] = fill_sampler_descriptors(ctx, shader_sel, stage);
521          root_desc_indices[num_root_descriptors++] = num_params;
522       }
523       num_params++;
524    }
525    if (shader->nir->info.num_ssbos > 0) {
526       if (dirty & D3D12_SHADER_DIRTY_SSBO) {
527          assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES);
528          root_desc_tables[num_root_descriptors] = fill_ssbo_descriptors(ctx, shader, stage);
529          root_desc_indices[num_root_descriptors++] = num_params;
530       }
531       num_params++;
532    }
533    if (shader->nir->info.num_images > 0) {
534       if (dirty & D3D12_SHADER_DIRTY_IMAGE) {
535          assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES);
536          root_desc_tables[num_root_descriptors] = fill_image_descriptors(ctx, shader, stage);
537          root_desc_indices[num_root_descriptors++] = num_params;
538       }
539       num_params++;
540    }
541 }
542 
543 static unsigned
update_graphics_root_parameters(struct d3d12_context * ctx,const struct pipe_draw_info * dinfo,unsigned drawid,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],struct d3d12_cmd_signature_key * cmd_sig_key)544 update_graphics_root_parameters(struct d3d12_context *ctx,
545                                 const struct pipe_draw_info *dinfo,
546                                 unsigned drawid,
547                                 const struct pipe_draw_start_count_bias *draw,
548                                 D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],
549                                 int root_desc_indices[MAX_DESCRIPTOR_TABLES],
550                                 struct d3d12_cmd_signature_key *cmd_sig_key)
551 {
552    unsigned num_params = 0;
553    unsigned num_root_descriptors = 0;
554 
555    for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
556       struct d3d12_shader_selector *shader_sel = ctx->gfx_stages[i];
557       if (!shader_sel)
558          continue;
559 
560       update_shader_stage_root_parameters(ctx, shader_sel, num_params, num_root_descriptors, root_desc_tables, root_desc_indices);
561       /* TODO Don't always update state vars */
562       if (shader_sel->current->num_state_vars > 0) {
563          uint32_t constants[D3D12_MAX_GRAPHICS_STATE_VARS * 4];
564          unsigned size = fill_graphics_state_vars(ctx, dinfo, drawid, draw, shader_sel->current, constants, cmd_sig_key);
565          if (cmd_sig_key->draw_or_dispatch_params)
566             cmd_sig_key->params_root_const_param = num_params;
567          ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0);
568          num_params++;
569       }
570    }
571    return num_root_descriptors;
572 }
573 
574 static unsigned
update_compute_root_parameters(struct d3d12_context * ctx,const struct pipe_grid_info * info,D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],int root_desc_indices[MAX_DESCRIPTOR_TABLES],struct d3d12_cmd_signature_key * cmd_sig_key)575 update_compute_root_parameters(struct d3d12_context *ctx,
576                                const struct pipe_grid_info *info,
577                                D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],
578                                int root_desc_indices[MAX_DESCRIPTOR_TABLES],
579                                struct d3d12_cmd_signature_key *cmd_sig_key)
580 {
581    unsigned num_params = 0;
582    unsigned num_root_descriptors = 0;
583 
584    struct d3d12_shader_selector *shader_sel = ctx->compute_state;
585    if (shader_sel) {
586       update_shader_stage_root_parameters(ctx, shader_sel, num_params, num_root_descriptors, root_desc_tables, root_desc_indices);
587       /* TODO Don't always update state vars */
588       if (shader_sel->current->num_state_vars > 0) {
589          uint32_t constants[D3D12_MAX_COMPUTE_STATE_VARS * 4];
590          unsigned size = fill_compute_state_vars(ctx, info, shader_sel->current, constants, cmd_sig_key);
591          if (cmd_sig_key->draw_or_dispatch_params)
592             cmd_sig_key->params_root_const_param = num_params;
593          ctx->cmdlist->SetComputeRoot32BitConstants(num_params, size, constants, 0);
594          num_params++;
595       }
596    }
597    return num_root_descriptors;
598 }
599 
600 static bool
validate_stream_output_targets(struct d3d12_context * ctx)601 validate_stream_output_targets(struct d3d12_context *ctx)
602 {
603    unsigned factor = 0;
604 
605    if (ctx->gfx_pipeline_state.num_so_targets &&
606        ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY])
607       factor = ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]->key.gs.stream_output_factor;
608 
609    if (factor > 1)
610       return d3d12_enable_fake_so_buffers(ctx, factor);
611    else
612       return d3d12_disable_fake_so_buffers(ctx);
613 }
614 
615 static D3D_PRIMITIVE_TOPOLOGY
topology(enum pipe_prim_type prim_type,uint8_t patch_vertices)616 topology(enum pipe_prim_type prim_type, uint8_t patch_vertices)
617 {
618    switch (prim_type) {
619    case PIPE_PRIM_POINTS:
620       return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
621 
622    case PIPE_PRIM_LINES:
623       return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
624 
625    case PIPE_PRIM_LINE_STRIP:
626       return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
627 
628    case PIPE_PRIM_TRIANGLES:
629       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
630 
631    case PIPE_PRIM_TRIANGLE_STRIP:
632       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
633 
634    case PIPE_PRIM_LINES_ADJACENCY:
635       return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
636 
637    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
638       return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;
639 
640    case PIPE_PRIM_TRIANGLES_ADJACENCY:
641       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;
642 
643    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
644       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;
645 
646    case PIPE_PRIM_PATCHES:
647       return (D3D_PRIMITIVE_TOPOLOGY)(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + patch_vertices - 1);
648 
649    case PIPE_PRIM_QUADS:
650    case PIPE_PRIM_QUAD_STRIP:
651       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; /* HACK: this is just wrong! */
652 
653    default:
654       debug_printf("pipe_prim_type: %s\n", u_prim_name(prim_type));
655       unreachable("unexpected enum pipe_prim_type");
656    }
657 }
658 
659 static DXGI_FORMAT
ib_format(unsigned index_size)660 ib_format(unsigned index_size)
661 {
662    switch (index_size) {
663    case 1: return DXGI_FORMAT_R8_UINT;
664    case 2: return DXGI_FORMAT_R16_UINT;
665    case 4: return DXGI_FORMAT_R32_UINT;
666 
667    default:
668       unreachable("unexpected index-buffer size");
669    }
670 }
671 
672 static void
twoface_emulation(struct d3d12_context * ctx,struct d3d12_rasterizer_state * rast,const struct pipe_draw_info * dinfo,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draw)673 twoface_emulation(struct d3d12_context *ctx,
674                   struct d3d12_rasterizer_state *rast,
675                   const struct pipe_draw_info *dinfo,
676                   const struct pipe_draw_indirect_info *indirect,
677                   const struct pipe_draw_start_count_bias *draw)
678 {
679    /* draw backfaces */
680    ctx->base.bind_rasterizer_state(&ctx->base, rast->twoface_back);
681    d3d12_draw_vbo(&ctx->base, dinfo, 0, indirect, draw, 1);
682 
683    /* restore real state */
684    ctx->base.bind_rasterizer_state(&ctx->base, rast);
685 }
686 
687 static void
transition_surface_subresources_state(struct d3d12_context * ctx,struct pipe_surface * psurf,struct pipe_resource * pres,D3D12_RESOURCE_STATES state)688 transition_surface_subresources_state(struct d3d12_context *ctx,
689                                       struct pipe_surface *psurf,
690                                       struct pipe_resource *pres,
691                                       D3D12_RESOURCE_STATES state)
692 {
693    struct d3d12_resource *res = d3d12_resource(pres);
694    unsigned start_layer, num_layers;
695    if (!d3d12_subresource_id_uses_layer(res->base.b.target)) {
696       start_layer = 0;
697       num_layers = 1;
698    } else {
699       start_layer = psurf->u.tex.first_layer;
700       num_layers = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;
701    }
702    d3d12_transition_subresources_state(ctx, res,
703                                        psurf->u.tex.level, 1,
704                                        start_layer, num_layers,
705                                        d3d12_get_format_start_plane(psurf->format),
706                                        d3d12_get_format_num_planes(psurf->format),
707                                        state,
708                                        D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
709 }
710 
711 static bool
prim_supported(enum pipe_prim_type prim_type)712 prim_supported(enum pipe_prim_type prim_type)
713 {
714    switch (prim_type) {
715    case PIPE_PRIM_POINTS:
716    case PIPE_PRIM_LINES:
717    case PIPE_PRIM_LINE_STRIP:
718    case PIPE_PRIM_TRIANGLES:
719    case PIPE_PRIM_TRIANGLE_STRIP:
720    case PIPE_PRIM_LINES_ADJACENCY:
721    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
722    case PIPE_PRIM_TRIANGLES_ADJACENCY:
723    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
724    case PIPE_PRIM_PATCHES:
725       return true;
726 
727    default:
728       return false;
729    }
730 }
731 
732 static inline struct d3d12_shader_selector *
d3d12_last_vertex_stage(struct d3d12_context * ctx)733 d3d12_last_vertex_stage(struct d3d12_context *ctx)
734 {
735    struct d3d12_shader_selector *sel = ctx->gfx_stages[PIPE_SHADER_GEOMETRY];
736    if (!sel || sel->is_variant)
737       sel = ctx->gfx_stages[PIPE_SHADER_TESS_EVAL];
738    if (!sel)
739       sel = ctx->gfx_stages[PIPE_SHADER_VERTEX];
740    return sel;
741 }
742 
743 static bool
update_draw_indirect_with_sysvals(struct d3d12_context * ctx,const struct pipe_draw_info * dinfo,unsigned drawid,const struct pipe_draw_indirect_info ** indirect_inout,struct pipe_draw_indirect_info * indirect_out)744 update_draw_indirect_with_sysvals(struct d3d12_context *ctx,
745    const struct pipe_draw_info *dinfo,
746    unsigned drawid,
747    const struct pipe_draw_indirect_info **indirect_inout,
748    struct pipe_draw_indirect_info *indirect_out)
749 {
750    if (*indirect_inout == nullptr ||
751       ctx->gfx_stages[PIPE_SHADER_VERTEX] == nullptr)
752       return false;
753 
754    unsigned sysvals[] = {
755       SYSTEM_VALUE_VERTEX_ID_ZERO_BASE,
756       SYSTEM_VALUE_BASE_VERTEX,
757       SYSTEM_VALUE_FIRST_VERTEX,
758       SYSTEM_VALUE_BASE_INSTANCE,
759       SYSTEM_VALUE_DRAW_ID,
760    };
761    bool any = false;
762    for (unsigned sysval : sysvals) {
763       any |= (BITSET_TEST(ctx->gfx_stages[PIPE_SHADER_VERTEX]->initial->info.system_values_read, sysval));
764    }
765    if (!any)
766       return false;
767 
768    d3d12_compute_transform_save_restore save;
769    d3d12_save_compute_transform_state(ctx, &save);
770 
771    auto indirect_in = *indirect_inout;
772    *indirect_inout = indirect_out;
773 
774    d3d12_compute_transform_key key;
775    memset(&key, 0, sizeof(key));
776    key.type = d3d12_compute_transform_type::base_vertex;
777    key.base_vertex.indexed = dinfo->index_size > 0;
778    key.base_vertex.dynamic_count = indirect_in->indirect_draw_count != nullptr;
779    ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key));
780 
781    ctx->transform_state_vars[0] = indirect_in->stride;
782    ctx->transform_state_vars[1] = indirect_in->offset;
783    ctx->transform_state_vars[2] = drawid;
784 
785    if (indirect_in->indirect_draw_count) {
786       pipe_constant_buffer draw_count_cbuf;
787       draw_count_cbuf.buffer = indirect_in->indirect_draw_count;
788       draw_count_cbuf.buffer_offset = indirect_in->indirect_draw_count_offset;
789       draw_count_cbuf.buffer_size = 4;
790       draw_count_cbuf.user_buffer = nullptr;
791       ctx->base.set_constant_buffer(&ctx->base, PIPE_SHADER_COMPUTE, 1, false, &draw_count_cbuf);
792    }
793 
794    pipe_shader_buffer new_cs_ssbos[2];
795    new_cs_ssbos[0].buffer = indirect_in->buffer;
796    new_cs_ssbos[0].buffer_offset = 0;
797    new_cs_ssbos[0].buffer_size = indirect_in->buffer->width0;
798 
799    /* 4 additional uints for base vertex, base instance, draw ID, and a bool for indexed draw */
800    unsigned out_stride = sizeof(uint32_t) * ((key.base_vertex.indexed ? 5 : 4) + 4);
801    pipe_resource output_buf_templ = {};
802    output_buf_templ.target = PIPE_BUFFER;
803    output_buf_templ.width0 = out_stride * indirect_in->draw_count;
804    output_buf_templ.height0 = output_buf_templ.depth0 = output_buf_templ.array_size =
805       output_buf_templ.last_level = 1;
806    output_buf_templ.usage = PIPE_USAGE_DEFAULT;
807 
808    new_cs_ssbos[1].buffer = ctx->base.screen->resource_create(ctx->base.screen, &output_buf_templ);
809    new_cs_ssbos[1].buffer_offset = 0;
810    new_cs_ssbos[1].buffer_size = output_buf_templ.width0;
811    ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 2, new_cs_ssbos, 2);
812 
813    pipe_grid_info grid = {};
814    grid.block[0] = grid.block[1] = grid.block[2] = 1;
815    grid.grid[0] = indirect_in->draw_count;
816    grid.grid[1] = grid.grid[2] = 1;
817    ctx->base.launch_grid(&ctx->base, &grid);
818 
819    d3d12_restore_compute_transform_state(ctx, &save);
820 
821    *indirect_out = *indirect_in;
822    indirect_out->buffer = new_cs_ssbos[1].buffer;
823    indirect_out->offset = 0;
824    indirect_out->stride = out_stride;
825    return true;
826 }
827 
828 static bool
update_draw_auto(struct d3d12_context * ctx,const struct pipe_draw_indirect_info ** indirect_inout,struct pipe_draw_indirect_info * indirect_out)829 update_draw_auto(struct d3d12_context *ctx,
830    const struct pipe_draw_indirect_info **indirect_inout,
831    struct pipe_draw_indirect_info *indirect_out)
832 {
833    if (*indirect_inout == nullptr ||
834        (*indirect_inout)->count_from_stream_output == nullptr ||
835        ctx->gfx_stages[PIPE_SHADER_VERTEX] == nullptr)
836       return false;
837 
838    d3d12_compute_transform_save_restore save;
839    d3d12_save_compute_transform_state(ctx, &save);
840 
841    auto indirect_in = *indirect_inout;
842    *indirect_inout = indirect_out;
843 
844    d3d12_compute_transform_key key;
845    memset(&key, 0, sizeof(key));
846    key.type = d3d12_compute_transform_type::draw_auto;
847    ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key));
848 
849    auto so_arg = indirect_in->count_from_stream_output;
850    d3d12_stream_output_target *target = (d3d12_stream_output_target *)so_arg;
851 
852    ctx->transform_state_vars[0] = ctx->vbs[0].stride;
853    ctx->transform_state_vars[1] = ctx->vbs[0].buffer_offset - so_arg->buffer_offset;
854 
855    pipe_shader_buffer new_cs_ssbo;
856    new_cs_ssbo.buffer = target->fill_buffer;
857    new_cs_ssbo.buffer_offset = target->fill_buffer_offset;
858    new_cs_ssbo.buffer_size = target->fill_buffer->width0 - new_cs_ssbo.buffer_offset;
859    ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 1, &new_cs_ssbo, 1);
860 
861    pipe_grid_info grid = {};
862    grid.block[0] = grid.block[1] = grid.block[2] = 1;
863    grid.grid[0] = grid.grid[1] = grid.grid[2] = 1;
864    ctx->base.launch_grid(&ctx->base, &grid);
865 
866    d3d12_restore_compute_transform_state(ctx, &save);
867 
868    *indirect_out = *indirect_in;
869    pipe_resource_reference(&indirect_out->buffer, target->fill_buffer);
870    indirect_out->offset = target->fill_buffer_offset + 4;
871    indirect_out->stride = sizeof(D3D12_DRAW_ARGUMENTS);
872    indirect_out->count_from_stream_output = nullptr;
873    return true;
874 }
875 
876 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)877 d3d12_draw_vbo(struct pipe_context *pctx,
878                const struct pipe_draw_info *dinfo,
879                unsigned drawid_offset,
880                const struct pipe_draw_indirect_info *indirect,
881                const struct pipe_draw_start_count_bias *draws,
882                unsigned num_draws)
883 {
884    if (num_draws > 1) {
885       util_draw_multi(pctx, dinfo, drawid_offset, indirect, draws, num_draws);
886       return;
887    }
888 
889    if (!indirect && (!draws[0].count || !dinfo->instance_count))
890       return;
891 
892    struct d3d12_context *ctx = d3d12_context(pctx);
893    struct d3d12_screen *screen = d3d12_screen(pctx->screen);
894    struct d3d12_batch *batch;
895    struct pipe_resource *index_buffer = NULL;
896    unsigned index_offset = 0;
897    enum d3d12_surface_conversion_mode conversion_modes[PIPE_MAX_COLOR_BUFS] = {};
898    struct pipe_draw_indirect_info patched_indirect = {};
899 
900    if (!prim_supported((enum pipe_prim_type)dinfo->mode) ||
901        dinfo->index_size == 1 ||
902        (dinfo->primitive_restart && dinfo->restart_index != 0xffff &&
903         dinfo->restart_index != 0xffffffff)) {
904 
905       if (!dinfo->primitive_restart &&
906           !indirect &&
907           !u_trim_pipe_prim((enum pipe_prim_type)dinfo->mode, (unsigned *)&draws[0].count))
908          return;
909 
910       ctx->initial_api_prim = (enum pipe_prim_type)dinfo->mode;
911       util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base);
912       util_primconvert_draw_vbo(ctx->primconvert, dinfo, drawid_offset, indirect, draws, num_draws);
913       return;
914    }
915 
916    bool draw_auto = update_draw_auto(ctx, &indirect, &patched_indirect);
917    bool indirect_with_sysvals = !draw_auto && update_draw_indirect_with_sysvals(ctx, dinfo, drawid_offset, &indirect, &patched_indirect);
918    struct d3d12_cmd_signature_key cmd_sig_key;
919    memset(&cmd_sig_key, 0, sizeof(cmd_sig_key));
920 
921    if (indirect) {
922       cmd_sig_key.compute = false;
923       cmd_sig_key.indexed = dinfo->index_size > 0;
924       if (indirect->draw_count > 1 ||
925           indirect->indirect_draw_count ||
926           indirect_with_sysvals)
927          cmd_sig_key.multi_draw_stride = indirect->stride;
928       else if (cmd_sig_key.indexed)
929          cmd_sig_key.multi_draw_stride = sizeof(D3D12_DRAW_INDEXED_ARGUMENTS);
930       else
931          cmd_sig_key.multi_draw_stride = sizeof(D3D12_DRAW_ARGUMENTS);
932    }
933 
934    for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
935       if (ctx->fb.cbufs[i]) {
936          struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
937          conversion_modes[i] = d3d12_surface_update_pre_draw(pctx, surface, d3d12_rtv_format(ctx, i));
938          if (conversion_modes[i] != D3D12_SURFACE_CONVERSION_NONE)
939             ctx->cmdlist_dirty |= D3D12_DIRTY_FRAMEBUFFER;
940       }
941    }
942 
943    struct d3d12_rasterizer_state *rast = ctx->gfx_pipeline_state.rast;
944    if (rast->twoface_back) {
945       enum pipe_prim_type saved_mode = ctx->initial_api_prim;
946       twoface_emulation(ctx, rast, dinfo, indirect, &draws[0]);
947       ctx->initial_api_prim = saved_mode;
948    }
949 
950    if (ctx->pstipple.enabled && ctx->gfx_pipeline_state.rast->base.poly_stipple_enable)
951       ctx->shader_dirty[PIPE_SHADER_FRAGMENT] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS |
952                                                  D3D12_SHADER_DIRTY_SAMPLERS;
953 
954    /* this should *really* be fixed at a higher level than here! */
955    enum pipe_prim_type reduced_prim = u_reduced_prim((enum pipe_prim_type)dinfo->mode);
956    if (reduced_prim == PIPE_PRIM_TRIANGLES &&
957        ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_FRONT_AND_BACK)
958       return;
959 
960    if (ctx->gfx_pipeline_state.prim_type != dinfo->mode) {
961       ctx->gfx_pipeline_state.prim_type = (enum pipe_prim_type)dinfo->mode;
962       ctx->state_dirty |= D3D12_DIRTY_PRIM_MODE;
963    }
964 
965    d3d12_select_shader_variants(ctx, dinfo);
966    d3d12_validate_queries(ctx);
967    for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
968       struct d3d12_shader *shader = ctx->gfx_stages[i] ? ctx->gfx_stages[i]->current : NULL;
969       if (ctx->gfx_pipeline_state.stages[i] != shader) {
970          ctx->gfx_pipeline_state.stages[i] = shader;
971          ctx->state_dirty |= D3D12_DIRTY_SHADER;
972       }
973    }
974 
975    /* Reset to an invalid value after it's been used */
976    ctx->initial_api_prim = PIPE_PRIM_MAX;
977 
978    /* Copy the stream output info from the current vertex/geometry shader */
979    if (ctx->state_dirty & D3D12_DIRTY_SHADER) {
980       struct d3d12_shader_selector *sel = d3d12_last_vertex_stage(ctx);
981       if (sel) {
982          ctx->gfx_pipeline_state.so_info = sel->so_info;
983       } else {
984          memset(&ctx->gfx_pipeline_state.so_info, 0, sizeof(sel->so_info));
985       }
986    }
987    if (!validate_stream_output_targets(ctx)) {
988       debug_printf("validate_stream_output_targets() failed\n");
989       return;
990    }
991 
992    D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ib_strip_cut_value =
993       D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
994    if (dinfo->index_size > 0) {
995       assert(dinfo->index_size != 1);
996 
997       if (dinfo->has_user_indices) {
998          if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer,
999              &index_offset, 4)) {
1000             debug_printf("util_upload_index_buffer() failed\n");
1001             return;
1002          }
1003       } else {
1004          index_buffer = dinfo->index.resource;
1005       }
1006 
1007       if (dinfo->primitive_restart) {
1008          assert(dinfo->restart_index == 0xffff ||
1009                 dinfo->restart_index == 0xffffffff);
1010          ib_strip_cut_value = dinfo->restart_index == 0xffff ?
1011             D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF :
1012             D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;
1013       }
1014    }
1015 
1016    if (ctx->gfx_pipeline_state.ib_strip_cut_value != ib_strip_cut_value) {
1017       ctx->gfx_pipeline_state.ib_strip_cut_value = ib_strip_cut_value;
1018       ctx->state_dirty |= D3D12_DIRTY_STRIP_CUT_VALUE;
1019    }
1020 
1021    if (!ctx->gfx_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_SHADER) {
1022       ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx, false);
1023       if (ctx->gfx_pipeline_state.root_signature != root_signature) {
1024          ctx->gfx_pipeline_state.root_signature = root_signature;
1025          ctx->state_dirty |= D3D12_DIRTY_ROOT_SIGNATURE;
1026          for (int i = 0; i < D3D12_GFX_SHADER_STAGES; ++i)
1027             ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_ALL;
1028       }
1029    }
1030 
1031    if (!ctx->current_gfx_pso || ctx->state_dirty & D3D12_DIRTY_GFX_PSO) {
1032       ctx->current_gfx_pso = d3d12_get_gfx_pipeline_state(ctx);
1033       assert(ctx->current_gfx_pso);
1034    }
1035 
1036    ctx->cmdlist_dirty |= ctx->state_dirty;
1037 
1038    if (!check_descriptors_left(ctx, false))
1039       d3d12_flush_cmdlist(ctx);
1040    batch = d3d12_current_batch(ctx);
1041 
1042    if (ctx->cmdlist_dirty & D3D12_DIRTY_ROOT_SIGNATURE) {
1043       d3d12_batch_reference_object(batch, ctx->gfx_pipeline_state.root_signature);
1044       ctx->cmdlist->SetGraphicsRootSignature(ctx->gfx_pipeline_state.root_signature);
1045    }
1046 
1047    if (ctx->cmdlist_dirty & D3D12_DIRTY_GFX_PSO) {
1048       assert(ctx->current_gfx_pso);
1049       d3d12_batch_reference_object(batch, ctx->current_gfx_pso);
1050       ctx->cmdlist->SetPipelineState(ctx->current_gfx_pso);
1051    }
1052 
1053    D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES];
1054    int root_desc_indices[MAX_DESCRIPTOR_TABLES];
1055    unsigned num_root_descriptors = update_graphics_root_parameters(ctx, dinfo, drawid_offset, &draws[0],
1056       root_desc_tables, root_desc_indices, &cmd_sig_key);
1057 
1058    bool need_zero_one_depth_range = d3d12_need_zero_one_depth_range(ctx);
1059    if (need_zero_one_depth_range != ctx->need_zero_one_depth_range) {
1060       ctx->cmdlist_dirty |= D3D12_DIRTY_VIEWPORT;
1061       ctx->need_zero_one_depth_range = need_zero_one_depth_range;
1062    }
1063 
1064    if (ctx->cmdlist_dirty & D3D12_DIRTY_VIEWPORT) {
1065       D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS];
1066       for (unsigned i = 0; i < ctx->num_viewports; ++i) {
1067          viewports[i] = ctx->viewports[i];
1068          if (ctx->need_zero_one_depth_range) {
1069             viewports[i].MinDepth = 0.0f;
1070             viewports[i].MaxDepth = 1.0f;
1071          }
1072          if (ctx->fb.nr_cbufs == 0 && !ctx->fb.zsbuf) {
1073             viewports[i].TopLeftX = MAX2(0.0f, viewports[i].TopLeftX);
1074             viewports[i].TopLeftY = MAX2(0.0f, viewports[i].TopLeftY);
1075             viewports[i].Width = MIN2(ctx->fb.width, viewports[i].Width);
1076             viewports[i].Height = MIN2(ctx->fb.height, viewports[i].Height);
1077          }
1078       }
1079       ctx->cmdlist->RSSetViewports(ctx->num_viewports, viewports);
1080    }
1081 
1082    if (ctx->cmdlist_dirty & D3D12_DIRTY_SCISSOR) {
1083       if (ctx->gfx_pipeline_state.rast->base.scissor && ctx->num_viewports > 0)
1084          ctx->cmdlist->RSSetScissorRects(ctx->num_viewports, ctx->scissors);
1085       else
1086          ctx->cmdlist->RSSetScissorRects(PIPE_MAX_VIEWPORTS, MAX_SCISSOR_ARRAY);
1087    }
1088 
1089    if (ctx->cmdlist_dirty & D3D12_DIRTY_BLEND_COLOR) {
1090       unsigned blend_factor_flags = ctx->gfx_pipeline_state.blend->blend_factor_flags;
1091       if (blend_factor_flags & (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ANY)) {
1092          ctx->cmdlist->OMSetBlendFactor(ctx->blend_factor);
1093       } else if (blend_factor_flags & D3D12_BLEND_FACTOR_ALPHA) {
1094          float alpha_const[4] = { ctx->blend_factor[3], ctx->blend_factor[3],
1095                                  ctx->blend_factor[3], ctx->blend_factor[3] };
1096          ctx->cmdlist->OMSetBlendFactor(alpha_const);
1097       }
1098    }
1099 
1100    if (ctx->cmdlist_dirty & D3D12_DIRTY_STENCIL_REF)
1101       ctx->cmdlist->OMSetStencilRef(ctx->stencil_ref.ref_value[0]);
1102 
1103    if (ctx->cmdlist_dirty & D3D12_DIRTY_PRIM_MODE)
1104       ctx->cmdlist->IASetPrimitiveTopology(topology((enum pipe_prim_type)dinfo->mode, ctx->patch_vertices));
1105 
1106    for (unsigned i = 0; i < ctx->num_vbs; ++i) {
1107       if (ctx->vbs[i].buffer.resource) {
1108          struct d3d12_resource *res = d3d12_resource(ctx->vbs[i].buffer.resource);
1109          d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
1110          if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS)
1111             d3d12_batch_reference_resource(batch, res, false);
1112       }
1113    }
1114    if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS)
1115       ctx->cmdlist->IASetVertexBuffers(0, ctx->num_vbs, ctx->vbvs);
1116 
1117    if (index_buffer) {
1118       D3D12_INDEX_BUFFER_VIEW ibv;
1119       struct d3d12_resource *res = d3d12_resource(index_buffer);
1120       ibv.BufferLocation = d3d12_resource_gpu_virtual_address(res) + index_offset;
1121       ibv.SizeInBytes = res->base.b.width0 - index_offset;
1122       ibv.Format = ib_format(dinfo->index_size);
1123       d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_INDEX_BUFFER, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
1124       if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER ||
1125           memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) {
1126          ctx->ibv = ibv;
1127          d3d12_batch_reference_resource(batch, res, false);
1128          ctx->cmdlist->IASetIndexBuffer(&ibv);
1129       }
1130 
1131       if (dinfo->has_user_indices)
1132          pipe_resource_reference(&index_buffer, NULL);
1133    }
1134 
1135    if (ctx->cmdlist_dirty & D3D12_DIRTY_FRAMEBUFFER) {
1136       D3D12_CPU_DESCRIPTOR_HANDLE render_targets[PIPE_MAX_COLOR_BUFS] = {};
1137       D3D12_CPU_DESCRIPTOR_HANDLE *depth_desc = NULL, tmp_desc;
1138       for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
1139          if (ctx->fb.cbufs[i]) {
1140             struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
1141             render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i]);
1142             d3d12_batch_reference_surface_texture(batch, surface);
1143          } else
1144             render_targets[i] = screen->null_rtv.cpu_handle;
1145       }
1146       if (ctx->fb.zsbuf) {
1147          struct d3d12_surface *surface = d3d12_surface(ctx->fb.zsbuf);
1148          tmp_desc = surface->desc_handle.cpu_handle;
1149          d3d12_batch_reference_surface_texture(batch, surface);
1150          depth_desc = &tmp_desc;
1151       }
1152       ctx->cmdlist->OMSetRenderTargets(ctx->fb.nr_cbufs, render_targets, FALSE, depth_desc);
1153    }
1154 
1155    struct pipe_stream_output_target **so_targets = ctx->fake_so_buffer_factor ? ctx->fake_so_targets
1156                                                                               : ctx->so_targets;
1157    D3D12_STREAM_OUTPUT_BUFFER_VIEW *so_buffer_views = ctx->fake_so_buffer_factor ? ctx->fake_so_buffer_views
1158                                                                                  : ctx->so_buffer_views;
1159    for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) {
1160       struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)so_targets[i];
1161 
1162       if (!target)
1163          continue;
1164 
1165       struct d3d12_resource *so_buffer = d3d12_resource(target->base.buffer);
1166       struct d3d12_resource *fill_buffer = d3d12_resource(target->fill_buffer);
1167 
1168       if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) {
1169          d3d12_batch_reference_resource(batch, so_buffer, true);
1170          d3d12_batch_reference_resource(batch, fill_buffer, true);
1171       }
1172 
1173       d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
1174       d3d12_transition_resource_state(ctx, fill_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
1175    }
1176    if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT)
1177       ctx->cmdlist->SOSetTargets(0, 4, so_buffer_views);
1178 
1179    for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
1180       struct pipe_surface *psurf = ctx->fb.cbufs[i];
1181       if (!psurf)
1182          continue;
1183 
1184       struct pipe_resource *pres = conversion_modes[i] == D3D12_SURFACE_CONVERSION_BGRA_UINT ?
1185                                       d3d12_surface(psurf)->rgba_texture : psurf->texture;
1186       transition_surface_subresources_state(ctx, psurf, pres,
1187          D3D12_RESOURCE_STATE_RENDER_TARGET);
1188    }
1189    if (ctx->fb.zsbuf) {
1190       struct pipe_surface *psurf = ctx->fb.zsbuf;
1191       transition_surface_subresources_state(ctx, psurf, psurf->texture,
1192          D3D12_RESOURCE_STATE_DEPTH_WRITE);
1193    }
1194 
1195    ID3D12Resource *indirect_arg_buf = nullptr;
1196    ID3D12Resource *indirect_count_buf = nullptr;
1197    uint64_t indirect_arg_offset = 0, indirect_count_offset = 0;
1198    if (indirect) {
1199       if (indirect->buffer) {
1200          struct d3d12_resource *indirect_buf = d3d12_resource(indirect->buffer);
1201          uint64_t buf_offset = 0;
1202          indirect_arg_buf = d3d12_resource_underlying(indirect_buf, &buf_offset);
1203          indirect_arg_offset = indirect->offset + buf_offset;
1204          d3d12_transition_resource_state(ctx, indirect_buf,
1205             D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
1206          d3d12_batch_reference_resource(batch, indirect_buf, false);
1207       }
1208       if (indirect->indirect_draw_count) {
1209          struct d3d12_resource *count_buf = d3d12_resource(indirect->indirect_draw_count);
1210          uint64_t count_offset = 0;
1211          indirect_count_buf = d3d12_resource_underlying(count_buf, &count_offset);
1212          indirect_count_offset = indirect->indirect_draw_count_offset + count_offset;
1213          d3d12_transition_resource_state(ctx, count_buf,
1214             D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
1215          d3d12_batch_reference_resource(batch, count_buf, false);
1216       }
1217       assert(!indirect->count_from_stream_output);
1218    }
1219 
1220    d3d12_apply_resource_states(ctx, false);
1221 
1222    for (unsigned i = 0; i < num_root_descriptors; ++i)
1223       ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]);
1224 
1225    if (indirect) {
1226       unsigned draw_count = draw_auto ? 1 : indirect->draw_count;
1227       ID3D12CommandSignature *cmd_sig = d3d12_get_cmd_signature(ctx, &cmd_sig_key);
1228       ctx->cmdlist->ExecuteIndirect(cmd_sig, draw_count, indirect_arg_buf,
1229          indirect_arg_offset, indirect_count_buf, indirect_count_offset);
1230    } else {
1231       if (dinfo->index_size > 0)
1232          ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count,
1233                                             draws[0].start, draws[0].index_bias,
1234                                             dinfo->start_instance);
1235       else
1236          ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count,
1237                                      draws[0].start, dinfo->start_instance);
1238    }
1239 
1240    ctx->state_dirty &= D3D12_DIRTY_COMPUTE_MASK;
1241    batch->pending_memory_barrier = false;
1242 
1243    ctx->cmdlist_dirty &= D3D12_DIRTY_COMPUTE_MASK |
1244       (index_buffer ? 0 : D3D12_DIRTY_INDEX_BUFFER);
1245 
1246    /* The next dispatch needs to reassert the compute PSO */
1247    ctx->cmdlist_dirty |= D3D12_DIRTY_COMPUTE_SHADER;
1248 
1249    for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i)
1250       ctx->shader_dirty[i] = 0;
1251 
1252    for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
1253       if (ctx->fb.cbufs[i]) {
1254          struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
1255          d3d12_surface_update_post_draw(pctx, surface, conversion_modes[i]);
1256       }
1257    }
1258 
1259    pipe_resource_reference(&patched_indirect.buffer, NULL);
1260 }
1261 
1262 static bool
update_dispatch_indirect_with_sysvals(struct d3d12_context * ctx,struct pipe_resource ** indirect_inout,unsigned * indirect_offset_inout,struct pipe_resource ** indirect_out)1263 update_dispatch_indirect_with_sysvals(struct d3d12_context *ctx,
1264                                       struct pipe_resource **indirect_inout,
1265                                       unsigned *indirect_offset_inout,
1266                                       struct pipe_resource **indirect_out)
1267 {
1268    if (*indirect_inout == nullptr ||
1269        ctx->compute_state == nullptr)
1270       return false;
1271 
1272    if (!BITSET_TEST(ctx->compute_state->current->nir->info.system_values_read, SYSTEM_VALUE_NUM_WORKGROUPS))
1273       return false;
1274 
1275    if (ctx->current_predication)
1276       ctx->cmdlist->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
1277 
1278    auto indirect_in = *indirect_inout;
1279 
1280    /* 6 uints: 2 copies of the indirect arg buffer */
1281    pipe_resource output_buf_templ = {};
1282    output_buf_templ.target = PIPE_BUFFER;
1283    output_buf_templ.width0 = sizeof(uint32_t) * 6;
1284    output_buf_templ.height0 = output_buf_templ.depth0 = output_buf_templ.array_size =
1285       output_buf_templ.last_level = 1;
1286    output_buf_templ.usage = PIPE_USAGE_DEFAULT;
1287    *indirect_out = ctx->base.screen->resource_create(ctx->base.screen, &output_buf_templ);
1288 
1289    struct pipe_box src_box = { (int)*indirect_offset_inout, 0, 0, sizeof(uint32_t) * 3, 1, 1 };
1290    ctx->base.resource_copy_region(&ctx->base, *indirect_out, 0, 0, 0, 0, indirect_in, 0, &src_box);
1291    ctx->base.resource_copy_region(&ctx->base, *indirect_out, 0, src_box.width, 0, 0, indirect_in, 0, &src_box);
1292 
1293    if (ctx->current_predication)
1294       d3d12_enable_predication(ctx);
1295 
1296    *indirect_inout = *indirect_out;
1297    *indirect_offset_inout = 0;
1298    return true;
1299 }
1300 
1301 void
d3d12_launch_grid(struct pipe_context * pctx,const struct pipe_grid_info * info)1302 d3d12_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
1303 {
1304    struct d3d12_context *ctx = d3d12_context(pctx);
1305    struct d3d12_batch *batch;
1306    struct pipe_resource *patched_indirect = nullptr;
1307 
1308    struct d3d12_cmd_signature_key cmd_sig_key;
1309    memset(&cmd_sig_key, 0, sizeof(cmd_sig_key));
1310    cmd_sig_key.compute = 1;
1311    cmd_sig_key.multi_draw_stride = sizeof(D3D12_DISPATCH_ARGUMENTS);
1312 
1313    struct pipe_resource *indirect = info->indirect;
1314    unsigned indirect_offset = info->indirect_offset;
1315    if (indirect && update_dispatch_indirect_with_sysvals(ctx, &indirect, &indirect_offset, &patched_indirect))
1316       cmd_sig_key.multi_draw_stride = sizeof(D3D12_DISPATCH_ARGUMENTS) * 2;
1317 
1318    d3d12_select_compute_shader_variants(ctx, info);
1319    d3d12_validate_queries(ctx);
1320    struct d3d12_shader *shader = ctx->compute_state ? ctx->compute_state->current : NULL;
1321    if (ctx->compute_pipeline_state.stage != shader) {
1322       ctx->compute_pipeline_state.stage = shader;
1323       ctx->state_dirty |= D3D12_DIRTY_COMPUTE_SHADER;
1324    }
1325 
1326    if (!ctx->compute_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_COMPUTE_SHADER) {
1327       ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx, true);
1328       if (ctx->compute_pipeline_state.root_signature != root_signature) {
1329          ctx->compute_pipeline_state.root_signature = root_signature;
1330          ctx->state_dirty |= D3D12_DIRTY_COMPUTE_ROOT_SIGNATURE;
1331          ctx->shader_dirty[PIPE_SHADER_COMPUTE] |= D3D12_SHADER_DIRTY_ALL;
1332       }
1333    }
1334 
1335    if (!ctx->current_compute_pso || ctx->state_dirty & D3D12_DIRTY_COMPUTE_PSO) {
1336       ctx->current_compute_pso = d3d12_get_compute_pipeline_state(ctx);
1337       assert(ctx->current_compute_pso);
1338    }
1339 
1340    ctx->cmdlist_dirty |= ctx->state_dirty;
1341 
1342    if (!check_descriptors_left(ctx, true))
1343       d3d12_flush_cmdlist(ctx);
1344    batch = d3d12_current_batch(ctx);
1345 
1346    if (ctx->cmdlist_dirty & D3D12_DIRTY_COMPUTE_ROOT_SIGNATURE) {
1347       d3d12_batch_reference_object(batch, ctx->compute_pipeline_state.root_signature);
1348       ctx->cmdlist->SetComputeRootSignature(ctx->compute_pipeline_state.root_signature);
1349    }
1350 
1351    if (ctx->cmdlist_dirty & D3D12_DIRTY_COMPUTE_PSO) {
1352       assert(ctx->current_compute_pso);
1353       d3d12_batch_reference_object(batch, ctx->current_compute_pso);
1354       ctx->cmdlist->SetPipelineState(ctx->current_compute_pso);
1355    }
1356 
1357    D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES];
1358    int root_desc_indices[MAX_DESCRIPTOR_TABLES];
1359    unsigned num_root_descriptors = update_compute_root_parameters(ctx, info, root_desc_tables, root_desc_indices, &cmd_sig_key);
1360 
1361    ID3D12Resource *indirect_arg_buf = nullptr;
1362    uint64_t indirect_arg_offset = 0;
1363    if (indirect) {
1364       struct d3d12_resource *indirect_buf = d3d12_resource(indirect);
1365       uint64_t buf_offset = 0;
1366       indirect_arg_buf = d3d12_resource_underlying(indirect_buf, &buf_offset);
1367       indirect_arg_offset = indirect_offset + buf_offset;
1368       d3d12_transition_resource_state(ctx, indirect_buf,
1369          D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE);
1370       d3d12_batch_reference_resource(batch, indirect_buf, false);
1371    }
1372 
1373    d3d12_apply_resource_states(ctx, ctx->compute_state->is_variant);
1374 
1375    for (unsigned i = 0; i < num_root_descriptors; ++i)
1376       ctx->cmdlist->SetComputeRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]);
1377 
1378    if (indirect) {
1379       ID3D12CommandSignature *cmd_sig = d3d12_get_cmd_signature(ctx, &cmd_sig_key);
1380       ctx->cmdlist->ExecuteIndirect(cmd_sig, 1, indirect_arg_buf, indirect_arg_offset, nullptr, 0);
1381    } else {
1382       ctx->cmdlist->Dispatch(info->grid[0], info->grid[1], info->grid[2]);
1383    }
1384 
1385    ctx->state_dirty &= D3D12_DIRTY_GFX_MASK;
1386    ctx->cmdlist_dirty &= D3D12_DIRTY_GFX_MASK;
1387 
1388    /* The next draw needs to reassert the graphics PSO */
1389    ctx->cmdlist_dirty |= D3D12_DIRTY_SHADER;
1390    batch->pending_memory_barrier = false;
1391 
1392    ctx->shader_dirty[PIPE_SHADER_COMPUTE] = 0;
1393    pipe_resource_reference(&patched_indirect, nullptr);
1394 }
1395