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