1 /*
2  * This file is part of libplacebo.
3  *
4  * libplacebo is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * libplacebo is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #pragma once
19 #include "common.h"
20 
21 // Since lots of vulkan operations need to be done lazily once the affected
22 // resources are no longer in use, provide an abstraction for tracking these.
23 // In practice, these are only checked and run when submitting new commands, so
24 // the actual execution may be delayed by a frame.
25 typedef void (*vk_cb)(void *p, void *arg);
26 
27 struct vk_callback {
28     vk_cb run;
29     void *priv;
30     void *arg;
31 };
32 
33 // Associate a callback with the completion of all currently pending commands.
34 // This will essentially run once the device is completely idle.
35 void vk_dev_callback(struct vk_ctx *vk, vk_cb callback,
36                      const void *priv, const void *arg);
37 
38 // Helper wrapper around command buffers that also track dependencies,
39 // callbacks and synchronization primitives
40 //
41 // Thread-safety: Unsafe
42 struct vk_cmd {
43     struct vk_cmdpool *pool; // pool it was allocated from
44     VkQueue queue;           // the submission queue (for recording/pending)
45     VkCommandBuffer buf;     // the command buffer itself
46     VkFence fence;           // the fence guards cmd buffer reuse
47     // The semaphores represent dependencies that need to complete before
48     // this command can be executed. These are *not* owned by the vk_cmd
49     PL_ARRAY(VkSemaphore) deps;
50     PL_ARRAY(VkPipelineStageFlags) depstages;
51     // The signals represent semaphores that fire once the command finishes
52     // executing. These are also not owned by the vk_cmd
53     PL_ARRAY(VkSemaphore) sigs;
54     // Since VkFences are useless, we have to manually track "callbacks"
55     // to fire once the VkFence completes. These are used for multiple purposes,
56     // ranging from garbage collection (resource deallocation) to fencing.
57     PL_ARRAY(struct vk_callback) callbacks;
58     // Abstract objects associated with this command. Can be used to
59     // selectively flush.
60     PL_ARRAY(const void *) objs;
61 };
62 
63 // Associate a callback with the completion of the current command. This
64 // function will be run once the command completes, or shortly thereafter.
65 void vk_cmd_callback(struct vk_cmd *cmd, vk_cb callback,
66                      const void *priv, const void *arg);
67 
68 // Associate a raw dependency for the current command. This semaphore must
69 // signal by the corresponding stage before the command may execute.
70 void vk_cmd_dep(struct vk_cmd *cmd, VkSemaphore dep, VkPipelineStageFlags stage);
71 
72 // Associate an object with a command. This can be used to partially flush
73 // commands only involving the object in question.
74 void vk_cmd_obj(struct vk_cmd *cmd, const void *obj);
75 
76 // Associate a raw signal with the current command. This semaphore will signal
77 // after the command completes.
78 void vk_cmd_sig(struct vk_cmd *cmd, VkSemaphore sig);
79 
80 enum vk_wait_type {
81     VK_WAIT_NONE,    // no synchronization needed
82     VK_WAIT_BARRIER, // synchronization via pipeline barriers
83     VK_WAIT_EVENT,   // synchronization via events
84 };
85 
86 // Signal abstraction: represents an abstract synchronization mechanism.
87 // Internally, this may either resolve as a semaphore or an event depending
88 // on whether the appropriate conditions are met.
89 //
90 // Thread-safety: Unsafe
91 struct vk_signal;
92 
93 // Generates a signal after the execution of all previous commands matching the
94 // given the pipeline stage. The signal is owned by the caller, and must be
95 // consumed with vk_cmd_wait or released with vk_signal_cancel in order to
96 // free the resources.
97 struct vk_signal *vk_cmd_signal(struct vk_ctx *vk, struct vk_cmd *cmd,
98                                 VkPipelineStageFlags stage);
99 
100 // Consumes a previously generated signal. This signal must fire by the
101 // indicated stage before the command can run. This function takes over
102 // ownership of the signal (and the signal will be released/reused
103 // automatically)
104 //
105 // The return type indicates what the caller needs to do:
106 //   VK_SIGNAL_NONE:    no further handling needed, caller can use TOP_OF_PIPE
107 //   VK_SIGNAL_BARRIER: caller must use pipeline barrier from last stage
108 //   VK_SIGNAL_EVENT:   caller must use VkEvent from last stage
109 //                      (never returned if out_event is NULL)
110 enum vk_wait_type vk_cmd_wait(struct vk_ctx *vk, struct vk_cmd *cmd,
111                               struct vk_signal **sigptr,
112                               VkPipelineStageFlags stage,
113                               VkEvent *out_event);
114 
115 // Destroys a currently pending signal, for example if the resource is no
116 // longer relevant.
117 void vk_signal_destroy(struct vk_ctx *vk, struct vk_signal **sig);
118 
119 // Command pool / queue family hybrid abstraction
120 struct vk_cmdpool {
121     VkQueueFamilyProperties props;
122     int qf; // queue family index
123     VkCommandPool pool;
124     VkQueue *queues;
125     int num_queues;
126     int idx_queues;
127     // Command buffers associated with this queue. These are available for
128     // re-recording
129     PL_ARRAY(struct vk_cmd *) cmds;
130 };
131 
132 // Set up a vk_cmdpool corresponding to a queue family.
133 struct vk_cmdpool *vk_cmdpool_create(struct vk_ctx *vk,
134                                      VkDeviceQueueCreateInfo qinfo,
135                                      VkQueueFamilyProperties props);
136 
137 void vk_cmdpool_destroy(struct vk_ctx *vk, struct vk_cmdpool *pool);
138 
139 // Fetch a command buffer from a command pool and begin recording to it.
140 // Returns NULL on failure.
141 struct vk_cmd *vk_cmd_begin(struct vk_ctx *vk, struct vk_cmdpool *pool);
142 
143 // Finish recording a command buffer and queue it for execution. This function
144 // takes over ownership of **cmd, and sets *cmd to NULL in doing so.
145 bool vk_cmd_queue(struct vk_ctx *vk, struct vk_cmd **cmd);
146 
147 // Block until some commands complete executing. This is the only function that
148 // actually processes the callbacks. Will wait at most `timeout` nanoseconds
149 // for the completion of any command. The timeout may also be passed as 0, in
150 // which case this function will not block, but only poll for completed
151 // commands. Returns whether any forward progress was made.
152 //
153 // This does *not* flush any queued commands, forgetting to do so may result
154 // in infinite loops if waiting for the completion of callbacks that were
155 // never flushed!
156 bool vk_poll_commands(struct vk_ctx *vk, uint64_t timeout);
157 
158 // Flush all currently queued commands. Returns whether successful. Failed
159 // commands will be implicitly dropped.
160 bool vk_flush_commands(struct vk_ctx *vk);
161 
162 // Like `vk_flush_commands`, but only flushes up to the last command involving
163 // `obj`, inclusive. If `obj` is NULL, behaves as `vk_flush_commands`.
164 bool vk_flush_obj(struct vk_ctx *vk, const void *obj);
165 
166 // Rotate through queues in each command pool. Call this once per frame, after
167 // submitting all of the command buffers for that frame. Calling this more
168 // often than that is possible but bad for performance.
169 void vk_rotate_queues(struct vk_ctx *vk);
170 
171 // Wait until all commands are complete, i.e. the device is idle. This is
172 // basically equivalent to calling `vk_poll_commands` with a timeout of
173 // UINT64_MAX until it returns `false`.
174 void vk_wait_idle(struct vk_ctx *vk);
175