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