1 /*
2 * Copyright © 2024 Collabora Ltd.
3 *
4 * Derived from tu_cmd_buffer.c which is:
5 * Copyright © 2016 Red Hat.
6 * Copyright © 2016 Bas Nieuwenhuizen
7 * Copyright © 2015 Intel Corporation
8 *
9 * SPDX-License-Identifier: MIT
10 */
11
12 #include "panvk_cmd_buffer.h"
13 #include "panvk_entrypoints.h"
14 #include "panvk_event.h"
15
16 #include "util/u_dynarray.h"
17
18 static void
panvk_add_set_event_operation(struct panvk_cmd_buffer * cmdbuf,struct panvk_event * event,enum panvk_cmd_event_op_type type)19 panvk_add_set_event_operation(struct panvk_cmd_buffer *cmdbuf,
20 struct panvk_event *event,
21 enum panvk_cmd_event_op_type type)
22 {
23 struct panvk_cmd_event_op op = {
24 .type = type,
25 .event = event,
26 };
27
28 if (cmdbuf->cur_batch == NULL) {
29 /* No open batch, let's create a new one so this operation happens in
30 * the right order.
31 */
32 panvk_per_arch(cmd_open_batch)(cmdbuf);
33 util_dynarray_append(&cmdbuf->cur_batch->event_ops,
34 struct panvk_cmd_event_op, op);
35 panvk_per_arch(cmd_close_batch)(cmdbuf);
36 } else {
37 /* Let's close the current batch so the operation executes before any
38 * future commands.
39 */
40 util_dynarray_append(&cmdbuf->cur_batch->event_ops,
41 struct panvk_cmd_event_op, op);
42 panvk_per_arch(cmd_close_batch)(cmdbuf);
43 panvk_per_arch(cmd_preload_fb_after_batch_split)(cmdbuf);
44 panvk_per_arch(cmd_open_batch)(cmdbuf);
45 }
46 }
47
48 static void
panvk_add_wait_event_operation(struct panvk_cmd_buffer * cmdbuf,struct panvk_event * event)49 panvk_add_wait_event_operation(struct panvk_cmd_buffer *cmdbuf,
50 struct panvk_event *event)
51 {
52 struct panvk_cmd_event_op op = {
53 .type = PANVK_EVENT_OP_WAIT,
54 .event = event,
55 };
56
57 if (cmdbuf->cur_batch == NULL) {
58 /* No open batch, let's create a new one and have it wait for this event. */
59 panvk_per_arch(cmd_open_batch)(cmdbuf);
60 util_dynarray_append(&cmdbuf->cur_batch->event_ops,
61 struct panvk_cmd_event_op, op);
62 } else {
63 /* Let's close the current batch so any future commands wait on the
64 * event signal operation.
65 */
66 if (cmdbuf->cur_batch->frag_jc.first_job ||
67 cmdbuf->cur_batch->vtc_jc.first_job) {
68 panvk_per_arch(cmd_close_batch)(cmdbuf);
69 panvk_per_arch(cmd_preload_fb_after_batch_split)(cmdbuf);
70 panvk_per_arch(cmd_open_batch)(cmdbuf);
71 }
72 util_dynarray_append(&cmdbuf->cur_batch->event_ops,
73 struct panvk_cmd_event_op, op);
74 }
75 }
76
77 VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(CmdSetEvent2)78 panvk_per_arch(CmdSetEvent2)(VkCommandBuffer commandBuffer, VkEvent _event,
79 const VkDependencyInfo *pDependencyInfo)
80 {
81 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
82 VK_FROM_HANDLE(panvk_event, event, _event);
83
84 /* vkCmdSetEvent cannot be called inside a render pass */
85 assert(cmdbuf->vk.render_pass == NULL);
86
87 panvk_add_set_event_operation(cmdbuf, event, PANVK_EVENT_OP_SET);
88 }
89
90 VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(CmdResetEvent2)91 panvk_per_arch(CmdResetEvent2)(VkCommandBuffer commandBuffer, VkEvent _event,
92 VkPipelineStageFlags2 stageMask)
93 {
94 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
95 VK_FROM_HANDLE(panvk_event, event, _event);
96
97 /* vkCmdResetEvent cannot be called inside a render pass */
98 assert(cmdbuf->vk.render_pass == NULL);
99
100 panvk_add_set_event_operation(cmdbuf, event, PANVK_EVENT_OP_RESET);
101 }
102
103 VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(CmdWaitEvents2)104 panvk_per_arch(CmdWaitEvents2)(VkCommandBuffer commandBuffer,
105 uint32_t eventCount, const VkEvent *pEvents,
106 const VkDependencyInfo *pDependencyInfos)
107 {
108 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
109
110 assert(eventCount > 0);
111
112 for (uint32_t i = 0; i < eventCount; i++) {
113 VK_FROM_HANDLE(panvk_event, event, pEvents[i]);
114 panvk_add_wait_event_operation(cmdbuf, event);
115 }
116 }
117