1/*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include <assert.h>
25#include <stdbool.h>
26#include <string.h>
27#include <unistd.h>
28#include <fcntl.h>
29
30#include "anv_private.h"
31#include "anv_measure.h"
32
33#include "vk_util.h"
34
35/** \file anv_cmd_buffer.c
36 *
37 * This file contains all of the stuff for emitting commands into a command
38 * buffer.  This includes implementations of most of the vkCmd*
39 * entrypoints.  This file is concerned entirely with state emission and
40 * not with the command buffer data structure itself.  As far as this file
41 * is concerned, most of anv_cmd_buffer is magic.
42 */
43
44/* TODO: These are taken from GLES.  We should check the Vulkan spec */
45const struct anv_dynamic_state default_dynamic_state = {
46   .viewport = {
47      .count = 0,
48   },
49   .scissor = {
50      .count = 0,
51   },
52   .line_width = 1.0f,
53   .depth_bias = {
54      .bias = 0.0f,
55      .clamp = 0.0f,
56      .slope = 0.0f,
57   },
58   .blend_constants = { 0.0f, 0.0f, 0.0f, 0.0f },
59   .depth_bounds = {
60      .min = 0.0f,
61      .max = 1.0f,
62   },
63   .stencil_compare_mask = {
64      .front = ~0u,
65      .back = ~0u,
66   },
67   .stencil_write_mask = {
68      .front = ~0u,
69      .back = ~0u,
70   },
71   .stencil_reference = {
72      .front = 0u,
73      .back = 0u,
74   },
75   .stencil_op = {
76      .front = {
77         .fail_op = 0,
78         .pass_op = 0,
79         .depth_fail_op = 0,
80         .compare_op = 0,
81      },
82      .back = {
83         .fail_op = 0,
84         .pass_op = 0,
85         .depth_fail_op = 0,
86         .compare_op = 0,
87      },
88   },
89   .line_stipple = {
90      .factor = 0u,
91      .pattern = 0u,
92   },
93   .cull_mode = 0,
94   .front_face = 0,
95   .primitive_topology = 0,
96   .depth_test_enable = 0,
97   .depth_write_enable = 0,
98   .depth_compare_op = 0,
99   .depth_bounds_test_enable = 0,
100   .stencil_test_enable = 0,
101   .dyn_vbo_stride = 0,
102   .dyn_vbo_size = 0,
103   .color_writes = 0xff,
104   .raster_discard = 0,
105   .depth_bias_enable = 0,
106   .primitive_restart_enable = 0,
107   .logic_op = 0,
108};
109
110/**
111 * Copy the dynamic state from src to dest based on the copy_mask.
112 *
113 * Avoid copying states that have not changed, except for VIEWPORT, SCISSOR and
114 * BLEND_CONSTANTS (always copy them if they are in the copy_mask).
115 *
116 * Returns a mask of the states which changed.
117 */
118anv_cmd_dirty_mask_t
119anv_dynamic_state_copy(struct anv_dynamic_state *dest,
120                       const struct anv_dynamic_state *src,
121                       anv_cmd_dirty_mask_t copy_mask)
122{
123   anv_cmd_dirty_mask_t changed = 0;
124
125   if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_VIEWPORT) {
126      dest->viewport.count = src->viewport.count;
127      typed_memcpy(dest->viewport.viewports, src->viewport.viewports,
128                   src->viewport.count);
129      changed |= ANV_CMD_DIRTY_DYNAMIC_VIEWPORT;
130   }
131
132   if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_SCISSOR) {
133      dest->scissor.count = src->scissor.count;
134      typed_memcpy(dest->scissor.scissors, src->scissor.scissors,
135                   src->scissor.count);
136      changed |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR;
137   }
138
139   if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS) {
140      typed_memcpy(dest->blend_constants, src->blend_constants, 4);
141      changed |= ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS;
142   }
143
144#define ANV_CMP_COPY(field, flag)                                 \
145   if (copy_mask & flag) {                                        \
146      if (dest->field != src->field) {                            \
147         dest->field = src->field;                                \
148         changed |= flag;                                         \
149      }                                                           \
150   }
151
152   ANV_CMP_COPY(line_width, ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH);
153
154   ANV_CMP_COPY(depth_bias.bias, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS);
155   ANV_CMP_COPY(depth_bias.clamp, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS);
156   ANV_CMP_COPY(depth_bias.slope, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS);
157
158   ANV_CMP_COPY(depth_bounds.min, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS);
159   ANV_CMP_COPY(depth_bounds.max, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS);
160
161   ANV_CMP_COPY(stencil_compare_mask.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK);
162   ANV_CMP_COPY(stencil_compare_mask.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK);
163
164   ANV_CMP_COPY(stencil_write_mask.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK);
165   ANV_CMP_COPY(stencil_write_mask.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK);
166
167   ANV_CMP_COPY(stencil_reference.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE);
168   ANV_CMP_COPY(stencil_reference.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE);
169
170   ANV_CMP_COPY(line_stipple.factor, ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE);
171   ANV_CMP_COPY(line_stipple.pattern, ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE);
172
173   ANV_CMP_COPY(cull_mode, ANV_CMD_DIRTY_DYNAMIC_CULL_MODE);
174   ANV_CMP_COPY(front_face, ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE);
175   ANV_CMP_COPY(primitive_topology, ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY);
176   ANV_CMP_COPY(depth_test_enable, ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE);
177   ANV_CMP_COPY(depth_write_enable, ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE);
178   ANV_CMP_COPY(depth_compare_op, ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP);
179   ANV_CMP_COPY(depth_bounds_test_enable, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE);
180   ANV_CMP_COPY(stencil_test_enable, ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE);
181
182   if (copy_mask & VK_DYNAMIC_STATE_STENCIL_OP_EXT) {
183      ANV_CMP_COPY(stencil_op.front.fail_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP);
184      ANV_CMP_COPY(stencil_op.front.pass_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP);
185      ANV_CMP_COPY(stencil_op.front.depth_fail_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP);
186      ANV_CMP_COPY(stencil_op.front.compare_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP);
187      ANV_CMP_COPY(stencil_op.back.fail_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP);
188      ANV_CMP_COPY(stencil_op.back.pass_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP);
189      ANV_CMP_COPY(stencil_op.back.depth_fail_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP);
190      ANV_CMP_COPY(stencil_op.back.compare_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP);
191   }
192
193   ANV_CMP_COPY(dyn_vbo_stride, ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE);
194   ANV_CMP_COPY(dyn_vbo_size, ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE);
195
196   ANV_CMP_COPY(raster_discard, ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
197   ANV_CMP_COPY(depth_bias_enable, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE);
198   ANV_CMP_COPY(primitive_restart_enable, ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE);
199   ANV_CMP_COPY(logic_op, ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP);
200
201   if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
202      dest->sample_locations.samples = src->sample_locations.samples;
203      typed_memcpy(dest->sample_locations.locations,
204                   src->sample_locations.locations,
205                   dest->sample_locations.samples);
206      changed |= ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS;
207   }
208
209   ANV_CMP_COPY(color_writes, ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE);
210
211   ANV_CMP_COPY(fragment_shading_rate.width, ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE);
212   ANV_CMP_COPY(fragment_shading_rate.height, ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE);
213
214#undef ANV_CMP_COPY
215
216   return changed;
217}
218
219static void
220anv_cmd_state_init(struct anv_cmd_buffer *cmd_buffer)
221{
222   struct anv_cmd_state *state = &cmd_buffer->state;
223
224   memset(state, 0, sizeof(*state));
225
226   state->current_pipeline = UINT32_MAX;
227   state->restart_index = UINT32_MAX;
228   state->gfx.dynamic = default_dynamic_state;
229}
230
231static void
232anv_cmd_pipeline_state_finish(struct anv_cmd_buffer *cmd_buffer,
233                              struct anv_cmd_pipeline_state *pipe_state)
234{
235   for (uint32_t i = 0; i < ARRAY_SIZE(pipe_state->push_descriptors); i++) {
236      if (pipe_state->push_descriptors[i]) {
237         anv_descriptor_set_layout_unref(cmd_buffer->device,
238             pipe_state->push_descriptors[i]->set.layout);
239         vk_free(&cmd_buffer->pool->alloc, pipe_state->push_descriptors[i]);
240      }
241   }
242}
243
244static void
245anv_cmd_state_finish(struct anv_cmd_buffer *cmd_buffer)
246{
247   struct anv_cmd_state *state = &cmd_buffer->state;
248
249   anv_cmd_pipeline_state_finish(cmd_buffer, &state->gfx.base);
250   anv_cmd_pipeline_state_finish(cmd_buffer, &state->compute.base);
251
252   vk_free(&cmd_buffer->pool->alloc, state->attachments);
253}
254
255static void
256anv_cmd_state_reset(struct anv_cmd_buffer *cmd_buffer)
257{
258   anv_cmd_state_finish(cmd_buffer);
259   anv_cmd_state_init(cmd_buffer);
260}
261
262static VkResult anv_create_cmd_buffer(
263    struct anv_device *                         device,
264    struct anv_cmd_pool *                       pool,
265    VkCommandBufferLevel                        level,
266    VkCommandBuffer*                            pCommandBuffer)
267{
268   struct anv_cmd_buffer *cmd_buffer;
269   VkResult result;
270
271   cmd_buffer = vk_alloc2(&device->vk.alloc, &pool->alloc, sizeof(*cmd_buffer),
272                          8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
273   if (cmd_buffer == NULL)
274      return vk_error(pool, VK_ERROR_OUT_OF_HOST_MEMORY);
275
276   result = vk_command_buffer_init(&cmd_buffer->vk, &device->vk);
277   if (result != VK_SUCCESS)
278      goto fail_alloc;
279
280   cmd_buffer->batch.status = VK_SUCCESS;
281
282   cmd_buffer->device = device;
283   cmd_buffer->pool = pool;
284   cmd_buffer->level = level;
285
286   result = anv_cmd_buffer_init_batch_bo_chain(cmd_buffer);
287   if (result != VK_SUCCESS)
288      goto fail_vk;
289
290   anv_state_stream_init(&cmd_buffer->surface_state_stream,
291                         &device->surface_state_pool, 4096);
292   anv_state_stream_init(&cmd_buffer->dynamic_state_stream,
293                         &device->dynamic_state_pool, 16384);
294   anv_state_stream_init(&cmd_buffer->general_state_stream,
295                         &device->general_state_pool, 16384);
296
297   cmd_buffer->self_mod_locations = NULL;
298
299   anv_cmd_state_init(cmd_buffer);
300
301   list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers);
302
303   anv_measure_init(cmd_buffer);
304
305   *pCommandBuffer = anv_cmd_buffer_to_handle(cmd_buffer);
306
307   return VK_SUCCESS;
308
309 fail_vk:
310   vk_command_buffer_finish(&cmd_buffer->vk);
311 fail_alloc:
312   vk_free2(&device->vk.alloc, &pool->alloc, cmd_buffer);
313
314   return result;
315}
316
317VkResult anv_AllocateCommandBuffers(
318    VkDevice                                    _device,
319    const VkCommandBufferAllocateInfo*          pAllocateInfo,
320    VkCommandBuffer*                            pCommandBuffers)
321{
322   ANV_FROM_HANDLE(anv_device, device, _device);
323   ANV_FROM_HANDLE(anv_cmd_pool, pool, pAllocateInfo->commandPool);
324
325   VkResult result = VK_SUCCESS;
326   uint32_t i;
327
328   for (i = 0; i < pAllocateInfo->commandBufferCount; i++) {
329      result = anv_create_cmd_buffer(device, pool, pAllocateInfo->level,
330                                     &pCommandBuffers[i]);
331      if (result != VK_SUCCESS)
332         break;
333   }
334
335   if (result != VK_SUCCESS) {
336      anv_FreeCommandBuffers(_device, pAllocateInfo->commandPool,
337                             i, pCommandBuffers);
338      for (i = 0; i < pAllocateInfo->commandBufferCount; i++)
339         pCommandBuffers[i] = VK_NULL_HANDLE;
340   }
341
342   return result;
343}
344
345static void
346anv_cmd_buffer_destroy(struct anv_cmd_buffer *cmd_buffer)
347{
348   anv_measure_destroy(cmd_buffer);
349
350   list_del(&cmd_buffer->pool_link);
351
352   anv_cmd_buffer_fini_batch_bo_chain(cmd_buffer);
353
354   anv_state_stream_finish(&cmd_buffer->surface_state_stream);
355   anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
356   anv_state_stream_finish(&cmd_buffer->general_state_stream);
357
358   anv_cmd_state_finish(cmd_buffer);
359
360   vk_free(&cmd_buffer->pool->alloc, cmd_buffer->self_mod_locations);
361
362   vk_command_buffer_finish(&cmd_buffer->vk);
363   vk_free2(&cmd_buffer->device->vk.alloc, &cmd_buffer->pool->alloc,
364            cmd_buffer);
365}
366
367void anv_FreeCommandBuffers(
368    VkDevice                                    device,
369    VkCommandPool                               commandPool,
370    uint32_t                                    commandBufferCount,
371    const VkCommandBuffer*                      pCommandBuffers)
372{
373   for (uint32_t i = 0; i < commandBufferCount; i++) {
374      ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, pCommandBuffers[i]);
375
376      if (!cmd_buffer)
377         continue;
378
379      anv_cmd_buffer_destroy(cmd_buffer);
380   }
381}
382
383VkResult
384anv_cmd_buffer_reset(struct anv_cmd_buffer *cmd_buffer)
385{
386   vk_command_buffer_reset(&cmd_buffer->vk);
387
388   cmd_buffer->usage_flags = 0;
389   cmd_buffer->perf_query_pool = NULL;
390   anv_cmd_buffer_reset_batch_bo_chain(cmd_buffer);
391   anv_cmd_state_reset(cmd_buffer);
392
393   anv_state_stream_finish(&cmd_buffer->surface_state_stream);
394   anv_state_stream_init(&cmd_buffer->surface_state_stream,
395                         &cmd_buffer->device->surface_state_pool, 4096);
396
397   anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
398   anv_state_stream_init(&cmd_buffer->dynamic_state_stream,
399                         &cmd_buffer->device->dynamic_state_pool, 16384);
400
401   anv_state_stream_finish(&cmd_buffer->general_state_stream);
402   anv_state_stream_init(&cmd_buffer->general_state_stream,
403                         &cmd_buffer->device->general_state_pool, 16384);
404
405   anv_measure_reset(cmd_buffer);
406   return VK_SUCCESS;
407}
408
409VkResult anv_ResetCommandBuffer(
410    VkCommandBuffer                             commandBuffer,
411    VkCommandBufferResetFlags                   flags)
412{
413   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
414   return anv_cmd_buffer_reset(cmd_buffer);
415}
416
417void
418anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer)
419{
420   const struct intel_device_info *devinfo = &cmd_buffer->device->info;
421   anv_genX(devinfo, cmd_buffer_emit_state_base_address)(cmd_buffer);
422}
423
424void
425anv_cmd_buffer_mark_image_written(struct anv_cmd_buffer *cmd_buffer,
426                                  const struct anv_image *image,
427                                  VkImageAspectFlagBits aspect,
428                                  enum isl_aux_usage aux_usage,
429                                  uint32_t level,
430                                  uint32_t base_layer,
431                                  uint32_t layer_count)
432{
433   const struct intel_device_info *devinfo = &cmd_buffer->device->info;
434   anv_genX(devinfo, cmd_buffer_mark_image_written)(cmd_buffer, image,
435                                                    aspect, aux_usage,
436                                                    level, base_layer,
437                                                    layer_count);
438}
439
440void
441anv_cmd_emit_conditional_render_predicate(struct anv_cmd_buffer *cmd_buffer)
442{
443   const struct intel_device_info *devinfo = &cmd_buffer->device->info;
444   anv_genX(devinfo, cmd_emit_conditional_render_predicate)(cmd_buffer);
445}
446
447static bool
448mem_update(void *dst, const void *src, size_t size)
449{
450   if (memcmp(dst, src, size) == 0)
451      return false;
452
453   memcpy(dst, src, size);
454   return true;
455}
456
457static void
458set_dirty_for_bind_map(struct anv_cmd_buffer *cmd_buffer,
459                       gl_shader_stage stage,
460                       const struct anv_pipeline_bind_map *map)
461{
462   assert(stage < ARRAY_SIZE(cmd_buffer->state.surface_sha1s));
463   if (mem_update(cmd_buffer->state.surface_sha1s[stage],
464                  map->surface_sha1, sizeof(map->surface_sha1)))
465      cmd_buffer->state.descriptors_dirty |= mesa_to_vk_shader_stage(stage);
466
467   assert(stage < ARRAY_SIZE(cmd_buffer->state.sampler_sha1s));
468   if (mem_update(cmd_buffer->state.sampler_sha1s[stage],
469                  map->sampler_sha1, sizeof(map->sampler_sha1)))
470      cmd_buffer->state.descriptors_dirty |= mesa_to_vk_shader_stage(stage);
471
472   assert(stage < ARRAY_SIZE(cmd_buffer->state.push_sha1s));
473   if (mem_update(cmd_buffer->state.push_sha1s[stage],
474                  map->push_sha1, sizeof(map->push_sha1)))
475      cmd_buffer->state.push_constants_dirty |= mesa_to_vk_shader_stage(stage);
476}
477
478void anv_CmdBindPipeline(
479    VkCommandBuffer                             commandBuffer,
480    VkPipelineBindPoint                         pipelineBindPoint,
481    VkPipeline                                  _pipeline)
482{
483   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
484   ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
485
486   switch (pipelineBindPoint) {
487   case VK_PIPELINE_BIND_POINT_COMPUTE: {
488      struct anv_compute_pipeline *compute_pipeline =
489         anv_pipeline_to_compute(pipeline);
490      if (cmd_buffer->state.compute.pipeline == compute_pipeline)
491         return;
492
493      cmd_buffer->state.compute.pipeline = compute_pipeline;
494      cmd_buffer->state.compute.pipeline_dirty = true;
495      set_dirty_for_bind_map(cmd_buffer, MESA_SHADER_COMPUTE,
496                             &compute_pipeline->cs->bind_map);
497      break;
498   }
499
500   case VK_PIPELINE_BIND_POINT_GRAPHICS: {
501      struct anv_graphics_pipeline *gfx_pipeline =
502         anv_pipeline_to_graphics(pipeline);
503      if (cmd_buffer->state.gfx.pipeline == gfx_pipeline)
504         return;
505
506      cmd_buffer->state.gfx.pipeline = gfx_pipeline;
507      cmd_buffer->state.gfx.vb_dirty |= gfx_pipeline->vb_used;
508      cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_PIPELINE;
509
510      anv_foreach_stage(stage, gfx_pipeline->active_stages) {
511         set_dirty_for_bind_map(cmd_buffer, stage,
512                                &gfx_pipeline->shaders[stage]->bind_map);
513      }
514
515      /* Apply the dynamic state from the pipeline */
516      cmd_buffer->state.gfx.dirty |=
517         anv_dynamic_state_copy(&cmd_buffer->state.gfx.dynamic,
518                                &gfx_pipeline->dynamic_state,
519                                gfx_pipeline->dynamic_state_mask);
520      break;
521   }
522
523   case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR: {
524      struct anv_ray_tracing_pipeline *rt_pipeline =
525         anv_pipeline_to_ray_tracing(pipeline);
526      if (cmd_buffer->state.rt.pipeline == rt_pipeline)
527         return;
528
529      cmd_buffer->state.rt.pipeline = rt_pipeline;
530      cmd_buffer->state.rt.pipeline_dirty = true;
531
532      if (rt_pipeline->stack_size > 0) {
533         anv_CmdSetRayTracingPipelineStackSizeKHR(commandBuffer,
534                                                  rt_pipeline->stack_size);
535      }
536      break;
537   }
538
539   default:
540      assert(!"invalid bind point");
541      break;
542   }
543}
544
545void anv_CmdSetRasterizerDiscardEnableEXT(
546    VkCommandBuffer                             commandBuffer,
547    VkBool32                                    rasterizerDiscardEnable)
548{
549   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
550
551   cmd_buffer->state.gfx.dynamic.raster_discard = rasterizerDiscardEnable;
552
553   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE;
554}
555
556void anv_CmdSetDepthBiasEnableEXT(
557    VkCommandBuffer                             commandBuffer,
558    VkBool32                                    depthBiasEnable)
559{
560   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
561
562   cmd_buffer->state.gfx.dynamic.depth_bias_enable = depthBiasEnable;
563
564   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE;
565}
566
567void anv_CmdSetPrimitiveRestartEnableEXT(
568    VkCommandBuffer                             commandBuffer,
569    VkBool32                                    primitiveRestartEnable)
570{
571   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
572
573   cmd_buffer->state.gfx.dynamic.primitive_restart_enable = primitiveRestartEnable;
574
575   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE;
576}
577
578void anv_CmdSetLogicOpEXT(
579   VkCommandBuffer                              commandBuffer,
580    VkLogicOp                                   logicOp)
581{
582   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
583
584   cmd_buffer->state.gfx.dynamic.logic_op = logicOp;
585
586   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP;
587}
588
589void anv_CmdSetPatchControlPointsEXT(
590    VkCommandBuffer                             commandBuffer,
591    uint32_t                                    patchControlPoints)
592{
593   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
594   anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_FEATURE_NOT_PRESENT);
595}
596
597void anv_CmdSetViewport(
598    VkCommandBuffer                             commandBuffer,
599    uint32_t                                    firstViewport,
600    uint32_t                                    viewportCount,
601    const VkViewport*                           pViewports)
602{
603   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
604
605   const uint32_t total_count = firstViewport + viewportCount;
606   if (cmd_buffer->state.gfx.dynamic.viewport.count < total_count)
607      cmd_buffer->state.gfx.dynamic.viewport.count = total_count;
608
609   memcpy(cmd_buffer->state.gfx.dynamic.viewport.viewports + firstViewport,
610          pViewports, viewportCount * sizeof(*pViewports));
611
612   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_VIEWPORT;
613}
614
615void anv_CmdSetViewportWithCountEXT(
616   VkCommandBuffer                              commandBuffer,
617   uint32_t                                     viewportCount,
618   const VkViewport*                            pViewports)
619{
620   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
621
622   cmd_buffer->state.gfx.dynamic.viewport.count = viewportCount;
623
624   memcpy(cmd_buffer->state.gfx.dynamic.viewport.viewports,
625          pViewports, viewportCount * sizeof(*pViewports));
626
627   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_VIEWPORT;
628}
629
630void anv_CmdSetScissor(
631    VkCommandBuffer                             commandBuffer,
632    uint32_t                                    firstScissor,
633    uint32_t                                    scissorCount,
634    const VkRect2D*                             pScissors)
635{
636   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
637
638   const uint32_t total_count = firstScissor + scissorCount;
639   if (cmd_buffer->state.gfx.dynamic.scissor.count < total_count)
640      cmd_buffer->state.gfx.dynamic.scissor.count = total_count;
641
642   memcpy(cmd_buffer->state.gfx.dynamic.scissor.scissors + firstScissor,
643          pScissors, scissorCount * sizeof(*pScissors));
644
645   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR;
646}
647
648void anv_CmdSetScissorWithCountEXT(
649   VkCommandBuffer                              commandBuffer,
650   uint32_t                                     scissorCount,
651   const VkRect2D*                              pScissors)
652{
653   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
654
655   cmd_buffer->state.gfx.dynamic.scissor.count = scissorCount;
656
657   memcpy(cmd_buffer->state.gfx.dynamic.scissor.scissors,
658          pScissors, scissorCount * sizeof(*pScissors));
659
660   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR;
661}
662
663void anv_CmdSetPrimitiveTopologyEXT(
664   VkCommandBuffer                              commandBuffer,
665   VkPrimitiveTopology                          primitiveTopology)
666{
667   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
668
669   cmd_buffer->state.gfx.dynamic.primitive_topology = primitiveTopology;
670
671   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY;
672}
673
674void anv_CmdSetLineWidth(
675    VkCommandBuffer                             commandBuffer,
676    float                                       lineWidth)
677{
678   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
679
680   cmd_buffer->state.gfx.dynamic.line_width = lineWidth;
681   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH;
682}
683
684void anv_CmdSetDepthBias(
685    VkCommandBuffer                             commandBuffer,
686    float                                       depthBiasConstantFactor,
687    float                                       depthBiasClamp,
688    float                                       depthBiasSlopeFactor)
689{
690   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
691
692   cmd_buffer->state.gfx.dynamic.depth_bias.bias = depthBiasConstantFactor;
693   cmd_buffer->state.gfx.dynamic.depth_bias.clamp = depthBiasClamp;
694   cmd_buffer->state.gfx.dynamic.depth_bias.slope = depthBiasSlopeFactor;
695
696   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS;
697}
698
699void anv_CmdSetBlendConstants(
700    VkCommandBuffer                             commandBuffer,
701    const float                                 blendConstants[4])
702{
703   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
704
705   memcpy(cmd_buffer->state.gfx.dynamic.blend_constants,
706          blendConstants, sizeof(float) * 4);
707
708   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS;
709}
710
711void anv_CmdSetDepthBounds(
712    VkCommandBuffer                             commandBuffer,
713    float                                       minDepthBounds,
714    float                                       maxDepthBounds)
715{
716   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
717
718   cmd_buffer->state.gfx.dynamic.depth_bounds.min = minDepthBounds;
719   cmd_buffer->state.gfx.dynamic.depth_bounds.max = maxDepthBounds;
720
721   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS;
722}
723
724void anv_CmdSetStencilCompareMask(
725    VkCommandBuffer                             commandBuffer,
726    VkStencilFaceFlags                          faceMask,
727    uint32_t                                    compareMask)
728{
729   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
730
731   if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
732      cmd_buffer->state.gfx.dynamic.stencil_compare_mask.front = compareMask;
733   if (faceMask & VK_STENCIL_FACE_BACK_BIT)
734      cmd_buffer->state.gfx.dynamic.stencil_compare_mask.back = compareMask;
735
736   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK;
737}
738
739void anv_CmdSetStencilWriteMask(
740    VkCommandBuffer                             commandBuffer,
741    VkStencilFaceFlags                          faceMask,
742    uint32_t                                    writeMask)
743{
744   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
745
746   if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
747      cmd_buffer->state.gfx.dynamic.stencil_write_mask.front = writeMask;
748   if (faceMask & VK_STENCIL_FACE_BACK_BIT)
749      cmd_buffer->state.gfx.dynamic.stencil_write_mask.back = writeMask;
750
751   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK;
752}
753
754void anv_CmdSetStencilReference(
755    VkCommandBuffer                             commandBuffer,
756    VkStencilFaceFlags                          faceMask,
757    uint32_t                                    reference)
758{
759   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
760
761   if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
762      cmd_buffer->state.gfx.dynamic.stencil_reference.front = reference;
763   if (faceMask & VK_STENCIL_FACE_BACK_BIT)
764      cmd_buffer->state.gfx.dynamic.stencil_reference.back = reference;
765
766   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE;
767}
768
769void anv_CmdSetSampleLocationsEXT(
770    VkCommandBuffer                             commandBuffer,
771    const VkSampleLocationsInfoEXT*             pSampleLocationsInfo)
772{
773   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
774
775   struct anv_dynamic_state *dyn_state = &cmd_buffer->state.gfx.dynamic;
776   uint32_t samples = pSampleLocationsInfo->sampleLocationsPerPixel;
777
778   dyn_state->sample_locations.samples = samples;
779   typed_memcpy(dyn_state->sample_locations.locations,
780                pSampleLocationsInfo->pSampleLocations, samples);
781
782   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS;
783}
784
785void anv_CmdSetLineStippleEXT(
786    VkCommandBuffer                             commandBuffer,
787    uint32_t                                    lineStippleFactor,
788    uint16_t                                    lineStipplePattern)
789{
790   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
791
792   cmd_buffer->state.gfx.dynamic.line_stipple.factor = lineStippleFactor;
793   cmd_buffer->state.gfx.dynamic.line_stipple.pattern = lineStipplePattern;
794
795   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE;
796}
797
798void anv_CmdSetCullModeEXT(
799   VkCommandBuffer                              commandBuffer,
800   VkCullModeFlags                              cullMode)
801{
802   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
803
804   cmd_buffer->state.gfx.dynamic.cull_mode = cullMode;
805
806   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_CULL_MODE;
807}
808
809void anv_CmdSetFrontFaceEXT(
810   VkCommandBuffer                              commandBuffer,
811   VkFrontFace                                  frontFace)
812{
813   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
814
815   cmd_buffer->state.gfx.dynamic.front_face = frontFace;
816
817   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE;
818}
819
820void anv_CmdSetDepthTestEnableEXT(
821   VkCommandBuffer                              commandBuffer,
822   VkBool32                                     depthTestEnable)
823
824{
825   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
826
827   cmd_buffer->state.gfx.dynamic.depth_test_enable = depthTestEnable;
828
829   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE;
830}
831
832void anv_CmdSetDepthWriteEnableEXT(
833   VkCommandBuffer                              commandBuffer,
834   VkBool32                                     depthWriteEnable)
835{
836   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
837
838   cmd_buffer->state.gfx.dynamic.depth_write_enable = depthWriteEnable;
839
840   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE;
841}
842
843void anv_CmdSetDepthCompareOpEXT(
844   VkCommandBuffer                              commandBuffer,
845   VkCompareOp                                  depthCompareOp)
846{
847   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
848
849   cmd_buffer->state.gfx.dynamic.depth_compare_op = depthCompareOp;
850
851   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP;
852}
853
854void anv_CmdSetDepthBoundsTestEnableEXT(
855   VkCommandBuffer                              commandBuffer,
856   VkBool32                                     depthBoundsTestEnable)
857{
858   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
859
860   cmd_buffer->state.gfx.dynamic.depth_bounds_test_enable = depthBoundsTestEnable;
861
862   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE;
863}
864
865void anv_CmdSetStencilTestEnableEXT(
866   VkCommandBuffer                              commandBuffer,
867   VkBool32                                     stencilTestEnable)
868{
869   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
870
871   cmd_buffer->state.gfx.dynamic.stencil_test_enable = stencilTestEnable;
872
873   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE;
874}
875
876void anv_CmdSetStencilOpEXT(
877   VkCommandBuffer                              commandBuffer,
878   VkStencilFaceFlags                           faceMask,
879   VkStencilOp                                  failOp,
880   VkStencilOp                                  passOp,
881   VkStencilOp                                  depthFailOp,
882   VkCompareOp                                  compareOp)
883{
884   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
885
886   if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
887      cmd_buffer->state.gfx.dynamic.stencil_op.front.fail_op = failOp;
888      cmd_buffer->state.gfx.dynamic.stencil_op.front.pass_op = passOp;
889      cmd_buffer->state.gfx.dynamic.stencil_op.front.depth_fail_op = depthFailOp;
890      cmd_buffer->state.gfx.dynamic.stencil_op.front.compare_op = compareOp;
891    }
892
893   if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
894      cmd_buffer->state.gfx.dynamic.stencil_op.back.fail_op = failOp;
895      cmd_buffer->state.gfx.dynamic.stencil_op.back.pass_op = passOp;
896      cmd_buffer->state.gfx.dynamic.stencil_op.back.depth_fail_op = depthFailOp;
897      cmd_buffer->state.gfx.dynamic.stencil_op.back.compare_op = compareOp;
898   }
899
900   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP;
901}
902
903static void
904anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
905                                   VkPipelineBindPoint bind_point,
906                                   struct anv_pipeline_layout *layout,
907                                   uint32_t set_index,
908                                   struct anv_descriptor_set *set,
909                                   uint32_t *dynamic_offset_count,
910                                   const uint32_t **dynamic_offsets)
911{
912   struct anv_descriptor_set_layout *set_layout =
913      layout->set[set_index].layout;
914
915   VkShaderStageFlags stages = set_layout->shader_stages;
916   struct anv_cmd_pipeline_state *pipe_state;
917
918   switch (bind_point) {
919   case VK_PIPELINE_BIND_POINT_GRAPHICS:
920      stages &= VK_SHADER_STAGE_ALL_GRAPHICS;
921      pipe_state = &cmd_buffer->state.gfx.base;
922      break;
923
924   case VK_PIPELINE_BIND_POINT_COMPUTE:
925      stages &= VK_SHADER_STAGE_COMPUTE_BIT;
926      pipe_state = &cmd_buffer->state.compute.base;
927      break;
928
929   case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR:
930      stages &= VK_SHADER_STAGE_RAYGEN_BIT_KHR |
931                VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
932                VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
933                VK_SHADER_STAGE_MISS_BIT_KHR |
934                VK_SHADER_STAGE_INTERSECTION_BIT_KHR |
935                VK_SHADER_STAGE_CALLABLE_BIT_KHR;
936      pipe_state = &cmd_buffer->state.rt.base;
937      break;
938
939   default:
940      unreachable("invalid bind point");
941   }
942
943   VkShaderStageFlags dirty_stages = 0;
944   /* If it's a push descriptor set, we have to flag things as dirty
945    * regardless of whether or not the CPU-side data structure changed as we
946    * may have edited in-place.
947    */
948   if (pipe_state->descriptors[set_index] != set ||
949         anv_descriptor_set_is_push(set)) {
950      pipe_state->descriptors[set_index] = set;
951
952      /* Ray-tracing shaders are entirely bindless and so they don't have
953       * access to HW binding tables.  This means that we have to upload the
954       * descriptor set as an 64-bit address in the push constants.
955       */
956      if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) {
957         struct anv_push_constants *push = &pipe_state->push_constants;
958
959         struct anv_address addr = anv_descriptor_set_address(set);
960         push->desc_sets[set_index] = anv_address_physical(addr);
961
962         if (addr.bo) {
963            anv_reloc_list_add_bo(cmd_buffer->batch.relocs,
964                                  cmd_buffer->batch.alloc,
965                                  addr.bo);
966         }
967      }
968
969      dirty_stages |= stages;
970   }
971
972   if (dynamic_offsets) {
973      if (set_layout->dynamic_offset_count > 0) {
974         struct anv_push_constants *push = &pipe_state->push_constants;
975         uint32_t dynamic_offset_start =
976            layout->set[set_index].dynamic_offset_start;
977         uint32_t *push_offsets =
978            &push->dynamic_offsets[dynamic_offset_start];
979
980         /* Assert that everything is in range */
981         assert(set_layout->dynamic_offset_count <= *dynamic_offset_count);
982         assert(dynamic_offset_start + set_layout->dynamic_offset_count <=
983                ARRAY_SIZE(push->dynamic_offsets));
984
985         for (uint32_t i = 0; i < set_layout->dynamic_offset_count; i++) {
986            if (push_offsets[i] != (*dynamic_offsets)[i]) {
987               push_offsets[i] = (*dynamic_offsets)[i];
988               /* dynamic_offset_stages[] elements could contain blanket
989                * values like VK_SHADER_STAGE_ALL, so limit this to the
990                * binding point's bits.
991                */
992               dirty_stages |= set_layout->dynamic_offset_stages[i] & stages;
993            }
994         }
995
996         *dynamic_offsets += set_layout->dynamic_offset_count;
997         *dynamic_offset_count -= set_layout->dynamic_offset_count;
998      }
999   }
1000
1001   cmd_buffer->state.descriptors_dirty |= dirty_stages;
1002   cmd_buffer->state.push_constants_dirty |= dirty_stages;
1003}
1004
1005void anv_CmdBindDescriptorSets(
1006    VkCommandBuffer                             commandBuffer,
1007    VkPipelineBindPoint                         pipelineBindPoint,
1008    VkPipelineLayout                            _layout,
1009    uint32_t                                    firstSet,
1010    uint32_t                                    descriptorSetCount,
1011    const VkDescriptorSet*                      pDescriptorSets,
1012    uint32_t                                    dynamicOffsetCount,
1013    const uint32_t*                             pDynamicOffsets)
1014{
1015   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1016   ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
1017
1018   assert(firstSet + descriptorSetCount <= MAX_SETS);
1019
1020   for (uint32_t i = 0; i < descriptorSetCount; i++) {
1021      ANV_FROM_HANDLE(anv_descriptor_set, set, pDescriptorSets[i]);
1022      anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint,
1023                                         layout, firstSet + i, set,
1024                                         &dynamicOffsetCount,
1025                                         &pDynamicOffsets);
1026   }
1027}
1028
1029void anv_CmdBindVertexBuffers2EXT(
1030   VkCommandBuffer                              commandBuffer,
1031   uint32_t                                     firstBinding,
1032   uint32_t                                     bindingCount,
1033   const VkBuffer*                              pBuffers,
1034   const VkDeviceSize*                          pOffsets,
1035   const VkDeviceSize*                          pSizes,
1036   const VkDeviceSize*                          pStrides)
1037{
1038   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1039   struct anv_vertex_binding *vb = cmd_buffer->state.vertex_bindings;
1040
1041   /* We have to defer setting up vertex buffer since we need the buffer
1042    * stride from the pipeline. */
1043
1044   if (pSizes)
1045      cmd_buffer->state.gfx.dynamic.dyn_vbo_size = true;
1046   if (pStrides)
1047      cmd_buffer->state.gfx.dynamic.dyn_vbo_stride = true;
1048
1049   assert(firstBinding + bindingCount <= MAX_VBS);
1050   for (uint32_t i = 0; i < bindingCount; i++) {
1051      vb[firstBinding + i].buffer = anv_buffer_from_handle(pBuffers[i]);
1052      vb[firstBinding + i].offset = pOffsets[i];
1053      vb[firstBinding + i].size = pSizes ? pSizes[i] : 0;
1054      vb[firstBinding + i].stride = pStrides ? pStrides[i] : 0;
1055      cmd_buffer->state.gfx.vb_dirty |= 1 << (firstBinding + i);
1056   }
1057}
1058
1059void anv_CmdBindVertexBuffers(
1060    VkCommandBuffer                             commandBuffer,
1061    uint32_t                                    firstBinding,
1062    uint32_t                                    bindingCount,
1063    const VkBuffer*                             pBuffers,
1064    const VkDeviceSize*                         pOffsets)
1065{
1066   return anv_CmdBindVertexBuffers2EXT(commandBuffer, firstBinding,
1067                                       bindingCount, pBuffers, pOffsets,
1068                                       NULL, NULL);
1069}
1070
1071void anv_CmdBindTransformFeedbackBuffersEXT(
1072    VkCommandBuffer                             commandBuffer,
1073    uint32_t                                    firstBinding,
1074    uint32_t                                    bindingCount,
1075    const VkBuffer*                             pBuffers,
1076    const VkDeviceSize*                         pOffsets,
1077    const VkDeviceSize*                         pSizes)
1078{
1079   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1080   struct anv_xfb_binding *xfb = cmd_buffer->state.xfb_bindings;
1081
1082   /* We have to defer setting up vertex buffer since we need the buffer
1083    * stride from the pipeline. */
1084
1085   assert(firstBinding + bindingCount <= MAX_XFB_BUFFERS);
1086   for (uint32_t i = 0; i < bindingCount; i++) {
1087      if (pBuffers[i] == VK_NULL_HANDLE) {
1088         xfb[firstBinding + i].buffer = NULL;
1089      } else {
1090         ANV_FROM_HANDLE(anv_buffer, buffer, pBuffers[i]);
1091         xfb[firstBinding + i].buffer = buffer;
1092         xfb[firstBinding + i].offset = pOffsets[i];
1093         xfb[firstBinding + i].size =
1094            anv_buffer_get_range(buffer, pOffsets[i],
1095                                 pSizes ? pSizes[i] : VK_WHOLE_SIZE);
1096      }
1097   }
1098}
1099
1100enum isl_format
1101anv_isl_format_for_descriptor_type(const struct anv_device *device,
1102                                   VkDescriptorType type)
1103{
1104   switch (type) {
1105   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1106   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1107      return device->physical->compiler->indirect_ubos_use_sampler ?
1108             ISL_FORMAT_R32G32B32A32_FLOAT : ISL_FORMAT_RAW;
1109
1110   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1111   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1112      return ISL_FORMAT_RAW;
1113
1114   default:
1115      unreachable("Invalid descriptor type");
1116   }
1117}
1118
1119struct anv_state
1120anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer *cmd_buffer,
1121                            const void *data, uint32_t size, uint32_t alignment)
1122{
1123   struct anv_state state;
1124
1125   state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, size, alignment);
1126   memcpy(state.map, data, size);
1127
1128   VG(VALGRIND_CHECK_MEM_IS_DEFINED(state.map, size));
1129
1130   return state;
1131}
1132
1133struct anv_state
1134anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer *cmd_buffer,
1135                             uint32_t *a, uint32_t *b,
1136                             uint32_t dwords, uint32_t alignment)
1137{
1138   struct anv_state state;
1139   uint32_t *p;
1140
1141   state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
1142                                              dwords * 4, alignment);
1143   p = state.map;
1144   for (uint32_t i = 0; i < dwords; i++)
1145      p[i] = a[i] | b[i];
1146
1147   VG(VALGRIND_CHECK_MEM_IS_DEFINED(p, dwords * 4));
1148
1149   return state;
1150}
1151
1152struct anv_state
1153anv_cmd_buffer_gfx_push_constants(struct anv_cmd_buffer *cmd_buffer)
1154{
1155   struct anv_push_constants *data =
1156      &cmd_buffer->state.gfx.base.push_constants;
1157
1158   struct anv_state state =
1159      anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
1160                                         sizeof(struct anv_push_constants),
1161                                         32 /* bottom 5 bits MBZ */);
1162   memcpy(state.map, data, sizeof(struct anv_push_constants));
1163
1164   return state;
1165}
1166
1167struct anv_state
1168anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer)
1169{
1170   const struct intel_device_info *devinfo = &cmd_buffer->device->info;
1171   struct anv_push_constants *data =
1172      &cmd_buffer->state.compute.base.push_constants;
1173   struct anv_compute_pipeline *pipeline = cmd_buffer->state.compute.pipeline;
1174   const struct brw_cs_prog_data *cs_prog_data = get_cs_prog_data(pipeline);
1175   const struct anv_push_range *range = &pipeline->cs->bind_map.push_ranges[0];
1176
1177   const struct brw_cs_dispatch_info dispatch =
1178      brw_cs_get_dispatch_info(devinfo, cs_prog_data, NULL);
1179   const unsigned total_push_constants_size =
1180      brw_cs_push_const_total_size(cs_prog_data, dispatch.threads);
1181   if (total_push_constants_size == 0)
1182      return (struct anv_state) { .offset = 0 };
1183
1184   const unsigned push_constant_alignment =
1185      cmd_buffer->device->info.ver < 8 ? 32 : 64;
1186   const unsigned aligned_total_push_constants_size =
1187      ALIGN(total_push_constants_size, push_constant_alignment);
1188   struct anv_state state;
1189   if (devinfo->verx10 >= 125) {
1190      state = anv_state_stream_alloc(&cmd_buffer->general_state_stream,
1191                                     aligned_total_push_constants_size,
1192                                     push_constant_alignment);
1193   } else {
1194      state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
1195                                                 aligned_total_push_constants_size,
1196                                                 push_constant_alignment);
1197   }
1198
1199   void *dst = state.map;
1200   const void *src = (char *)data + (range->start * 32);
1201
1202   if (cs_prog_data->push.cross_thread.size > 0) {
1203      memcpy(dst, src, cs_prog_data->push.cross_thread.size);
1204      dst += cs_prog_data->push.cross_thread.size;
1205      src += cs_prog_data->push.cross_thread.size;
1206   }
1207
1208   if (cs_prog_data->push.per_thread.size > 0) {
1209      for (unsigned t = 0; t < dispatch.threads; t++) {
1210         memcpy(dst, src, cs_prog_data->push.per_thread.size);
1211
1212         uint32_t *subgroup_id = dst +
1213            offsetof(struct anv_push_constants, cs.subgroup_id) -
1214            (range->start * 32 + cs_prog_data->push.cross_thread.size);
1215         *subgroup_id = t;
1216
1217         dst += cs_prog_data->push.per_thread.size;
1218      }
1219   }
1220
1221   return state;
1222}
1223
1224void anv_CmdPushConstants(
1225    VkCommandBuffer                             commandBuffer,
1226    VkPipelineLayout                            layout,
1227    VkShaderStageFlags                          stageFlags,
1228    uint32_t                                    offset,
1229    uint32_t                                    size,
1230    const void*                                 pValues)
1231{
1232   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1233
1234   if (stageFlags & VK_SHADER_STAGE_ALL_GRAPHICS) {
1235      struct anv_cmd_pipeline_state *pipe_state =
1236         &cmd_buffer->state.gfx.base;
1237
1238      memcpy(pipe_state->push_constants.client_data + offset, pValues, size);
1239   }
1240   if (stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) {
1241      struct anv_cmd_pipeline_state *pipe_state =
1242         &cmd_buffer->state.compute.base;
1243
1244      memcpy(pipe_state->push_constants.client_data + offset, pValues, size);
1245   }
1246   if (stageFlags & (VK_SHADER_STAGE_RAYGEN_BIT_KHR |
1247                     VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
1248                     VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
1249                     VK_SHADER_STAGE_MISS_BIT_KHR |
1250                     VK_SHADER_STAGE_INTERSECTION_BIT_KHR |
1251                     VK_SHADER_STAGE_CALLABLE_BIT_KHR)) {
1252      struct anv_cmd_pipeline_state *pipe_state =
1253         &cmd_buffer->state.rt.base;
1254
1255      memcpy(pipe_state->push_constants.client_data + offset, pValues, size);
1256   }
1257
1258   cmd_buffer->state.push_constants_dirty |= stageFlags;
1259}
1260
1261VkResult anv_CreateCommandPool(
1262    VkDevice                                    _device,
1263    const VkCommandPoolCreateInfo*              pCreateInfo,
1264    const VkAllocationCallbacks*                pAllocator,
1265    VkCommandPool*                              pCmdPool)
1266{
1267   ANV_FROM_HANDLE(anv_device, device, _device);
1268   struct anv_cmd_pool *pool;
1269
1270   pool = vk_object_alloc(&device->vk, pAllocator, sizeof(*pool),
1271                          VK_OBJECT_TYPE_COMMAND_POOL);
1272   if (pool == NULL)
1273      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1274
1275   assert(pCreateInfo->queueFamilyIndex < device->physical->queue.family_count);
1276   pool->queue_family =
1277      &device->physical->queue.families[pCreateInfo->queueFamilyIndex];
1278
1279   if (pAllocator)
1280      pool->alloc = *pAllocator;
1281   else
1282      pool->alloc = device->vk.alloc;
1283
1284   list_inithead(&pool->cmd_buffers);
1285
1286   pool->flags = pCreateInfo->flags;
1287
1288   *pCmdPool = anv_cmd_pool_to_handle(pool);
1289
1290   return VK_SUCCESS;
1291}
1292
1293void anv_DestroyCommandPool(
1294    VkDevice                                    _device,
1295    VkCommandPool                               commandPool,
1296    const VkAllocationCallbacks*                pAllocator)
1297{
1298   ANV_FROM_HANDLE(anv_device, device, _device);
1299   ANV_FROM_HANDLE(anv_cmd_pool, pool, commandPool);
1300
1301   if (!pool)
1302      return;
1303
1304   list_for_each_entry_safe(struct anv_cmd_buffer, cmd_buffer,
1305                            &pool->cmd_buffers, pool_link) {
1306      anv_cmd_buffer_destroy(cmd_buffer);
1307   }
1308
1309   vk_object_free(&device->vk, pAllocator, pool);
1310}
1311
1312VkResult anv_ResetCommandPool(
1313    VkDevice                                    device,
1314    VkCommandPool                               commandPool,
1315    VkCommandPoolResetFlags                     flags)
1316{
1317   ANV_FROM_HANDLE(anv_cmd_pool, pool, commandPool);
1318
1319   list_for_each_entry(struct anv_cmd_buffer, cmd_buffer,
1320                       &pool->cmd_buffers, pool_link) {
1321      anv_cmd_buffer_reset(cmd_buffer);
1322   }
1323
1324   return VK_SUCCESS;
1325}
1326
1327void anv_TrimCommandPool(
1328    VkDevice                                    device,
1329    VkCommandPool                               commandPool,
1330    VkCommandPoolTrimFlags                      flags)
1331{
1332   /* Nothing for us to do here.  Our pools stay pretty tidy. */
1333}
1334
1335/**
1336 * Return NULL if the current subpass has no depthstencil attachment.
1337 */
1338const struct anv_image_view *
1339anv_cmd_buffer_get_depth_stencil_view(const struct anv_cmd_buffer *cmd_buffer)
1340{
1341   const struct anv_subpass *subpass = cmd_buffer->state.subpass;
1342
1343   if (subpass->depth_stencil_attachment == NULL)
1344      return NULL;
1345
1346   const struct anv_image_view *iview =
1347      cmd_buffer->state.attachments[subpass->depth_stencil_attachment->attachment].image_view;
1348
1349   assert(iview->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
1350                               VK_IMAGE_ASPECT_STENCIL_BIT));
1351
1352   return iview;
1353}
1354
1355static struct anv_descriptor_set *
1356anv_cmd_buffer_push_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
1357                                   VkPipelineBindPoint bind_point,
1358                                   struct anv_descriptor_set_layout *layout,
1359                                   uint32_t _set)
1360{
1361   struct anv_cmd_pipeline_state *pipe_state;
1362
1363   switch (bind_point) {
1364   case VK_PIPELINE_BIND_POINT_GRAPHICS:
1365      pipe_state = &cmd_buffer->state.gfx.base;
1366      break;
1367
1368   case VK_PIPELINE_BIND_POINT_COMPUTE:
1369      pipe_state = &cmd_buffer->state.compute.base;
1370      break;
1371
1372   case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR:
1373      pipe_state = &cmd_buffer->state.rt.base;
1374      break;
1375
1376   default:
1377      unreachable("invalid bind point");
1378   }
1379
1380   struct anv_push_descriptor_set **push_set =
1381      &pipe_state->push_descriptors[_set];
1382
1383   if (*push_set == NULL) {
1384      *push_set = vk_zalloc(&cmd_buffer->pool->alloc,
1385                            sizeof(struct anv_push_descriptor_set), 8,
1386                            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1387      if (*push_set == NULL) {
1388         anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_HOST_MEMORY);
1389         return NULL;
1390      }
1391   }
1392
1393   struct anv_descriptor_set *set = &(*push_set)->set;
1394
1395   if (set->layout != layout) {
1396      if (set->layout)
1397         anv_descriptor_set_layout_unref(cmd_buffer->device, set->layout);
1398      anv_descriptor_set_layout_ref(layout);
1399      set->layout = layout;
1400   }
1401   set->size = anv_descriptor_set_layout_size(layout, 0);
1402   set->buffer_view_count = layout->buffer_view_count;
1403   set->descriptor_count = layout->descriptor_count;
1404   set->buffer_views = (*push_set)->buffer_views;
1405
1406   if (layout->descriptor_buffer_size &&
1407       ((*push_set)->set_used_on_gpu ||
1408        set->desc_mem.alloc_size < layout->descriptor_buffer_size)) {
1409      /* The previous buffer is either actively used by some GPU command (so
1410       * we can't modify it) or is too small.  Allocate a new one.
1411       */
1412      struct anv_state desc_mem =
1413         anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream,
1414                                anv_descriptor_set_layout_descriptor_buffer_size(layout, 0),
1415                                ANV_UBO_ALIGNMENT);
1416      if (set->desc_mem.alloc_size) {
1417         /* TODO: Do we really need to copy all the time? */
1418         memcpy(desc_mem.map, set->desc_mem.map,
1419                MIN2(desc_mem.alloc_size, set->desc_mem.alloc_size));
1420      }
1421      set->desc_mem = desc_mem;
1422
1423      set->desc_addr = (struct anv_address) {
1424         .bo = cmd_buffer->dynamic_state_stream.state_pool->block_pool.bo,
1425         .offset = set->desc_mem.offset,
1426      };
1427
1428      enum isl_format format =
1429         anv_isl_format_for_descriptor_type(cmd_buffer->device,
1430                                            VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
1431
1432      const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;
1433      set->desc_surface_state =
1434         anv_state_stream_alloc(&cmd_buffer->surface_state_stream,
1435                                isl_dev->ss.size, isl_dev->ss.align);
1436      anv_fill_buffer_surface_state(cmd_buffer->device,
1437                                    set->desc_surface_state, format,
1438                                    ISL_SURF_USAGE_CONSTANT_BUFFER_BIT,
1439                                    set->desc_addr,
1440                                    layout->descriptor_buffer_size, 1);
1441   }
1442
1443   return set;
1444}
1445
1446void anv_CmdPushDescriptorSetKHR(
1447    VkCommandBuffer commandBuffer,
1448    VkPipelineBindPoint pipelineBindPoint,
1449    VkPipelineLayout _layout,
1450    uint32_t _set,
1451    uint32_t descriptorWriteCount,
1452    const VkWriteDescriptorSet* pDescriptorWrites)
1453{
1454   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1455   ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
1456
1457   assert(_set < MAX_SETS);
1458
1459   struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;
1460
1461   struct anv_descriptor_set *set =
1462      anv_cmd_buffer_push_descriptor_set(cmd_buffer, pipelineBindPoint,
1463                                         set_layout, _set);
1464   if (!set)
1465      return;
1466
1467   /* Go through the user supplied descriptors. */
1468   for (uint32_t i = 0; i < descriptorWriteCount; i++) {
1469      const VkWriteDescriptorSet *write = &pDescriptorWrites[i];
1470
1471      switch (write->descriptorType) {
1472      case VK_DESCRIPTOR_TYPE_SAMPLER:
1473      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1474      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1475      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1476      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1477         for (uint32_t j = 0; j < write->descriptorCount; j++) {
1478            anv_descriptor_set_write_image_view(cmd_buffer->device, set,
1479                                                write->pImageInfo + j,
1480                                                write->descriptorType,
1481                                                write->dstBinding,
1482                                                write->dstArrayElement + j);
1483         }
1484         break;
1485
1486      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1487      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1488         for (uint32_t j = 0; j < write->descriptorCount; j++) {
1489            ANV_FROM_HANDLE(anv_buffer_view, bview,
1490                            write->pTexelBufferView[j]);
1491
1492            anv_descriptor_set_write_buffer_view(cmd_buffer->device, set,
1493                                                 write->descriptorType,
1494                                                 bview,
1495                                                 write->dstBinding,
1496                                                 write->dstArrayElement + j);
1497         }
1498         break;
1499
1500      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1501      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1502      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1503      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1504         for (uint32_t j = 0; j < write->descriptorCount; j++) {
1505            ANV_FROM_HANDLE(anv_buffer, buffer, write->pBufferInfo[j].buffer);
1506
1507            anv_descriptor_set_write_buffer(cmd_buffer->device, set,
1508                                            &cmd_buffer->surface_state_stream,
1509                                            write->descriptorType,
1510                                            buffer,
1511                                            write->dstBinding,
1512                                            write->dstArrayElement + j,
1513                                            write->pBufferInfo[j].offset,
1514                                            write->pBufferInfo[j].range);
1515         }
1516         break;
1517
1518      case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
1519         const VkWriteDescriptorSetAccelerationStructureKHR *accel_write =
1520            vk_find_struct_const(write, WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR);
1521         assert(accel_write->accelerationStructureCount ==
1522                write->descriptorCount);
1523         for (uint32_t j = 0; j < write->descriptorCount; j++) {
1524            ANV_FROM_HANDLE(anv_acceleration_structure, accel,
1525                            accel_write->pAccelerationStructures[j]);
1526            anv_descriptor_set_write_acceleration_structure(cmd_buffer->device,
1527                                                            set, accel,
1528                                                            write->dstBinding,
1529                                                            write->dstArrayElement + j);
1530         }
1531         break;
1532      }
1533
1534      default:
1535         break;
1536      }
1537   }
1538
1539   anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint,
1540                                      layout, _set, set, NULL, NULL);
1541}
1542
1543void anv_CmdPushDescriptorSetWithTemplateKHR(
1544    VkCommandBuffer                             commandBuffer,
1545    VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
1546    VkPipelineLayout                            _layout,
1547    uint32_t                                    _set,
1548    const void*                                 pData)
1549{
1550   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1551   ANV_FROM_HANDLE(anv_descriptor_update_template, template,
1552                   descriptorUpdateTemplate);
1553   ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
1554
1555   assert(_set < MAX_PUSH_DESCRIPTORS);
1556
1557   struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;
1558
1559   struct anv_descriptor_set *set =
1560      anv_cmd_buffer_push_descriptor_set(cmd_buffer, template->bind_point,
1561                                         set_layout, _set);
1562   if (!set)
1563      return;
1564
1565   anv_descriptor_set_write_template(cmd_buffer->device, set,
1566                                     &cmd_buffer->surface_state_stream,
1567                                     template,
1568                                     pData);
1569
1570   anv_cmd_buffer_bind_descriptor_set(cmd_buffer, template->bind_point,
1571                                      layout, _set, set, NULL, NULL);
1572}
1573
1574void anv_CmdSetDeviceMask(
1575    VkCommandBuffer                             commandBuffer,
1576    uint32_t                                    deviceMask)
1577{
1578   /* No-op */
1579}
1580
1581void anv_CmdSetColorWriteEnableEXT(
1582    VkCommandBuffer                             commandBuffer,
1583    uint32_t                                    attachmentCount,
1584    const VkBool32*                             pColorWriteEnables)
1585{
1586   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1587
1588   assert(attachmentCount < MAX_RTS);
1589
1590   uint8_t color_writes = 0;
1591   for (uint32_t i = 0; i < attachmentCount; i++)
1592      color_writes |= pColorWriteEnables[i] ? (1 << i) : 0;
1593
1594   if (cmd_buffer->state.gfx.dynamic.color_writes != color_writes) {
1595      cmd_buffer->state.gfx.dynamic.color_writes = color_writes;
1596      cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE;
1597   }
1598}
1599
1600void anv_CmdSetFragmentShadingRateKHR(
1601    VkCommandBuffer                             commandBuffer,
1602    const VkExtent2D*                           pFragmentSize,
1603    const VkFragmentShadingRateCombinerOpKHR    combinerOps[2])
1604{
1605   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1606
1607   cmd_buffer->state.gfx.dynamic.fragment_shading_rate = *pFragmentSize;
1608   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE;
1609}
1610
1611static inline uint32_t
1612ilog2_round_up(uint32_t value)
1613{
1614   assert(value != 0);
1615   return 32 - __builtin_clz(value - 1);
1616}
1617
1618void anv_CmdSetRayTracingPipelineStackSizeKHR(
1619    VkCommandBuffer                             commandBuffer,
1620    uint32_t                                    pipelineStackSize)
1621{
1622   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1623   struct anv_cmd_ray_tracing_state *rt = &cmd_buffer->state.rt;
1624   struct anv_device *device = cmd_buffer->device;
1625
1626   if (anv_batch_has_error(&cmd_buffer->batch))
1627      return;
1628
1629   uint32_t stack_ids_per_dss = 2048; /* TODO */
1630
1631   unsigned stack_size_log2 = ilog2_round_up(pipelineStackSize);
1632   if (stack_size_log2 < 10)
1633      stack_size_log2 = 10;
1634
1635   if (rt->scratch.layout.total_size == 1 << stack_size_log2)
1636      return;
1637
1638   brw_rt_compute_scratch_layout(&rt->scratch.layout, &device->info,
1639                                 stack_ids_per_dss, 1 << stack_size_log2);
1640
1641   unsigned bucket = stack_size_log2 - 10;
1642   assert(bucket < ARRAY_SIZE(device->rt_scratch_bos));
1643
1644   struct anv_bo *bo = p_atomic_read(&device->rt_scratch_bos[bucket]);
1645   if (bo == NULL) {
1646      struct anv_bo *new_bo;
1647      VkResult result = anv_device_alloc_bo(device, "RT scratch",
1648                                            rt->scratch.layout.total_size,
1649                                            0, /* alloc_flags */
1650                                            0, /* explicit_address */
1651                                            &new_bo);
1652      if (result != VK_SUCCESS) {
1653         rt->scratch.layout.total_size = 0;
1654         anv_batch_set_error(&cmd_buffer->batch, result);
1655         return;
1656      }
1657
1658      bo = p_atomic_cmpxchg(&device->rt_scratch_bos[bucket], NULL, new_bo);
1659      if (bo != NULL) {
1660         anv_device_release_bo(device, bo);
1661      } else {
1662         bo = new_bo;
1663      }
1664   }
1665
1666   rt->scratch.bo = bo;
1667}
1668