• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2022 Raspberry Pi Ltd
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 "v3dv_private.h"
25 #include "compiler/nir/nir_builder.h"
26 
27 #include "vk_common_entrypoints.h"
28 
29 static nir_shader *
get_set_event_cs()30 get_set_event_cs()
31 {
32    const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options();
33    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options,
34                                                   "set event cs");
35 
36    nir_def *buf =
37       nir_vulkan_resource_index(&b, 2, 32, nir_imm_int(&b, 0),
38                                 .desc_set = 0,
39                                 .binding = 0,
40                                 .desc_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
41 
42    nir_def *offset =
43       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 0, .range = 4);
44 
45    nir_def *value =
46       nir_load_push_constant(&b, 1, 8, nir_imm_int(&b, 0), .base = 4, .range = 4);
47 
48    nir_store_ssbo(&b, value, buf, offset,
49                   .access = 0, .write_mask = 0x1, .align_mul = 4);
50 
51    return b.shader;
52 }
53 
54 static nir_shader *
get_wait_event_cs()55 get_wait_event_cs()
56 {
57    const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options();
58    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options,
59                                                   "wait event cs");
60 
61    nir_def *buf =
62       nir_vulkan_resource_index(&b, 2, 32, nir_imm_int(&b, 0),
63                                 .desc_set = 0,
64                                 .binding = 0,
65                                 .desc_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
66 
67    nir_def *offset =
68       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 0, .range = 4);
69 
70    nir_loop *loop = nir_push_loop(&b);
71       nir_def *load =
72          nir_load_ssbo(&b, 1, 8, buf, offset, .access = 0, .align_mul = 4);
73       nir_def *value = nir_i2i32(&b, load);
74 
75       nir_if *if_stmt = nir_push_if(&b, nir_ieq_imm(&b, value, 1));
76       nir_jump(&b, nir_jump_break);
77       nir_pop_if(&b, if_stmt);
78    nir_pop_loop(&b, loop);
79 
80    return b.shader;
81 }
82 
83 static bool
create_event_pipelines(struct v3dv_device * device)84 create_event_pipelines(struct v3dv_device *device)
85 {
86    VkResult result;
87 
88    if (!device->events.descriptor_set_layout) {
89       /* Pipeline layout:
90        *  - 1 storage buffer for the BO with the events state.
91        *  - 2 push constants:
92        *    0B: offset of the event in the buffer (4 bytes).
93        *    4B: value for the event (1 byte), only used with the set_event_pipeline.
94        */
95       VkDescriptorSetLayoutBinding descriptor_set_layout_binding = {
96          .binding = 0,
97          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
98          .descriptorCount = 1,
99          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
100       };
101 
102       VkDescriptorSetLayoutCreateInfo descriptor_set_layout_info = {
103          .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
104          .bindingCount = 1,
105          .pBindings = &descriptor_set_layout_binding,
106       };
107 
108       result =
109          v3dv_CreateDescriptorSetLayout(v3dv_device_to_handle(device),
110                                         &descriptor_set_layout_info,
111                                         &device->vk.alloc,
112                                         &device->events.descriptor_set_layout);
113 
114       if (result != VK_SUCCESS)
115          return false;
116    }
117 
118    if (!device->events.pipeline_layout) {
119       VkPipelineLayoutCreateInfo pipeline_layout_info = {
120          .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
121          .setLayoutCount = 1,
122          .pSetLayouts = &device->events.descriptor_set_layout,
123          .pushConstantRangeCount = 1,
124          .pPushConstantRanges =
125              &(VkPushConstantRange) { VK_SHADER_STAGE_COMPUTE_BIT, 0, 5 },
126       };
127 
128       result =
129          v3dv_CreatePipelineLayout(v3dv_device_to_handle(device),
130                                    &pipeline_layout_info,
131                                    &device->vk.alloc,
132                                    &device->events.pipeline_layout);
133 
134       if (result != VK_SUCCESS)
135          return false;
136    }
137 
138    VkPipeline pipeline;
139 
140    if (!device->events.set_event_pipeline) {
141       nir_shader *set_event_cs_nir = get_set_event_cs();
142       result = v3dv_create_compute_pipeline_from_nir(device,
143                                                      set_event_cs_nir,
144                                                      device->events.pipeline_layout,
145                                                      &pipeline);
146       ralloc_free(set_event_cs_nir);
147       if (result != VK_SUCCESS)
148          return false;
149 
150       device->events.set_event_pipeline = pipeline;
151    }
152 
153    if (!device->events.wait_event_pipeline) {
154       nir_shader *wait_event_cs_nir = get_wait_event_cs();
155       result = v3dv_create_compute_pipeline_from_nir(device,
156                                                      wait_event_cs_nir,
157                                                      device->events.pipeline_layout,
158                                                      &pipeline);
159       ralloc_free(wait_event_cs_nir);
160       if (result != VK_SUCCESS)
161          return false;
162 
163       device->events.wait_event_pipeline = pipeline;
164    }
165 
166    return true;
167 }
168 
169 static void
destroy_event_pipelines(struct v3dv_device * device)170 destroy_event_pipelines(struct v3dv_device *device)
171 {
172    VkDevice _device = v3dv_device_to_handle(device);
173 
174    v3dv_DestroyPipeline(_device, device->events.set_event_pipeline,
175                          &device->vk.alloc);
176    device->events.set_event_pipeline = VK_NULL_HANDLE;
177 
178    v3dv_DestroyPipeline(_device, device->events.wait_event_pipeline,
179                          &device->vk.alloc);
180    device->events.wait_event_pipeline = VK_NULL_HANDLE;
181 
182    v3dv_DestroyPipelineLayout(_device, device->events.pipeline_layout,
183                               &device->vk.alloc);
184    device->events.pipeline_layout = VK_NULL_HANDLE;
185 
186    v3dv_DestroyDescriptorSetLayout(_device,
187                                    device->events.descriptor_set_layout,
188                                    &device->vk.alloc);
189    device->events.descriptor_set_layout = VK_NULL_HANDLE;
190 }
191 
192 static void
init_event(struct v3dv_device * device,struct v3dv_event * event,uint32_t index)193 init_event(struct v3dv_device *device, struct v3dv_event *event, uint32_t index)
194 {
195    vk_object_base_init(&device->vk, &event->base, VK_OBJECT_TYPE_EVENT);
196    event->index = index;
197    list_addtail(&event->link, &device->events.free_list);
198 }
199 
200 VkResult
v3dv_event_allocate_resources(struct v3dv_device * device)201 v3dv_event_allocate_resources(struct v3dv_device *device)
202 {
203    VkResult result = VK_SUCCESS;
204    VkDevice _device = v3dv_device_to_handle(device);
205 
206    /* BO with event states. Make sure we always align to a page size (4096)
207     * to ensure we use all the memory the kernel will allocate for the BO.
208     *
209     * CTS has tests that require over 8192 active events (yes, really) so
210     * let's make sure we allow for that.
211     */
212    const uint32_t bo_size = 3 * 4096;
213    struct v3dv_bo *bo = v3dv_bo_alloc(device, bo_size, "events", true);
214    if (!bo) {
215       result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
216       goto fail;
217    }
218 
219    device->events.bo = bo;
220 
221    if (!v3dv_bo_map(device, bo, bo_size)) {
222       result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
223       goto fail;
224    }
225 
226    /* Pre-allocate our events, each event requires 1 byte of BO storage */
227    device->events.event_count = bo_size;
228    device->events.events =
229       vk_zalloc2(&device->vk.alloc, NULL,
230                  device->events.event_count * sizeof(struct v3dv_event), 8,
231                  VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
232    if (!device->events.events) {
233       result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
234       goto fail;
235    }
236 
237    list_inithead(&device->events.free_list);
238    for (int i = 0; i < device->events.event_count; i++)
239       init_event(device, &device->events.events[i], i);
240 
241    /* Vulkan buffer for the event state BO */
242    VkBufferCreateInfo buf_info = {
243       .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
244       .size = bo->size,
245       .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
246    };
247    result = v3dv_CreateBuffer(_device, &buf_info, NULL,
248                               &device->events.buffer);
249    if (result != VK_SUCCESS)
250       goto fail;
251 
252    struct v3dv_device_memory *mem =
253       vk_object_zalloc(&device->vk, NULL, sizeof(*mem),
254                        VK_OBJECT_TYPE_DEVICE_MEMORY);
255    if (!mem) {
256       result = VK_ERROR_OUT_OF_HOST_MEMORY;
257       goto fail;
258    }
259 
260    mem->bo = bo;
261    mem->type = &device->pdevice->memory.memoryTypes[0];
262 
263    device->events.mem = v3dv_device_memory_to_handle(mem);
264    VkBindBufferMemoryInfo bind_info = {
265       .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
266       .buffer = device->events.buffer,
267       .memory = device->events.mem,
268       .memoryOffset = 0,
269    };
270    v3dv_BindBufferMemory2(_device, 1, &bind_info);
271 
272    /* Pipelines */
273    if (!create_event_pipelines(device)) {
274       result = VK_ERROR_OUT_OF_HOST_MEMORY;
275       goto fail;
276    }
277 
278    /* Descriptor pool & set to access the buffer */
279    VkDescriptorPoolSize pool_size = {
280       .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
281       .descriptorCount = 1,
282    };
283    VkDescriptorPoolCreateInfo pool_info = {
284       .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
285       .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
286       .maxSets = 1,
287       .poolSizeCount = 1,
288       .pPoolSizes = &pool_size,
289    };
290    result =
291       v3dv_CreateDescriptorPool(_device, &pool_info, NULL,
292                                 &device->events.descriptor_pool);
293 
294    if (result != VK_SUCCESS)
295       goto fail;
296 
297    VkDescriptorSetAllocateInfo alloc_info = {
298       .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
299       .descriptorPool = device->events.descriptor_pool,
300       .descriptorSetCount = 1,
301       .pSetLayouts = &device->events.descriptor_set_layout,
302    };
303    result = v3dv_AllocateDescriptorSets(_device, &alloc_info,
304                                          &device->events.descriptor_set);
305    if (result != VK_SUCCESS)
306       goto  fail;
307 
308    VkDescriptorBufferInfo desc_buf_info = {
309       .buffer = device->events.buffer,
310       .offset = 0,
311       .range = VK_WHOLE_SIZE,
312    };
313 
314    VkWriteDescriptorSet write = {
315       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
316       .dstSet = device->events.descriptor_set,
317       .dstBinding = 0,
318       .dstArrayElement = 0,
319       .descriptorCount = 1,
320       .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
321       .pBufferInfo = &desc_buf_info,
322    };
323    v3dv_UpdateDescriptorSets(_device, 1, &write, 0, NULL);
324 
325    return VK_SUCCESS;
326 
327 fail:
328    v3dv_event_free_resources(device);
329    return result;
330 }
331 
332 void
v3dv_event_free_resources(struct v3dv_device * device)333 v3dv_event_free_resources(struct v3dv_device *device)
334 {
335    if (device->events.bo) {
336       v3dv_bo_free(device, device->events.bo);
337       device->events.bo = NULL;
338    }
339 
340    if (device->events.events) {
341       vk_free2(&device->vk.alloc, NULL, device->events.events);
342       device->events.events = NULL;
343    }
344 
345    if (device->events.mem) {
346       vk_object_free(&device->vk, NULL,
347                      v3dv_device_memory_from_handle(device->events.mem));
348       device->events.mem = VK_NULL_HANDLE;
349    }
350 
351    v3dv_DestroyBuffer(v3dv_device_to_handle(device),
352                       device->events.buffer, NULL);
353    device->events.buffer = VK_NULL_HANDLE;
354 
355    v3dv_FreeDescriptorSets(v3dv_device_to_handle(device),
356                            device->events.descriptor_pool,
357                            1, &device->events.descriptor_set);
358    device->events.descriptor_set = VK_NULL_HANDLE;
359 
360    v3dv_DestroyDescriptorPool(v3dv_device_to_handle(device),
361                               device->events.descriptor_pool,
362                               NULL);
363    device->events.descriptor_pool = VK_NULL_HANDLE;
364 
365    destroy_event_pipelines(device);
366 }
367 
368 static struct v3dv_event *
allocate_event(struct v3dv_device * device)369 allocate_event(struct v3dv_device *device)
370 {
371    mtx_lock(&device->events.lock);
372    if (list_is_empty(&device->events.free_list)) {
373       mtx_unlock(&device->events.lock);
374       return NULL;
375    }
376 
377    struct v3dv_event *event =
378       list_first_entry(&device->events.free_list, struct v3dv_event, link);
379    list_del(&event->link);
380    mtx_unlock(&device->events.lock);
381 
382    return event;
383 }
384 
385 static void
free_event(struct v3dv_device * device,uint32_t index)386 free_event(struct v3dv_device *device, uint32_t index)
387 {
388    assert(index < device->events.event_count);
389    mtx_lock(&device->events.lock);
390    list_addtail(&device->events.events[index].link, &device->events.free_list);
391    mtx_unlock(&device->events.lock);
392 }
393 
394 static void
event_set_value(struct v3dv_device * device,struct v3dv_event * event,uint8_t value)395 event_set_value(struct v3dv_device *device,
396                        struct v3dv_event *event,
397                        uint8_t value)
398 {
399    assert(value == 0 || value == 1);
400    uint8_t *data = (uint8_t *) device->events.bo->map;
401    data[event->index] = value;
402 }
403 
404 static uint8_t
event_get_value(struct v3dv_device * device,struct v3dv_event * event)405 event_get_value(struct v3dv_device *device, struct v3dv_event *event)
406 {
407    uint8_t *data = (uint8_t *) device->events.bo->map;
408    return data[event->index];
409 }
410 
411 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateEvent(VkDevice _device,const VkEventCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkEvent * pEvent)412 v3dv_CreateEvent(VkDevice _device,
413                  const VkEventCreateInfo *pCreateInfo,
414                  const VkAllocationCallbacks *pAllocator,
415                  VkEvent *pEvent)
416 {
417    V3DV_FROM_HANDLE(v3dv_device, device, _device);
418    VkResult result = VK_SUCCESS;
419 
420    struct v3dv_event *event = allocate_event(device);
421    if (!event) {
422       result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
423       goto fail;
424    }
425 
426    event_set_value(device, event, 0);
427    *pEvent = v3dv_event_to_handle(event);
428    return VK_SUCCESS;
429 
430 fail:
431    return result;
432 }
433 
434 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyEvent(VkDevice _device,VkEvent _event,const VkAllocationCallbacks * pAllocator)435 v3dv_DestroyEvent(VkDevice _device,
436                   VkEvent _event,
437                   const VkAllocationCallbacks *pAllocator)
438 {
439    V3DV_FROM_HANDLE(v3dv_device, device, _device);
440    V3DV_FROM_HANDLE(v3dv_event, event, _event);
441 
442    if (!event)
443       return;
444 
445    free_event(device, event->index);
446 }
447 
448 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetEventStatus(VkDevice _device,VkEvent _event)449 v3dv_GetEventStatus(VkDevice _device, VkEvent _event)
450 {
451    V3DV_FROM_HANDLE(v3dv_device, device, _device);
452    V3DV_FROM_HANDLE(v3dv_event, event, _event);
453    return event_get_value(device, event) ? VK_EVENT_SET : VK_EVENT_RESET;
454 }
455 
456 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_SetEvent(VkDevice _device,VkEvent _event)457 v3dv_SetEvent(VkDevice _device, VkEvent _event)
458 {
459    V3DV_FROM_HANDLE(v3dv_device, device, _device);
460    V3DV_FROM_HANDLE(v3dv_event, event, _event);
461    event_set_value(device, event, 1);
462    return VK_SUCCESS;
463 }
464 
465 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_ResetEvent(VkDevice _device,VkEvent _event)466 v3dv_ResetEvent(VkDevice _device, VkEvent _event)
467 {
468    V3DV_FROM_HANDLE(v3dv_device, device, _device);
469    V3DV_FROM_HANDLE(v3dv_event, event, _event);
470    event_set_value(device, event, 0);
471    return VK_SUCCESS;
472 }
473 
474 static void
cmd_buffer_emit_set_event(struct v3dv_cmd_buffer * cmd_buffer,struct v3dv_event * event,uint8_t value)475 cmd_buffer_emit_set_event(struct v3dv_cmd_buffer *cmd_buffer,
476                           struct v3dv_event *event,
477                           uint8_t value)
478 {
479    assert(value == 0 || value == 1);
480 
481    struct v3dv_device *device = cmd_buffer->device;
482    VkCommandBuffer commandBuffer = v3dv_cmd_buffer_to_handle(cmd_buffer);
483 
484    v3dv_cmd_buffer_meta_state_push(cmd_buffer, true);
485 
486    v3dv_CmdBindPipeline(commandBuffer,
487                         VK_PIPELINE_BIND_POINT_COMPUTE,
488                         device->events.set_event_pipeline);
489 
490    v3dv_CmdBindDescriptorSets(commandBuffer,
491                               VK_PIPELINE_BIND_POINT_COMPUTE,
492                               device->events.pipeline_layout,
493                               0, 1, &device->events.descriptor_set, 0, NULL);
494 
495    assert(event->index < device->events.event_count);
496    uint32_t offset = event->index;
497    v3dv_CmdPushConstants(commandBuffer,
498                          device->events.pipeline_layout,
499                          VK_SHADER_STAGE_COMPUTE_BIT,
500                          0, 4, &offset);
501 
502    v3dv_CmdPushConstants(commandBuffer,
503                          device->events.pipeline_layout,
504                          VK_SHADER_STAGE_COMPUTE_BIT,
505                          4, 1, &value);
506 
507    vk_common_CmdDispatch(commandBuffer, 1, 1, 1);
508 
509    v3dv_cmd_buffer_meta_state_pop(cmd_buffer, false);
510 }
511 
512 static void
cmd_buffer_emit_wait_event(struct v3dv_cmd_buffer * cmd_buffer,struct v3dv_event * event)513 cmd_buffer_emit_wait_event(struct v3dv_cmd_buffer *cmd_buffer,
514                            struct v3dv_event *event)
515 {
516    struct v3dv_device *device = cmd_buffer->device;
517    VkCommandBuffer commandBuffer = v3dv_cmd_buffer_to_handle(cmd_buffer);
518 
519    v3dv_cmd_buffer_meta_state_push(cmd_buffer, true);
520 
521    v3dv_CmdBindPipeline(commandBuffer,
522                         VK_PIPELINE_BIND_POINT_COMPUTE,
523                         device->events.wait_event_pipeline);
524 
525    v3dv_CmdBindDescriptorSets(commandBuffer,
526                               VK_PIPELINE_BIND_POINT_COMPUTE,
527                               device->events.pipeline_layout,
528                               0, 1, &device->events.descriptor_set, 0, NULL);
529 
530    assert(event->index < device->events.event_count);
531    uint32_t offset = event->index;
532    v3dv_CmdPushConstants(commandBuffer,
533                          device->events.pipeline_layout,
534                          VK_SHADER_STAGE_COMPUTE_BIT,
535                          0, 4, &offset);
536 
537    vk_common_CmdDispatch(commandBuffer, 1, 1, 1);
538 
539    v3dv_cmd_buffer_meta_state_pop(cmd_buffer, false);
540 }
541 
542 VKAPI_ATTR void VKAPI_CALL
v3dv_CmdSetEvent2(VkCommandBuffer commandBuffer,VkEvent _event,const VkDependencyInfo * pDependencyInfo)543 v3dv_CmdSetEvent2(VkCommandBuffer commandBuffer,
544                   VkEvent _event,
545                   const VkDependencyInfo *pDependencyInfo)
546 {
547    V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
548    V3DV_FROM_HANDLE(v3dv_event, event, _event);
549 
550    /* Event (re)sets can only happen outside a render pass instance so we
551     * should not be in the middle of job recording.
552     */
553    assert(cmd_buffer->state.pass == NULL);
554    assert(cmd_buffer->state.job == NULL);
555 
556    /* We need to add the compute stage to the dstStageMask of all dependencies,
557     * so let's go ahead and patch the dependency info we receive.
558     */
559    struct v3dv_device *device = cmd_buffer->device;
560 
561    uint32_t memory_barrier_count = pDependencyInfo->memoryBarrierCount;
562    VkMemoryBarrier2 *memory_barriers = memory_barrier_count ?
563       vk_alloc2(&device->vk.alloc, NULL,
564                 memory_barrier_count * sizeof(memory_barriers[0]), 8,
565                 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) : NULL;
566    for (int i = 0; i < memory_barrier_count; i++) {
567       memory_barriers[i] = pDependencyInfo->pMemoryBarriers[i];
568       memory_barriers[i].dstStageMask |= VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
569    }
570 
571    uint32_t buffer_barrier_count = pDependencyInfo->bufferMemoryBarrierCount;
572    VkBufferMemoryBarrier2 *buffer_barriers = buffer_barrier_count ?
573       vk_alloc2(&device->vk.alloc, NULL,
574                 buffer_barrier_count * sizeof(buffer_barriers[0]), 8,
575                 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) : NULL;
576    for (int i = 0; i < buffer_barrier_count; i++) {
577       buffer_barriers[i] = pDependencyInfo->pBufferMemoryBarriers[i];
578       buffer_barriers[i].dstStageMask |= VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
579    }
580 
581    uint32_t image_barrier_count = pDependencyInfo->imageMemoryBarrierCount;
582    VkImageMemoryBarrier2 *image_barriers = image_barrier_count ?
583       vk_alloc2(&device->vk.alloc, NULL,
584                 image_barrier_count * sizeof(image_barriers[0]), 8,
585                 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) : NULL;
586    for (int i = 0; i < image_barrier_count; i++) {
587       image_barriers[i] = pDependencyInfo->pImageMemoryBarriers[i];
588       image_barriers[i].dstStageMask |= VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
589    }
590 
591    VkDependencyInfo info = {
592       .sType = pDependencyInfo->sType,
593       .dependencyFlags = pDependencyInfo->dependencyFlags,
594       .memoryBarrierCount = memory_barrier_count,
595       .pMemoryBarriers = memory_barriers,
596       .bufferMemoryBarrierCount = buffer_barrier_count,
597       .pBufferMemoryBarriers = buffer_barriers,
598       .imageMemoryBarrierCount = image_barrier_count,
599       .pImageMemoryBarriers = image_barriers,
600    };
601 
602    v3dv_cmd_buffer_emit_pipeline_barrier(cmd_buffer, &info);
603 
604    cmd_buffer_emit_set_event(cmd_buffer, event, 1);
605 
606    if (memory_barriers)
607       vk_free2(&device->vk.alloc, NULL, memory_barriers);
608    if (buffer_barriers)
609       vk_free2(&device->vk.alloc, NULL, buffer_barriers);
610    if (image_barriers)
611       vk_free2(&device->vk.alloc, NULL, image_barriers);
612 }
613 
614 VKAPI_ATTR void VKAPI_CALL
v3dv_CmdResetEvent2(VkCommandBuffer commandBuffer,VkEvent _event,VkPipelineStageFlags2 stageMask)615 v3dv_CmdResetEvent2(VkCommandBuffer commandBuffer,
616                     VkEvent _event,
617                     VkPipelineStageFlags2 stageMask)
618 {
619    V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
620    V3DV_FROM_HANDLE(v3dv_event, event, _event);
621 
622    /* Event (re)sets can only happen outside a render pass instance so we
623     * should not be in the middle of job recording.
624     */
625    assert(cmd_buffer->state.pass == NULL);
626    assert(cmd_buffer->state.job == NULL);
627 
628    VkMemoryBarrier2 barrier = {
629       .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
630       .srcStageMask = stageMask,
631       .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
632    };
633    VkDependencyInfo info = {
634       .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
635       .memoryBarrierCount = 1,
636       .pMemoryBarriers = &barrier,
637    };
638    v3dv_cmd_buffer_emit_pipeline_barrier(cmd_buffer, &info);
639 
640    cmd_buffer_emit_set_event(cmd_buffer, event, 0);
641 }
642 
643 VKAPI_ATTR void VKAPI_CALL
v3dv_CmdWaitEvents2(VkCommandBuffer commandBuffer,uint32_t eventCount,const VkEvent * pEvents,const VkDependencyInfo * pDependencyInfo)644 v3dv_CmdWaitEvents2(VkCommandBuffer commandBuffer,
645                     uint32_t eventCount,
646                     const VkEvent *pEvents,
647                     const VkDependencyInfo *pDependencyInfo)
648 {
649    V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
650    for (uint32_t i = 0; i < eventCount; i++) {
651       struct v3dv_event *event = v3dv_event_from_handle(pEvents[i]);;
652       cmd_buffer_emit_wait_event(cmd_buffer, event);
653    }
654 
655    /* We need to add the compute stage to the srcStageMask of all dependencies,
656     * so let's go ahead and patch the dependency info we receive.
657     */
658    struct v3dv_device *device = cmd_buffer->device;
659    for (int e = 0; e < eventCount; e++) {
660       const VkDependencyInfo *info = &pDependencyInfo[e];
661 
662       uint32_t memory_barrier_count = info->memoryBarrierCount;
663       VkMemoryBarrier2 *memory_barriers = memory_barrier_count ?
664          vk_alloc2(&device->vk.alloc, NULL,
665                    memory_barrier_count * sizeof(memory_barriers[0]), 8,
666                    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) : NULL;
667       for (int i = 0; i < memory_barrier_count; i++) {
668          memory_barriers[i] = info->pMemoryBarriers[i];
669          memory_barriers[i].srcStageMask |= VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
670       }
671 
672       uint32_t buffer_barrier_count = info->bufferMemoryBarrierCount;
673       VkBufferMemoryBarrier2 *buffer_barriers = buffer_barrier_count ?
674          vk_alloc2(&device->vk.alloc, NULL,
675                    buffer_barrier_count * sizeof(buffer_barriers[0]), 8,
676                    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) : NULL;
677       for (int i = 0; i < buffer_barrier_count; i++) {
678          buffer_barriers[i] = info->pBufferMemoryBarriers[i];
679          buffer_barriers[i].srcStageMask |= VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
680       }
681 
682       uint32_t image_barrier_count = info->imageMemoryBarrierCount;
683       VkImageMemoryBarrier2 *image_barriers = image_barrier_count ?
684          vk_alloc2(&device->vk.alloc, NULL,
685                    image_barrier_count * sizeof(image_barriers[0]), 8,
686                    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) : NULL;
687       for (int i = 0; i < image_barrier_count; i++) {
688          image_barriers[i] = info->pImageMemoryBarriers[i];
689          image_barriers[i].srcStageMask |= VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
690       }
691 
692       VkDependencyInfo new_info = {
693          .sType = info->sType,
694          .dependencyFlags = info->dependencyFlags,
695          .memoryBarrierCount = memory_barrier_count,
696          .pMemoryBarriers = memory_barriers,
697          .bufferMemoryBarrierCount = buffer_barrier_count,
698          .pBufferMemoryBarriers = buffer_barriers,
699          .imageMemoryBarrierCount = image_barrier_count,
700          .pImageMemoryBarriers = image_barriers,
701       };
702 
703       v3dv_cmd_buffer_emit_pipeline_barrier(cmd_buffer, &new_info);
704 
705       if (memory_barriers)
706          vk_free2(&device->vk.alloc, NULL, memory_barriers);
707       if (buffer_barriers)
708          vk_free2(&device->vk.alloc, NULL, buffer_barriers);
709       if (image_barriers)
710          vk_free2(&device->vk.alloc, NULL, image_barriers);
711    }
712 }
713