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 #ifndef LIBPLACEBO_VULKAN_H_
19 #define LIBPLACEBO_VULKAN_H_
20 
21 #include <vulkan/vulkan.h>
22 #include <libplacebo/gpu.h>
23 #include <libplacebo/swapchain.h>
24 
25 PL_API_BEGIN
26 
27 // Structure representing a VkInstance. Using this is not required.
28 typedef const PL_STRUCT(pl_vk_inst) {
29     VkInstance instance;
30 
31     // The Vulkan API version supported by this VkInstance.
32     uint32_t api_version;
33 
34     // The associated vkGetInstanceProcAddr pointer.
35     PFN_vkGetInstanceProcAddr get_proc_addr;
36 
37     // The instance extensions that were successfully enabled, including
38     // extensions enabled by libplacebo internally. May contain duplicates.
39     const char * const *extensions;
40     int num_extensions;
41 
42     // The instance layers that were successfully enabled, including
43     // layers enabled by libplacebo internally. May contain duplicates.
44     const char * const *layers;
45     int num_layers;
46 } *pl_vk_inst;
47 
48 struct pl_vk_inst_params {
49     // If set, enable the debugging and validation layers. These should
50     // generally be lightweight and relatively harmless to enable.
51     bool debug;
52 
53     // If set, also enable GPU-assisted verification and best practices
54     // layers. (Note: May cause substantial slowdown and/or result in lots of
55     // false positive spam)
56     bool debug_extra;
57 
58     // If nonzero, restricts the Vulkan API version to be at most this. This
59     // is only really useful for explicitly testing backwards compatibility.
60     uint32_t max_api_version;
61 
62     // Pointer to a user-provided `vkGetInstanceProcAddr`. If this is NULL,
63     // libplacebo will use the directly linked version (if available).
64     PFN_vkGetInstanceProcAddr get_proc_addr;
65 
66     // Enables extra instance extensions. Instance creation will fail if these
67     // extensions are not all supported. The user may use this to enable e.g.
68     // windowing system integration.
69     const char * const *extensions;
70     int num_extensions;
71 
72     // Enables extra optional instance extensions. These are opportunistically
73     // enabled if supported by the device, but otherwise skipped.
74     const char * const *opt_extensions;
75     int num_opt_extensions;
76 
77     // Enables extra layers. Instance creation will fail if these layers are
78     // not all supported.
79     //
80     // NOTE: Layers needed for required/optional extensions are automatically
81     // enabled. The user does not specifically need to enable layers related
82     // to extension support.
83     const char * const *layers;
84     int num_layers;
85 
86     // Enables extra optional layers. These are opportunistically enabled if
87     // supported by the platform, but otherwise skipped.
88     const char * const *opt_layers;
89     int num_opt_layers;
90 };
91 
92 extern const struct pl_vk_inst_params pl_vk_inst_default_params;
93 
94 // Helper function to simplify instance creation. The user could also bypass
95 // these helpers and do it manually, but this function is provided as a
96 // convenience. It also sets up a debug callback which forwards all vulkan
97 // messages to the `pl_log` callback.
98 pl_vk_inst pl_vk_inst_create(pl_log log, const struct pl_vk_inst_params *params);
99 void pl_vk_inst_destroy(pl_vk_inst *inst);
100 
101 struct pl_vulkan_queue {
102     uint32_t index; // Queue family index
103     uint32_t count; // Queue family count
104 };
105 
106 // Structure representing the actual vulkan device and associated GPU instance
107 typedef const PL_STRUCT(pl_vulkan) {
108     pl_gpu gpu;
109 
110     // The vulkan objects in use. The user may use this for their own purposes,
111     // but please note that the lifetime is tied to the lifetime of the
112     // pl_vulkan object, and must not be destroyed by the user. Note that the
113     // created vulkan device may have any number of queues and queue family
114     // assignments; so using it for queue submission commands is ill-advised.
115     VkInstance instance;
116     VkPhysicalDevice phys_device;
117     VkDevice device;
118 
119     // The Vulkan API version supported by this VkPhysicalDevice.
120     uint32_t api_version;
121 
122     // The device extensions that were successfully enabled, including
123     // extensions enabled by libplacebo internally. May contain duplicates.
124     const char * const *extensions;
125     int num_extensions;
126 
127     // The device features that were enabled at device creation time.
128     const VkPhysicalDeviceFeatures2 *features;
129 
130     // The explicit queue families we are using to provide a given capability,
131     // or {0} if no appropriate dedicated queue family exists for this
132     // operation type.
133     //
134     // It's guaranteed that `queue_graphics` is always set, but the existence
135     // of the other two is optional, and libplacebo will only set them if
136     // they are different from the graphics queue. Note that queue_compute
137     // and queue_transfer may refer to the same queue family index.
138     struct pl_vulkan_queue queue_graphics; // provides VK_QUEUE_GRAPHICS_BIT
139     struct pl_vulkan_queue queue_compute;  // provides VK_QUEUE_COMPUTE_BIT
140     struct pl_vulkan_queue queue_transfer; // provides VK_QUEUE_TRANSFER_BIT
141 
142     // For convenience, these are the same enabled queue families and their
143     // queue counts in list form. This list does not contain duplicates.
144     const struct pl_vulkan_queue *queues;
145     int num_queues;
146 } *pl_vulkan;
147 
148 struct pl_vulkan_params {
149     // The vulkan instance. Optional, if NULL then libplacebo will internally
150     // create a VkInstance with the settings from `instance_params`.
151     //
152     // Note: The VkInstance provided by the user *MUST* be created with a
153     // VkApplicationInfo.apiVersion of VK_API_VERSION_1_1 or higher.
154     VkInstance instance;
155 
156     // Pointer to `vkGetInstanceProcAddr`. If this is NULL, libplacebo will
157     // use the directly linked version (if available).
158     //
159     // Note: This overwrites the same value from `instance_params`.
160     PFN_vkGetInstanceProcAddr get_proc_addr;
161 
162     // Configures the settings used for creating an internal vulkan instance.
163     // May be NULL. Ignored if `instance` is set.
164     const struct pl_vk_inst_params *instance_params;
165 
166     // When choosing the device, rule out all devices that don't support
167     // presenting to this surface. When creating a device, enable all extensions
168     // needed to ensure we can present to this surface. Optional. Only legal
169     // when specifying an existing VkInstance to use.
170     VkSurfaceKHR surface;
171 
172     // --- Physical device selection options
173 
174     // The vulkan physical device. May be set by the caller to indicate the
175     // physical device to use. Otherwise, libplacebo will pick the "best"
176     // available GPU, based on the advertised device type. (i.e., it will
177     // prefer discrete GPUs over integrated GPUs). Only legal when specifying
178     // an existing VkInstance to use.
179     VkPhysicalDevice device;
180 
181     // When choosing the device, only choose a device with this exact name.
182     // This overrides `allow_software`. No effect if `device` is set. Note: A
183     // list of devices and their names are logged at level PL_LOG_INFO.
184     const char *device_name;
185 
186     // When choosing the device, only choose a device with this exact UUID.
187     // This overrides `allow_software` and `device_name`. No effect if `device`
188     // is set.
189     //
190     // Note: This relies on instance-level support for at least one of the
191     // VK_KHR_external_*_capabilities extensions (or vulkan 1.1). If this field
192     // is set when the instance does not support it, an error will be
193     // generated.
194     uint8_t device_uuid[16];
195 
196     // When choosing the device, controls whether or not to also allow software
197     // GPUs. No effect if `device` or `device_name` are set.
198     bool allow_software;
199 
200     // --- Logical device creation options
201 
202     // Controls whether or not to allow asynchronous transfers, using transfer
203     // queue families, if supported by the device. This can be significantly
204     // faster and more power efficient, and also allows streaming uploads in
205     // parallel with rendering commands. Enabled by default.
206     bool async_transfer;
207 
208     // Controls whether or not to allow asynchronous compute, using dedicated
209     // compute queue families, if supported by the device. On some devices,
210     // these can allow the GPU to schedule compute shaders in parallel with
211     // fragment shaders. Enabled by default.
212     bool async_compute;
213 
214     // Limits the number of queues to request. If left as 0, this will enable
215     // as many queues as the device supports. Multiple queues can result in
216     // improved efficiency when submitting multiple commands that can entirely
217     // or partially execute in parallel. Defaults to 1, since using more queues
218     // can actually decrease performance.
219     int queue_count;
220 
221     // Enables extra device extensions. Device creation will fail if these
222     // extensions are not all supported. The user may use this to enable e.g.
223     // interop extensions.
224     const char * const *extensions;
225     int num_extensions;
226 
227     // Enables extra optional device extensions. These are opportunistically
228     // enabled if supported by the device, but otherwise skipped.
229     const char * const *opt_extensions;
230     int num_opt_extensions;
231 
232     // Optional extra features to enable at device creation time. These are
233     // opportunistically enabled if supported by the physical device, but
234     // otherwise kept disabled. Users may include extra extension-specific
235     // features in the pNext chain, however these *must* all be
236     // extension-specific structs, i.e. the use of "meta-structs" like
237     // VkPhysicalDeviceVulkan11Features is not allowed.
238     const VkPhysicalDeviceFeatures2 *features;
239 
240     // --- Misc/debugging options
241 
242     // Restrict specific features to e.g. work around driver bugs, or simply
243     // for testing purposes
244     int max_glsl_version;       // limit the maximum GLSL version
245     bool disable_events;        // disables usage of VkEvent completely
246     uint32_t max_api_version;   // limit the maximum vulkan API version
247 };
248 
249 // Default/recommended parameters. Should generally be safe and efficient.
250 extern const struct pl_vulkan_params pl_vulkan_default_params;
251 
252 // Creates a new vulkan device based on the given parameters and initializes
253 // a new GPU. This function will internally initialize a VkDevice. There is
254 // currently no way to share a vulkan device with the caller. If `params` is
255 // left as NULL, it defaults to &pl_vulkan_default_params.
256 //
257 // Thread-safety: Safe
258 pl_vulkan pl_vulkan_create(pl_log log, const struct pl_vulkan_params *params);
259 
260 // Destroys the vulkan device and all associated objects, except for the
261 // VkInstance provided by the user.
262 //
263 // Note that all resources allocated from this vulkan object (e.g. via the
264 // `vk->ra` or using `pl_vulkan_create_swapchain`) *must* be explicitly
265 // destroyed by the user before calling this.
266 //
267 // Also note that this function will block until all in-flight GPU commands are
268 // finished processing. You can avoid this by manually calling `pl_gpu_finish`
269 // before `pl_vulkan_destroy`.
270 void pl_vulkan_destroy(pl_vulkan *vk);
271 
272 struct pl_vulkan_device_params {
273     // The instance to use. Required!
274     //
275     // Note: The VkInstance provided by the user *MUST* be created with a
276     // VkApplicationInfo.apiVersion of VK_API_VERSION_1_1 or higher.
277     VkInstance instance;
278 
279     // Mirrored from `pl_vulkan_params`. All of these fields are optional.
280     PFN_vkGetInstanceProcAddr get_proc_addr;
281     VkSurfaceKHR surface;
282     const char *device_name;
283     uint8_t device_uuid[16];
284     bool allow_software;
285 };
286 
287 // Helper function to choose the best VkPhysicalDevice, given a VkInstance.
288 // This uses the same logic as `pl_vulkan_create` uses internally. If no
289 // matching device was found, this returns VK_NULL_HANDLE.
290 VkPhysicalDevice pl_vulkan_choose_device(pl_log log,
291                               const struct pl_vulkan_device_params *params);
292 
293 struct pl_vulkan_swapchain_params {
294     // The surface to use for rendering. Required, the user is in charge of
295     // creating this. Must belong to the same VkInstance as `vk->instance`.
296     VkSurfaceKHR surface;
297 
298     // When choosing the initial surface format, prefer HDR formats over SDR
299     // formats, if any is available.
300     //
301     // Deprecated in favor of `pl_swapchain_colorspace_hint`, which overrides
302     // this parameter if called.
303     bool prefer_hdr PL_DEPRECATED;
304 
305     // The preferred presentation mode. See the vulkan documentation for more
306     // information about these. If the device/surface combination does not
307     // support this mode, libplacebo will fall back to VK_PRESENT_MODE_FIFO_KHR.
308     //
309     // Warning: Leaving this zero-initialized is the same as having specified
310     // VK_PRESENT_MODE_IMMEDIATE_KHR, which is probably not what the user
311     // wants!
312     VkPresentModeKHR present_mode;
313 
314     // Allow up to N in-flight frames. This essentially controls how many
315     // rendering commands may be queued up at the same time. See the
316     // documentation for `pl_swapchain_get_latency` for more information. For
317     // vulkan specifically, we are only able to wait until the GPU has finished
318     // rendering a frame - we are unable to wait until the display has actually
319     // finished displaying it. So this only provides a rough guideline.
320     // Optional, defaults to 3.
321     int swapchain_depth;
322 
323     // This suppresses automatic recreation of the swapchain when any call
324     // returns VK_SUBOPTIMAL_KHR. Normally, libplacebo will recreate the
325     // swapchain internally on the next `pl_swapchain_start_frame`. If enabled,
326     // clients are assumed to take care of swapchain recreations themselves, by
327     // calling `pl_swapchain_resize` as appropriate. libplacebo will tolerate
328     // the "suboptimal" status indefinitely.
329     bool allow_suboptimal;
330 };
331 
332 // Creates a new vulkan swapchain based on an existing VkSurfaceKHR. Using this
333 // function requires that the vulkan device was created with the
334 // VK_KHR_swapchain extension. The easiest way of accomplishing this is to set
335 // the `pl_vulkan_params.surface` explicitly at creation time.
336 pl_swapchain pl_vulkan_create_swapchain(pl_vulkan vk,
337                               const struct pl_vulkan_swapchain_params *params);
338 
339 // This will return true if the vulkan swapchain is internally detected
340 // as being suboptimal (VK_SUBOPTIMAL_KHR). This might be of use to clients
341 // who have `params->allow_suboptimal` enabled.
342 bool pl_vulkan_swapchain_suboptimal(pl_swapchain sw);
343 
344 // Vulkan interop API, for sharing a single VkDevice (and associated vulkan
345 // resources) directly with the API user. The use of this API is a bit sketchy
346 // and requires careful communication of Vulkan API state.
347 
348 struct pl_vulkan_import_params {
349     // The vulkan instance. Required.
350     //
351     // Note: The VkInstance provided by the user *MUST* be created with a
352     // VkApplicationInfo.apiVersion of VK_API_VERSION_1_1 or higher.
353     VkInstance instance;
354 
355     // Pointer to `vkGetInstanceProcAddr`. If this is NULL, libplacebo will
356     // use the directly linked version (if available).
357     PFN_vkGetInstanceProcAddr get_proc_addr;
358 
359     // The physical device selected by the user. Required.
360     VkPhysicalDevice phys_device;
361 
362     // The logical device created by the user. Required.
363     VkDevice device;
364 
365     // --- Logical device parameters
366 
367     // List of all device-level extensions that were enabled. (Instance-level
368     // extensions need not be re-specified here, since it's guaranteed that any
369     // instance-level extensions that device-level extensions depend on were
370     // enabled at the instance level)
371     const char * const *extensions;
372     int num_extensions;
373 
374     // Enabled queue families. At least `queue_graphics` is required.
375     //
376     // It's okay for multiple queue families to be specified with the same
377     // index, e.g. in the event that a dedicated compute queue also happens to
378     // be the dedicated transfer queue.
379     //
380     // It's also okay to leave the queue struct as {0} in the event that no
381     // dedicated queue exists for a given operation type. libplacebo will
382     // automatically fall back to using e.g. the graphics queue instead.
383     struct pl_vulkan_queue queue_graphics; // must support VK_QUEUE_GRAPHICS_BIT
384     struct pl_vulkan_queue queue_compute;  // must support VK_QUEUE_COMPUTE_BIT
385     struct pl_vulkan_queue queue_transfer; // must support VK_QUEUE_TRANSFER_BIT
386 
387     // Enabled VkPhysicalDeviceFeatures. May be left as NULL, in which case
388     // libplacebo will assume no extra device features were enabled.
389     const VkPhysicalDeviceFeatures2 *features;
390 
391     // --- Misc/debugging options
392 
393     // Restrict specific features to e.g. work around driver bugs, or simply
394     // for testing purposes. See `pl_vulkan_params` for a description of these.
395     int max_glsl_version;
396     bool disable_events;
397     uint32_t max_api_version;
398 };
399 
400 // Import an existing VkDevice instead of creating a new one, and wrap it into
401 // a `pl_vulkan` abstraction. It's safe to `pl_vulkan_destroy` this, which will
402 // destroy application state related to libplacebo but leave the underlying
403 // VkDevice intact.
404 pl_vulkan pl_vulkan_import(pl_log log, const struct pl_vulkan_import_params *params);
405 
406 struct pl_vulkan_wrap_params {
407     // The image itself. It *must* be usable concurrently by all of the queue
408     // family indices listed in `pl_vulkan->queues`. Note that this requires
409     // the use of VK_SHARING_MODE_CONCURRENT if `pl_vulkan->num_queues` is
410     // greater than 1. If this is difficult to achieve for the user, then
411     // `async_transfer` / `async_compute` should be turned off, which
412     // guarantees the use of only one queue family.
413     VkImage image;
414 
415     // The image's dimensions (unused dimensions must be 0)
416     int width;
417     int height;
418     int depth;
419 
420     // The image's format. libplacebo will try to map this to an equivalent
421     // pl_fmt. If no compatible pl_fmt is found, wrapping will fail.
422     VkFormat format;
423 
424     // The usage flags the image was created with. libplacebo will set the
425     // pl_tex capabilities to include whatever it can, as determined by the set
426     // of enabled usage flags.
427     VkImageUsageFlags usage;
428 
429     // Deprecated fields. These are now ignored entirely.
430     enum pl_tex_sample_mode sample_mode PL_DEPRECATED;
431     enum pl_tex_address_mode address_mode PL_DEPRECATED;
432 };
433 
434 // Wraps an external VkImage into a pl_tex abstraction. By default, the image
435 // is considered "held" by the user and must be released before calling any
436 // pl_tex_* API calls on it (see `pl_vulkan_release`).
437 //
438 // This wrapper can be destroyed by simply calling `pl_tex_destroy` on it,
439 // which will not destroy the underlying VkImage. If a pl_tex wrapper is
440 // destroyed while an image is not currently being held by the user, that
441 // image is left in an undefined state.
442 //
443 // Wrapping the same VkImage multiple times is undefined behavior, as is trying
444 // to wrap an image belonging to a different VkDevice than the one in use by
445 // `gpu`.
446 //
447 // This function may fail, in which case it returns NULL.
448 pl_tex pl_vulkan_wrap(pl_gpu gpu, const struct pl_vulkan_wrap_params *params);
449 
450 // For purely informative reasons, this contains a list of extensions and
451 // device features that libplacebo *can* make use of. These are all strictly
452 // optional, but provide a hint to the API user as to what might be worth
453 // enabling at device creation time.
454 //
455 // Note: This also includes physical device features provided by extensions.
456 // They are all provided using extension-specific features structs, rather
457 // than the more general purpose VkPhysicalDeviceVulkan11Features etc.
458 extern const char * const pl_vulkan_recommended_extensions[];
459 extern const int pl_vulkan_num_recommended_extensions;
460 extern const VkPhysicalDeviceFeatures2 pl_vulkan_recommended_features;
461 
462 // Analogous to `pl_vulkan_wrap`, this function takes any `pl_tex` (including
463 // ones created by `pl_tex_create`) and unwraps it to expose the underlying
464 // VkImage to the user. Unlike `pl_vulkan_wrap`, this `pl_tex` is *not*
465 // considered held after calling this function - the user must explicitly
466 // `pl_vulkan_hold` before accessing the VkImage.
467 //
468 // `out_format` and `out_flags` will be updated to hold the VkImage's
469 // format and usage flags. (Optional)
470 VkImage pl_vulkan_unwrap(pl_gpu gpu, pl_tex tex,
471                          VkFormat *out_format, VkImageUsageFlags *out_flags);
472 
473 // "Hold" a shared image. This will transition the image into the layout and
474 // access mode specified by the user, and fire the given semaphore (optional)
475 // when this is done. This marks the image as held. Attempting to perform any
476 // pl_tex_* operation (except pl_tex_destroy) on a held image is undefined
477 // behavior.
478 //
479 // Returns whether successful.
480 bool pl_vulkan_hold(pl_gpu gpu, pl_tex tex, VkImageLayout layout,
481                     VkAccessFlags access, VkSemaphore sem_out);
482 
483 // This function is similar to `pl_vulkan_hold`, except that rather than
484 // forcibly transitioning to a given layout, the user is instead informed about
485 // the current layout and access and is in charge of transitioning it to their
486 // own layout/access before using it. May be more convenient for some users.
487 //
488 // Returns whether successful.
489 bool pl_vulkan_hold_raw(pl_gpu gpu, pl_tex tex, VkImageLayout *layout,
490                         VkAccessFlags *access, VkSemaphore sem_out);
491 
492 // "Release" a shared image, meaning it is no longer held. `layout` and
493 // `access` describe the current state of the image at the point in time when
494 // the user is releasing it. Performing any operation on the VkImage underlying
495 // this `pl_tex` while it is not being held by the user is undefined behavior.
496 //
497 // If `sem_in` is specified, it must fire before libplacebo will actually use
498 // or modify the image. (Optional)
499 void pl_vulkan_release(pl_gpu gpu, pl_tex tex, VkImageLayout layout,
500                        VkAccessFlags access, VkSemaphore sem_in);
501 
502 PL_API_END
503 
504 #endif // LIBPLACEBO_VULKAN_H_
505