xref: /aosp_15_r20/external/mesa3d/src/intel/vulkan_hasvk/anv_cmd_buffer.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 static void
anv_cmd_state_init(struct anv_cmd_buffer * cmd_buffer)45 anv_cmd_state_init(struct anv_cmd_buffer *cmd_buffer)
46 {
47    struct anv_cmd_state *state = &cmd_buffer->state;
48 
49    memset(state, 0, sizeof(*state));
50 
51    state->current_pipeline = UINT32_MAX;
52    state->gfx.restart_index = UINT32_MAX;
53    state->gfx.dirty = 0;
54 }
55 
56 static void
anv_cmd_pipeline_state_finish(struct anv_cmd_buffer * cmd_buffer,struct anv_cmd_pipeline_state * pipe_state)57 anv_cmd_pipeline_state_finish(struct anv_cmd_buffer *cmd_buffer,
58                               struct anv_cmd_pipeline_state *pipe_state)
59 {
60    for (uint32_t i = 0; i < ARRAY_SIZE(pipe_state->push_descriptors); i++) {
61       if (pipe_state->push_descriptors[i]) {
62          anv_descriptor_set_layout_unref(cmd_buffer->device,
63              pipe_state->push_descriptors[i]->set.layout);
64          vk_free(&cmd_buffer->vk.pool->alloc, pipe_state->push_descriptors[i]);
65       }
66    }
67 }
68 
69 static void
anv_cmd_state_finish(struct anv_cmd_buffer * cmd_buffer)70 anv_cmd_state_finish(struct anv_cmd_buffer *cmd_buffer)
71 {
72    struct anv_cmd_state *state = &cmd_buffer->state;
73 
74    anv_cmd_pipeline_state_finish(cmd_buffer, &state->gfx.base);
75    anv_cmd_pipeline_state_finish(cmd_buffer, &state->compute.base);
76 }
77 
78 static void
anv_cmd_state_reset(struct anv_cmd_buffer * cmd_buffer)79 anv_cmd_state_reset(struct anv_cmd_buffer *cmd_buffer)
80 {
81    anv_cmd_state_finish(cmd_buffer);
82    anv_cmd_state_init(cmd_buffer);
83 }
84 
85 static VkResult
anv_create_cmd_buffer(struct vk_command_pool * pool,VkCommandBufferLevel level,struct vk_command_buffer ** cmd_buffer_out)86 anv_create_cmd_buffer(struct vk_command_pool *pool,
87                       VkCommandBufferLevel level,
88                       struct vk_command_buffer **cmd_buffer_out)
89 {
90    struct anv_device *device =
91       container_of(pool->base.device, struct anv_device, vk);
92    struct anv_cmd_buffer *cmd_buffer;
93    VkResult result;
94 
95    cmd_buffer = vk_alloc(&pool->alloc, sizeof(*cmd_buffer), 8,
96                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
97    if (cmd_buffer == NULL)
98       return vk_error(pool, VK_ERROR_OUT_OF_HOST_MEMORY);
99 
100    result = vk_command_buffer_init(pool, &cmd_buffer->vk,
101                                    &anv_cmd_buffer_ops, level);
102    if (result != VK_SUCCESS)
103       goto fail_alloc;
104 
105    cmd_buffer->vk.dynamic_graphics_state.ms.sample_locations =
106       &cmd_buffer->state.gfx.sample_locations;
107 
108    cmd_buffer->batch.status = VK_SUCCESS;
109 
110    cmd_buffer->device = device;
111 
112    assert(pool->queue_family_index < device->physical->queue.family_count);
113    cmd_buffer->queue_family =
114       &device->physical->queue.families[pool->queue_family_index];
115 
116    result = anv_cmd_buffer_init_batch_bo_chain(cmd_buffer);
117    if (result != VK_SUCCESS)
118       goto fail_vk;
119 
120    anv_state_stream_init(&cmd_buffer->surface_state_stream,
121                          &device->surface_state_pool, 4096);
122    anv_state_stream_init(&cmd_buffer->dynamic_state_stream,
123                          &device->dynamic_state_pool, 16384);
124    anv_state_stream_init(&cmd_buffer->general_state_stream,
125                          &device->general_state_pool, 16384);
126 
127    cmd_buffer->self_mod_locations = NULL;
128 
129    anv_cmd_state_init(cmd_buffer);
130 
131    anv_measure_init(cmd_buffer);
132 
133    u_trace_init(&cmd_buffer->trace, &device->ds.trace_context);
134 
135    *cmd_buffer_out = &cmd_buffer->vk;
136 
137    return VK_SUCCESS;
138 
139  fail_vk:
140    vk_command_buffer_finish(&cmd_buffer->vk);
141  fail_alloc:
142    vk_free2(&device->vk.alloc, &pool->alloc, cmd_buffer);
143 
144    return result;
145 }
146 
147 static void
anv_cmd_buffer_destroy(struct vk_command_buffer * vk_cmd_buffer)148 anv_cmd_buffer_destroy(struct vk_command_buffer *vk_cmd_buffer)
149 {
150    struct anv_cmd_buffer *cmd_buffer =
151       container_of(vk_cmd_buffer, struct anv_cmd_buffer, vk);
152 
153    u_trace_fini(&cmd_buffer->trace);
154 
155    anv_measure_destroy(cmd_buffer);
156 
157    anv_cmd_buffer_fini_batch_bo_chain(cmd_buffer);
158 
159    anv_state_stream_finish(&cmd_buffer->surface_state_stream);
160    anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
161    anv_state_stream_finish(&cmd_buffer->general_state_stream);
162 
163    anv_cmd_state_finish(cmd_buffer);
164 
165    vk_free(&cmd_buffer->vk.pool->alloc, cmd_buffer->self_mod_locations);
166 
167    vk_command_buffer_finish(&cmd_buffer->vk);
168    vk_free(&cmd_buffer->vk.pool->alloc, cmd_buffer);
169 }
170 
171 void
anv_cmd_buffer_reset(struct vk_command_buffer * vk_cmd_buffer,UNUSED VkCommandBufferResetFlags flags)172 anv_cmd_buffer_reset(struct vk_command_buffer *vk_cmd_buffer,
173                      UNUSED VkCommandBufferResetFlags flags)
174 {
175    struct anv_cmd_buffer *cmd_buffer =
176       container_of(vk_cmd_buffer, struct anv_cmd_buffer, vk);
177 
178    vk_command_buffer_reset(&cmd_buffer->vk);
179 
180    cmd_buffer->usage_flags = 0;
181    cmd_buffer->perf_query_pool = NULL;
182    anv_cmd_buffer_reset_batch_bo_chain(cmd_buffer);
183    anv_cmd_state_reset(cmd_buffer);
184 
185    anv_state_stream_finish(&cmd_buffer->surface_state_stream);
186    anv_state_stream_init(&cmd_buffer->surface_state_stream,
187                          &cmd_buffer->device->surface_state_pool, 4096);
188 
189    anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
190    anv_state_stream_init(&cmd_buffer->dynamic_state_stream,
191                          &cmd_buffer->device->dynamic_state_pool, 16384);
192 
193    anv_state_stream_finish(&cmd_buffer->general_state_stream);
194    anv_state_stream_init(&cmd_buffer->general_state_stream,
195                          &cmd_buffer->device->general_state_pool, 16384);
196 
197    anv_measure_reset(cmd_buffer);
198 
199    u_trace_fini(&cmd_buffer->trace);
200    u_trace_init(&cmd_buffer->trace, &cmd_buffer->device->ds.trace_context);
201 }
202 
203 const struct vk_command_buffer_ops anv_cmd_buffer_ops = {
204    .create = anv_create_cmd_buffer,
205    .reset = anv_cmd_buffer_reset,
206    .destroy = anv_cmd_buffer_destroy,
207 };
208 
209 void
anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer * cmd_buffer)210 anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer)
211 {
212    const struct intel_device_info *devinfo = cmd_buffer->device->info;
213    anv_genX(devinfo, cmd_buffer_emit_state_base_address)(cmd_buffer);
214 }
215 
216 void
anv_cmd_buffer_mark_image_written(struct anv_cmd_buffer * cmd_buffer,const struct anv_image * image,VkImageAspectFlagBits aspect,enum isl_aux_usage aux_usage,uint32_t level,uint32_t base_layer,uint32_t layer_count)217 anv_cmd_buffer_mark_image_written(struct anv_cmd_buffer *cmd_buffer,
218                                   const struct anv_image *image,
219                                   VkImageAspectFlagBits aspect,
220                                   enum isl_aux_usage aux_usage,
221                                   uint32_t level,
222                                   uint32_t base_layer,
223                                   uint32_t layer_count)
224 {
225    const struct intel_device_info *devinfo = cmd_buffer->device->info;
226    anv_genX(devinfo, cmd_buffer_mark_image_written)(cmd_buffer, image,
227                                                     aspect, aux_usage,
228                                                     level, base_layer,
229                                                     layer_count);
230 }
231 
232 void
anv_cmd_emit_conditional_render_predicate(struct anv_cmd_buffer * cmd_buffer)233 anv_cmd_emit_conditional_render_predicate(struct anv_cmd_buffer *cmd_buffer)
234 {
235    const struct intel_device_info *devinfo = cmd_buffer->device->info;
236    anv_genX(devinfo, cmd_emit_conditional_render_predicate)(cmd_buffer);
237 }
238 
239 static bool
mem_update(void * dst,const void * src,size_t size)240 mem_update(void *dst, const void *src, size_t size)
241 {
242    if (memcmp(dst, src, size) == 0)
243       return false;
244 
245    memcpy(dst, src, size);
246    return true;
247 }
248 
249 static void
set_dirty_for_bind_map(struct anv_cmd_buffer * cmd_buffer,gl_shader_stage stage,const struct anv_pipeline_bind_map * map)250 set_dirty_for_bind_map(struct anv_cmd_buffer *cmd_buffer,
251                        gl_shader_stage stage,
252                        const struct anv_pipeline_bind_map *map)
253 {
254    assert(stage < ARRAY_SIZE(cmd_buffer->state.surface_sha1s));
255    if (mem_update(cmd_buffer->state.surface_sha1s[stage],
256                   map->surface_sha1, sizeof(map->surface_sha1)))
257       cmd_buffer->state.descriptors_dirty |= mesa_to_vk_shader_stage(stage);
258 
259    assert(stage < ARRAY_SIZE(cmd_buffer->state.sampler_sha1s));
260    if (mem_update(cmd_buffer->state.sampler_sha1s[stage],
261                   map->sampler_sha1, sizeof(map->sampler_sha1)))
262       cmd_buffer->state.descriptors_dirty |= mesa_to_vk_shader_stage(stage);
263 
264    assert(stage < ARRAY_SIZE(cmd_buffer->state.push_sha1s));
265    if (mem_update(cmd_buffer->state.push_sha1s[stage],
266                   map->push_sha1, sizeof(map->push_sha1)))
267       cmd_buffer->state.push_constants_dirty |= mesa_to_vk_shader_stage(stage);
268 }
269 
270 static inline uint32_t
ilog2_round_up(uint32_t value)271 ilog2_round_up(uint32_t value)
272 {
273    assert(value != 0);
274    return 32 - __builtin_clz(value - 1);
275 }
276 
anv_CmdBindPipeline(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipeline _pipeline)277 void anv_CmdBindPipeline(
278     VkCommandBuffer                             commandBuffer,
279     VkPipelineBindPoint                         pipelineBindPoint,
280     VkPipeline                                  _pipeline)
281 {
282    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
283    ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
284 
285    switch (pipelineBindPoint) {
286    case VK_PIPELINE_BIND_POINT_COMPUTE: {
287       struct anv_compute_pipeline *compute_pipeline =
288          anv_pipeline_to_compute(pipeline);
289       if (cmd_buffer->state.compute.pipeline == compute_pipeline)
290          return;
291 
292       cmd_buffer->state.compute.pipeline = compute_pipeline;
293       cmd_buffer->state.compute.pipeline_dirty = true;
294       set_dirty_for_bind_map(cmd_buffer, MESA_SHADER_COMPUTE,
295                              &compute_pipeline->cs->bind_map);
296       break;
297    }
298 
299    case VK_PIPELINE_BIND_POINT_GRAPHICS: {
300       struct anv_graphics_pipeline *gfx_pipeline =
301          anv_pipeline_to_graphics(pipeline);
302 
303       /* Apply the non dynamic state from the pipeline */
304       vk_cmd_set_dynamic_graphics_state(&cmd_buffer->vk,
305                                         &gfx_pipeline->dynamic_state);
306 
307       if (cmd_buffer->state.gfx.pipeline == gfx_pipeline)
308          return;
309 
310       cmd_buffer->state.gfx.pipeline = gfx_pipeline;
311       cmd_buffer->state.gfx.vb_dirty |= gfx_pipeline->vb_used;
312       cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_PIPELINE;
313 
314       anv_foreach_stage(stage, gfx_pipeline->active_stages) {
315          set_dirty_for_bind_map(cmd_buffer, stage,
316                                 &gfx_pipeline->shaders[stage]->bind_map);
317       }
318       break;
319    }
320 
321    default:
322       unreachable("invalid bind point");
323       break;
324    }
325 }
326 
327 static void
anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer * cmd_buffer,VkPipelineBindPoint bind_point,struct anv_pipeline_layout * layout,uint32_t set_index,struct anv_descriptor_set * set,uint32_t * dynamic_offset_count,const uint32_t ** dynamic_offsets)328 anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
329                                    VkPipelineBindPoint bind_point,
330                                    struct anv_pipeline_layout *layout,
331                                    uint32_t set_index,
332                                    struct anv_descriptor_set *set,
333                                    uint32_t *dynamic_offset_count,
334                                    const uint32_t **dynamic_offsets)
335 {
336    /* Either we have no pool because it's a push descriptor or the pool is not
337     * host only :
338     *
339     * VUID-vkCmdBindDescriptorSets-pDescriptorSets-04616:
340     *
341     *    "Each element of pDescriptorSets must not have been allocated from a
342     *     VkDescriptorPool with the
343     *     VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT flag set"
344     */
345    assert(!set->pool || !set->pool->host_only);
346 
347    struct anv_descriptor_set_layout *set_layout =
348       layout->set[set_index].layout;
349 
350    VkShaderStageFlags stages = set_layout->shader_stages;
351    struct anv_cmd_pipeline_state *pipe_state;
352 
353    switch (bind_point) {
354    case VK_PIPELINE_BIND_POINT_GRAPHICS:
355       stages &= VK_SHADER_STAGE_ALL_GRAPHICS;
356       pipe_state = &cmd_buffer->state.gfx.base;
357       break;
358 
359    case VK_PIPELINE_BIND_POINT_COMPUTE:
360       stages &= VK_SHADER_STAGE_COMPUTE_BIT;
361       pipe_state = &cmd_buffer->state.compute.base;
362       break;
363 
364    default:
365       unreachable("invalid bind point");
366    }
367 
368    VkShaderStageFlags dirty_stages = 0;
369    /* If it's a push descriptor set, we have to flag things as dirty
370     * regardless of whether or not the CPU-side data structure changed as we
371     * may have edited in-place.
372     */
373    if (pipe_state->descriptors[set_index] != set ||
374          anv_descriptor_set_is_push(set)) {
375       pipe_state->descriptors[set_index] = set;
376       dirty_stages |= stages;
377    }
378 
379    if (dynamic_offsets) {
380       if (set_layout->dynamic_offset_count > 0) {
381          struct anv_push_constants *push = &pipe_state->push_constants;
382          uint32_t dynamic_offset_start =
383             layout->set[set_index].dynamic_offset_start;
384          uint32_t *push_offsets =
385             &push->dynamic_offsets[dynamic_offset_start];
386 
387          /* Assert that everything is in range */
388          assert(set_layout->dynamic_offset_count <= *dynamic_offset_count);
389          assert(dynamic_offset_start + set_layout->dynamic_offset_count <=
390                 ARRAY_SIZE(push->dynamic_offsets));
391 
392          for (uint32_t i = 0; i < set_layout->dynamic_offset_count; i++) {
393             if (push_offsets[i] != (*dynamic_offsets)[i]) {
394                push_offsets[i] = (*dynamic_offsets)[i];
395                /* dynamic_offset_stages[] elements could contain blanket
396                 * values like VK_SHADER_STAGE_ALL, so limit this to the
397                 * binding point's bits.
398                 */
399                dirty_stages |= set_layout->dynamic_offset_stages[i] & stages;
400             }
401          }
402 
403          *dynamic_offsets += set_layout->dynamic_offset_count;
404          *dynamic_offset_count -= set_layout->dynamic_offset_count;
405       }
406    }
407 
408    cmd_buffer->state.descriptors_dirty |= dirty_stages;
409    cmd_buffer->state.push_constants_dirty |= dirty_stages;
410 }
411 
anv_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout _layout,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)412 void anv_CmdBindDescriptorSets(
413     VkCommandBuffer                             commandBuffer,
414     VkPipelineBindPoint                         pipelineBindPoint,
415     VkPipelineLayout                            _layout,
416     uint32_t                                    firstSet,
417     uint32_t                                    descriptorSetCount,
418     const VkDescriptorSet*                      pDescriptorSets,
419     uint32_t                                    dynamicOffsetCount,
420     const uint32_t*                             pDynamicOffsets)
421 {
422    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
423    ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
424 
425    assert(firstSet + descriptorSetCount <= MAX_SETS);
426 
427    for (uint32_t i = 0; i < descriptorSetCount; i++) {
428       ANV_FROM_HANDLE(anv_descriptor_set, set, pDescriptorSets[i]);
429       anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint,
430                                          layout, firstSet + i, set,
431                                          &dynamicOffsetCount,
432                                          &pDynamicOffsets);
433    }
434 }
435 
anv_CmdBindVertexBuffers2(VkCommandBuffer commandBuffer,uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets,const VkDeviceSize * pSizes,const VkDeviceSize * pStrides)436 void anv_CmdBindVertexBuffers2(
437    VkCommandBuffer                              commandBuffer,
438    uint32_t                                     firstBinding,
439    uint32_t                                     bindingCount,
440    const VkBuffer*                              pBuffers,
441    const VkDeviceSize*                          pOffsets,
442    const VkDeviceSize*                          pSizes,
443    const VkDeviceSize*                          pStrides)
444 {
445    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
446    struct anv_vertex_binding *vb = cmd_buffer->state.vertex_bindings;
447 
448    /* We have to defer setting up vertex buffer since we need the buffer
449     * stride from the pipeline. */
450 
451    assert(firstBinding + bindingCount <= MAX_VBS);
452    for (uint32_t i = 0; i < bindingCount; i++) {
453       ANV_FROM_HANDLE(anv_buffer, buffer, pBuffers[i]);
454 
455       if (buffer == NULL) {
456          vb[firstBinding + i] = (struct anv_vertex_binding) {
457             .buffer = NULL,
458          };
459       } else {
460          vb[firstBinding + i] = (struct anv_vertex_binding) {
461             .buffer = buffer,
462             .offset = pOffsets[i],
463             .size = vk_buffer_range(&buffer->vk, pOffsets[i],
464                                     pSizes ? pSizes[i] : VK_WHOLE_SIZE),
465          };
466       }
467       cmd_buffer->state.gfx.vb_dirty |= 1 << (firstBinding + i);
468    }
469 
470    if (pStrides != NULL) {
471       vk_cmd_set_vertex_binding_strides(&cmd_buffer->vk, firstBinding,
472                                         bindingCount, pStrides);
473    }
474 }
475 
anv_CmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer,uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets,const VkDeviceSize * pSizes)476 void anv_CmdBindTransformFeedbackBuffersEXT(
477     VkCommandBuffer                             commandBuffer,
478     uint32_t                                    firstBinding,
479     uint32_t                                    bindingCount,
480     const VkBuffer*                             pBuffers,
481     const VkDeviceSize*                         pOffsets,
482     const VkDeviceSize*                         pSizes)
483 {
484    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
485    struct anv_xfb_binding *xfb = cmd_buffer->state.xfb_bindings;
486 
487    /* We have to defer setting up vertex buffer since we need the buffer
488     * stride from the pipeline. */
489 
490    assert(firstBinding + bindingCount <= MAX_XFB_BUFFERS);
491    for (uint32_t i = 0; i < bindingCount; i++) {
492       if (pBuffers[i] == VK_NULL_HANDLE) {
493          xfb[firstBinding + i].buffer = NULL;
494       } else {
495          ANV_FROM_HANDLE(anv_buffer, buffer, pBuffers[i]);
496          xfb[firstBinding + i].buffer = buffer;
497          xfb[firstBinding + i].offset = pOffsets[i];
498          xfb[firstBinding + i].size =
499             vk_buffer_range(&buffer->vk, pOffsets[i],
500                             pSizes ? pSizes[i] : VK_WHOLE_SIZE);
501       }
502    }
503 }
504 
505 enum isl_format
anv_isl_format_for_descriptor_type(const struct anv_device * device,VkDescriptorType type)506 anv_isl_format_for_descriptor_type(const struct anv_device *device,
507                                    VkDescriptorType type)
508 {
509    switch (type) {
510    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
511    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
512       return device->physical->compiler->indirect_ubos_use_sampler ?
513              ISL_FORMAT_R32G32B32A32_FLOAT : ISL_FORMAT_RAW;
514 
515    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
516    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
517       return ISL_FORMAT_RAW;
518 
519    default:
520       unreachable("Invalid descriptor type");
521    }
522 }
523 
524 struct anv_state
anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer * cmd_buffer,const void * data,uint32_t size,uint32_t alignment)525 anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer *cmd_buffer,
526                             const void *data, uint32_t size, uint32_t alignment)
527 {
528    struct anv_state state;
529 
530    state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, size, alignment);
531    memcpy(state.map, data, size);
532 
533    VG(VALGRIND_CHECK_MEM_IS_DEFINED(state.map, size));
534 
535    return state;
536 }
537 
538 struct anv_state
anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer * cmd_buffer,uint32_t * a,uint32_t * b,uint32_t dwords,uint32_t alignment)539 anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer *cmd_buffer,
540                              uint32_t *a, uint32_t *b,
541                              uint32_t dwords, uint32_t alignment)
542 {
543    struct anv_state state;
544    uint32_t *p;
545 
546    state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
547                                               dwords * 4, alignment);
548    p = state.map;
549    for (uint32_t i = 0; i < dwords; i++)
550       p[i] = a[i] | b[i];
551 
552    VG(VALGRIND_CHECK_MEM_IS_DEFINED(p, dwords * 4));
553 
554    return state;
555 }
556 
557 struct anv_state
anv_cmd_buffer_gfx_push_constants(struct anv_cmd_buffer * cmd_buffer)558 anv_cmd_buffer_gfx_push_constants(struct anv_cmd_buffer *cmd_buffer)
559 {
560    struct anv_push_constants *data =
561       &cmd_buffer->state.gfx.base.push_constants;
562 
563    struct anv_state state =
564       anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
565                                          sizeof(struct anv_push_constants),
566                                          32 /* bottom 5 bits MBZ */);
567    memcpy(state.map, data, sizeof(struct anv_push_constants));
568 
569    return state;
570 }
571 
572 struct anv_state
anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer * cmd_buffer)573 anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer)
574 {
575    const struct intel_device_info *devinfo = cmd_buffer->device->info;
576    struct anv_push_constants *data =
577       &cmd_buffer->state.compute.base.push_constants;
578    struct anv_compute_pipeline *pipeline = cmd_buffer->state.compute.pipeline;
579    const struct elk_cs_prog_data *cs_prog_data = get_cs_prog_data(pipeline);
580    const struct anv_push_range *range = &pipeline->cs->bind_map.push_ranges[0];
581 
582    const struct intel_cs_dispatch_info dispatch =
583       elk_cs_get_dispatch_info(devinfo, cs_prog_data, NULL);
584    const unsigned total_push_constants_size =
585       elk_cs_push_const_total_size(cs_prog_data, dispatch.threads);
586    if (total_push_constants_size == 0)
587       return (struct anv_state) { .offset = 0 };
588 
589    const unsigned push_constant_alignment =
590       cmd_buffer->device->info->ver < 8 ? 32 : 64;
591    const unsigned aligned_total_push_constants_size =
592       ALIGN(total_push_constants_size, push_constant_alignment);
593    struct anv_state state =
594       anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
595                                          aligned_total_push_constants_size,
596                                          push_constant_alignment);
597 
598    void *dst = state.map;
599    const void *src = (char *)data + (range->start * 32);
600 
601    if (cs_prog_data->push.cross_thread.size > 0) {
602       memcpy(dst, src, cs_prog_data->push.cross_thread.size);
603       dst += cs_prog_data->push.cross_thread.size;
604       src += cs_prog_data->push.cross_thread.size;
605    }
606 
607    if (cs_prog_data->push.per_thread.size > 0) {
608       for (unsigned t = 0; t < dispatch.threads; t++) {
609          memcpy(dst, src, cs_prog_data->push.per_thread.size);
610 
611          uint32_t *subgroup_id = dst +
612             offsetof(struct anv_push_constants, cs.subgroup_id) -
613             (range->start * 32 + cs_prog_data->push.cross_thread.size);
614          *subgroup_id = t;
615 
616          dst += cs_prog_data->push.per_thread.size;
617       }
618    }
619 
620    return state;
621 }
622 
anv_CmdPushConstants(VkCommandBuffer commandBuffer,VkPipelineLayout layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)623 void anv_CmdPushConstants(
624     VkCommandBuffer                             commandBuffer,
625     VkPipelineLayout                            layout,
626     VkShaderStageFlags                          stageFlags,
627     uint32_t                                    offset,
628     uint32_t                                    size,
629     const void*                                 pValues)
630 {
631    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
632 
633    if (stageFlags & VK_SHADER_STAGE_ALL_GRAPHICS) {
634       struct anv_cmd_pipeline_state *pipe_state =
635          &cmd_buffer->state.gfx.base;
636 
637       memcpy(pipe_state->push_constants.client_data + offset, pValues, size);
638    }
639    if (stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) {
640       struct anv_cmd_pipeline_state *pipe_state =
641          &cmd_buffer->state.compute.base;
642 
643       memcpy(pipe_state->push_constants.client_data + offset, pValues, size);
644    }
645 
646    cmd_buffer->state.push_constants_dirty |= stageFlags;
647 }
648 
649 static struct anv_descriptor_set *
anv_cmd_buffer_push_descriptor_set(struct anv_cmd_buffer * cmd_buffer,VkPipelineBindPoint bind_point,struct anv_descriptor_set_layout * layout,uint32_t _set)650 anv_cmd_buffer_push_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
651                                    VkPipelineBindPoint bind_point,
652                                    struct anv_descriptor_set_layout *layout,
653                                    uint32_t _set)
654 {
655    struct anv_cmd_pipeline_state *pipe_state;
656 
657    switch (bind_point) {
658    case VK_PIPELINE_BIND_POINT_GRAPHICS:
659       pipe_state = &cmd_buffer->state.gfx.base;
660       break;
661 
662    case VK_PIPELINE_BIND_POINT_COMPUTE:
663       pipe_state = &cmd_buffer->state.compute.base;
664       break;
665 
666    default:
667       unreachable("invalid bind point");
668    }
669 
670    struct anv_push_descriptor_set **push_set =
671       &pipe_state->push_descriptors[_set];
672 
673    if (*push_set == NULL) {
674       *push_set = vk_zalloc(&cmd_buffer->vk.pool->alloc,
675                             sizeof(struct anv_push_descriptor_set), 8,
676                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
677       if (*push_set == NULL) {
678          anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_HOST_MEMORY);
679          return NULL;
680       }
681    }
682 
683    struct anv_descriptor_set *set = &(*push_set)->set;
684 
685    if (set->layout != layout) {
686       if (set->layout)
687          anv_descriptor_set_layout_unref(cmd_buffer->device, set->layout);
688       anv_descriptor_set_layout_ref(layout);
689       set->layout = layout;
690    }
691    set->size = anv_descriptor_set_layout_size(layout, 0);
692    set->buffer_view_count = layout->buffer_view_count;
693    set->descriptor_count = layout->descriptor_count;
694    set->buffer_views = (*push_set)->buffer_views;
695 
696    if (layout->descriptor_buffer_size &&
697        ((*push_set)->set_used_on_gpu ||
698         set->desc_mem.alloc_size < layout->descriptor_buffer_size)) {
699       /* The previous buffer is either actively used by some GPU command (so
700        * we can't modify it) or is too small.  Allocate a new one.
701        */
702       struct anv_state desc_mem =
703          anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream,
704                                 anv_descriptor_set_layout_descriptor_buffer_size(layout, 0),
705                                 ANV_UBO_ALIGNMENT);
706       if (set->desc_mem.alloc_size) {
707          /* TODO: Do we really need to copy all the time? */
708          memcpy(desc_mem.map, set->desc_mem.map,
709                 MIN2(desc_mem.alloc_size, set->desc_mem.alloc_size));
710       }
711       set->desc_mem = desc_mem;
712 
713       set->desc_addr = (struct anv_address) {
714          .bo = cmd_buffer->dynamic_state_stream.state_pool->block_pool.bo,
715          .offset = set->desc_mem.offset,
716       };
717 
718       enum isl_format format =
719          anv_isl_format_for_descriptor_type(cmd_buffer->device,
720                                             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
721 
722       const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;
723       set->desc_surface_state =
724          anv_state_stream_alloc(&cmd_buffer->surface_state_stream,
725                                 isl_dev->ss.size, isl_dev->ss.align);
726       anv_fill_buffer_surface_state(cmd_buffer->device,
727                                     set->desc_surface_state,
728                                     format, ISL_SWIZZLE_IDENTITY,
729                                     ISL_SURF_USAGE_CONSTANT_BUFFER_BIT,
730                                     set->desc_addr,
731                                     layout->descriptor_buffer_size, 1);
732    }
733 
734    return set;
735 }
736 
anv_CmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout _layout,uint32_t _set,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites)737 void anv_CmdPushDescriptorSetKHR(
738     VkCommandBuffer commandBuffer,
739     VkPipelineBindPoint pipelineBindPoint,
740     VkPipelineLayout _layout,
741     uint32_t _set,
742     uint32_t descriptorWriteCount,
743     const VkWriteDescriptorSet* pDescriptorWrites)
744 {
745    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
746    ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
747 
748    assert(_set < MAX_SETS);
749 
750    struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;
751 
752    struct anv_descriptor_set *set =
753       anv_cmd_buffer_push_descriptor_set(cmd_buffer, pipelineBindPoint,
754                                          set_layout, _set);
755    if (!set)
756       return;
757 
758    /* Go through the user supplied descriptors. */
759    for (uint32_t i = 0; i < descriptorWriteCount; i++) {
760       const VkWriteDescriptorSet *write = &pDescriptorWrites[i];
761 
762       switch (write->descriptorType) {
763       case VK_DESCRIPTOR_TYPE_SAMPLER:
764       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
765       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
766       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
767       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
768          for (uint32_t j = 0; j < write->descriptorCount; j++) {
769             anv_descriptor_set_write_image_view(cmd_buffer->device, set,
770                                                 write->pImageInfo + j,
771                                                 write->descriptorType,
772                                                 write->dstBinding,
773                                                 write->dstArrayElement + j);
774          }
775          break;
776 
777       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
778       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
779          for (uint32_t j = 0; j < write->descriptorCount; j++) {
780             ANV_FROM_HANDLE(anv_buffer_view, bview,
781                             write->pTexelBufferView[j]);
782 
783             anv_descriptor_set_write_buffer_view(cmd_buffer->device, set,
784                                                  write->descriptorType,
785                                                  bview,
786                                                  write->dstBinding,
787                                                  write->dstArrayElement + j);
788          }
789          break;
790 
791       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
792       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
793       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
794       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
795          for (uint32_t j = 0; j < write->descriptorCount; j++) {
796             ANV_FROM_HANDLE(anv_buffer, buffer, write->pBufferInfo[j].buffer);
797 
798             anv_descriptor_set_write_buffer(cmd_buffer->device, set,
799                                             &cmd_buffer->surface_state_stream,
800                                             write->descriptorType,
801                                             buffer,
802                                             write->dstBinding,
803                                             write->dstArrayElement + j,
804                                             write->pBufferInfo[j].offset,
805                                             write->pBufferInfo[j].range);
806          }
807          break;
808 
809       default:
810          break;
811       }
812    }
813 
814    anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint,
815                                       layout, _set, set, NULL, NULL);
816 }
817 
anv_CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer,VkDescriptorUpdateTemplate descriptorUpdateTemplate,VkPipelineLayout _layout,uint32_t _set,const void * pData)818 void anv_CmdPushDescriptorSetWithTemplateKHR(
819     VkCommandBuffer                             commandBuffer,
820     VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
821     VkPipelineLayout                            _layout,
822     uint32_t                                    _set,
823     const void*                                 pData)
824 {
825    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
826    VK_FROM_HANDLE(vk_descriptor_update_template, template,
827                   descriptorUpdateTemplate);
828    ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
829 
830    assert(_set < MAX_PUSH_DESCRIPTORS);
831 
832    struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;
833 
834    struct anv_descriptor_set *set =
835       anv_cmd_buffer_push_descriptor_set(cmd_buffer, template->bind_point,
836                                          set_layout, _set);
837    if (!set)
838       return;
839 
840    anv_descriptor_set_write_template(cmd_buffer->device, set,
841                                      &cmd_buffer->surface_state_stream,
842                                      template,
843                                      pData);
844 
845    anv_cmd_buffer_bind_descriptor_set(cmd_buffer, template->bind_point,
846                                       layout, _set, set, NULL, NULL);
847 }
848