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