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