1 /* Copyright (C) 2010-2020 The RetroArch team 2 * 3 * --------------------------------------------------------------------------------------------- 4 * The following license statement only applies to this libretro API header (libretro_vulkan.h) 5 * --------------------------------------------------------------------------------------------- 6 * 7 * Permission is hereby granted, free of charge, 8 * to any person obtaining a copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #ifndef LIBRETRO_VULKAN_H__ 24 #define LIBRETRO_VULKAN_H__ 25 26 #include <libretro.h> 27 #include <vulkan/vulkan.h> 28 29 #define RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION 5 30 #define RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION 1 31 32 struct retro_vulkan_image 33 { 34 VkImageView image_view; 35 VkImageLayout image_layout; 36 VkImageViewCreateInfo create_info; 37 }; 38 39 typedef void (*retro_vulkan_set_image_t)(void *handle, 40 const struct retro_vulkan_image *image, 41 uint32_t num_semaphores, 42 const VkSemaphore *semaphores, 43 uint32_t src_queue_family); 44 45 typedef uint32_t (*retro_vulkan_get_sync_index_t)(void *handle); 46 typedef uint32_t (*retro_vulkan_get_sync_index_mask_t)(void *handle); 47 typedef void (*retro_vulkan_set_command_buffers_t)(void *handle, 48 uint32_t num_cmd, 49 const VkCommandBuffer *cmd); 50 typedef void (*retro_vulkan_wait_sync_index_t)(void *handle); 51 typedef void (*retro_vulkan_lock_queue_t)(void *handle); 52 typedef void (*retro_vulkan_unlock_queue_t)(void *handle); 53 typedef void (*retro_vulkan_set_signal_semaphore_t)(void *handle, VkSemaphore semaphore); 54 55 typedef const VkApplicationInfo *(*retro_vulkan_get_application_info_t)(void); 56 57 struct retro_vulkan_context 58 { 59 VkPhysicalDevice gpu; 60 VkDevice device; 61 VkQueue queue; 62 uint32_t queue_family_index; 63 VkQueue presentation_queue; 64 uint32_t presentation_queue_family_index; 65 }; 66 67 typedef bool (*retro_vulkan_create_device_t)( 68 struct retro_vulkan_context *context, 69 VkInstance instance, 70 VkPhysicalDevice gpu, 71 VkSurfaceKHR surface, 72 PFN_vkGetInstanceProcAddr get_instance_proc_addr, 73 const char **required_device_extensions, 74 unsigned num_required_device_extensions, 75 const char **required_device_layers, 76 unsigned num_required_device_layers, 77 const VkPhysicalDeviceFeatures *required_features); 78 79 typedef void (*retro_vulkan_destroy_device_t)(void); 80 81 /* Note on thread safety: 82 * The Vulkan API is heavily designed around multi-threading, and 83 * the libretro interface for it should also be threading friendly. 84 * A core should be able to build command buffers and submit 85 * command buffers to the GPU from any thread. 86 */ 87 88 struct retro_hw_render_context_negotiation_interface_vulkan 89 { 90 /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN. */ 91 enum retro_hw_render_context_negotiation_interface_type interface_type; 92 /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION. */ 93 unsigned interface_version; 94 95 /* If non-NULL, returns a VkApplicationInfo struct that the frontend can use instead of 96 * its "default" application info. 97 */ 98 retro_vulkan_get_application_info_t get_application_info; 99 100 /* If non-NULL, the libretro core will choose one or more physical devices, 101 * create one or more logical devices and create one or more queues. 102 * The core must prepare a designated PhysicalDevice, Device, Queue and queue family index 103 * which the frontend will use for its internal operation. 104 * 105 * If gpu is not VK_NULL_HANDLE, the physical device provided to the frontend must be this PhysicalDevice. 106 * The core is still free to use other physical devices. 107 * 108 * The frontend will request certain extensions and layers for a device which is created. 109 * The core must ensure that the queue and queue_family_index support GRAPHICS and COMPUTE. 110 * 111 * If surface is not VK_NULL_HANDLE, the core must consider presentation when creating the queues. 112 * If presentation to "surface" is supported on the queue, presentation_queue must be equal to queue. 113 * If not, a second queue must be provided in presentation_queue and presentation_queue_index. 114 * If surface is not VK_NULL_HANDLE, the instance from frontend will have been created with supported for 115 * VK_KHR_surface extension. 116 * 117 * The core is free to set its own queue priorities. 118 * Device provided to frontend is owned by the frontend, but any additional device resources must be freed by core 119 * in destroy_device callback. 120 * 121 * If this function returns true, a PhysicalDevice, Device and Queues are initialized. 122 * If false, none of the above have been initialized and the frontend will attempt 123 * to fallback to "default" device creation, as if this function was never called. 124 */ 125 retro_vulkan_create_device_t create_device; 126 127 /* If non-NULL, this callback is called similar to context_destroy for HW_RENDER_INTERFACE. 128 * However, it will be called even if context_reset was not called. 129 * This can happen if the context never succeeds in being created. 130 * destroy_device will always be called before the VkInstance 131 * of the frontend is destroyed if create_device was called successfully so that the core has a chance of 132 * tearing down its own device resources. 133 * 134 * Only auxillary resources should be freed here, i.e. resources which are not part of retro_vulkan_context. 135 */ 136 retro_vulkan_destroy_device_t destroy_device; 137 }; 138 139 struct retro_hw_render_interface_vulkan 140 { 141 /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN. */ 142 enum retro_hw_render_interface_type interface_type; 143 /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION. */ 144 unsigned interface_version; 145 146 /* Opaque handle to the Vulkan backend in the frontend 147 * which must be passed along to all function pointers 148 * in this interface. 149 * 150 * The rationale for including a handle here (which libretro v1 151 * doesn't currently do in general) is: 152 * 153 * - Vulkan cores should be able to be freely threaded without lots of fuzz. 154 * This would break frontends which currently rely on TLS 155 * to deal with multiple cores loaded at the same time. 156 * - Fixing this in general is TODO for an eventual libretro v2. 157 */ 158 void *handle; 159 160 /* The Vulkan instance the context is using. */ 161 VkInstance instance; 162 /* The physical device used. */ 163 VkPhysicalDevice gpu; 164 /* The logical device used. */ 165 VkDevice device; 166 167 /* Allows a core to fetch all its needed symbols without having to link 168 * against the loader itself. */ 169 PFN_vkGetDeviceProcAddr get_device_proc_addr; 170 PFN_vkGetInstanceProcAddr get_instance_proc_addr; 171 172 /* The queue the core must use to submit data. 173 * This queue and index must remain constant throughout the lifetime 174 * of the context. 175 * 176 * This queue will be the queue that supports graphics and compute 177 * if the device supports compute. 178 */ 179 VkQueue queue; 180 unsigned queue_index; 181 182 /* Before calling retro_video_refresh_t with RETRO_HW_FRAME_BUFFER_VALID, 183 * set which image to use for this frame. 184 * 185 * If num_semaphores is non-zero, the frontend will wait for the 186 * semaphores provided to be signaled before using the results further 187 * in the pipeline. 188 * 189 * Semaphores provided by a single call to set_image will only be 190 * waited for once (waiting for a semaphore resets it). 191 * E.g. set_image, video_refresh, and then another 192 * video_refresh without set_image, 193 * but same image will only wait for semaphores once. 194 * 195 * For this reason, ownership transfer will only occur if semaphores 196 * are waited on for a particular frame in the frontend. 197 * 198 * Using semaphores is optional for synchronization purposes, 199 * but if not using 200 * semaphores, an image memory barrier in vkCmdPipelineBarrier 201 * should be used in the graphics_queue. 202 * Example: 203 * 204 * vkCmdPipelineBarrier(cmd, 205 * srcStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 206 * dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 207 * image_memory_barrier = { 208 * srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 209 * dstAccessMask = VK_ACCESS_SHADER_READ_BIT, 210 * }); 211 * 212 * The use of pipeline barriers instead of semaphores is encouraged 213 * as it is simpler and more fine-grained. A layout transition 214 * must generally happen anyways which requires a 215 * pipeline barrier. 216 * 217 * The image passed to set_image must have imageUsage flags set to at least 218 * VK_IMAGE_USAGE_TRANSFER_SRC_BIT and VK_IMAGE_USAGE_SAMPLED_BIT. 219 * The core will naturally want to use flags such as 220 * VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT and/or 221 * VK_IMAGE_USAGE_TRANSFER_DST_BIT depending 222 * on how the final image is created. 223 * 224 * The image must also have been created with MUTABLE_FORMAT bit set if 225 * 8-bit formats are used, so that the frontend can reinterpret sRGB 226 * formats as it sees fit. 227 * 228 * Images passed to set_image should be created with TILING_OPTIMAL. 229 * The image layout should be transitioned to either 230 * VK_IMAGE_LAYOUT_GENERIC or VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. 231 * The actual image layout used must be set in image_layout. 232 * 233 * The image must be a 2D texture which may or not be layered 234 * and/or mipmapped. 235 * 236 * The image must be suitable for linear sampling. 237 * While the image_view is typically the only field used, 238 * the frontend may want to reinterpret the texture as sRGB vs. 239 * non-sRGB for example so the VkImageViewCreateInfo used to 240 * create the image view must also be passed in. 241 * 242 * The data in the pointer to the image struct will not be copied 243 * as the pNext field in create_info cannot be reliably deep-copied. 244 * The image pointer passed to set_image must be valid until 245 * retro_video_refresh_t has returned. 246 * 247 * If frame duping is used when passing NULL to retro_video_refresh_t, 248 * the frontend is free to either use the latest image passed to 249 * set_image or reuse the older pointer passed to set_image the 250 * frame RETRO_HW_FRAME_BUFFER_VALID was last used. 251 * 252 * Essentially, the lifetime of the pointer passed to 253 * retro_video_refresh_t should be extended if frame duping is used 254 * so that the frontend can reuse the older pointer. 255 * 256 * The image itself however, must not be touched by the core until 257 * wait_sync_index has been completed later. The frontend may perform 258 * layout transitions on the image, so even read-only access is not defined. 259 * The exception to read-only rule is if GENERAL layout is used for the image. 260 * In this case, the frontend is not allowed to perform any layout transitions, 261 * so concurrent reads from core and frontend are allowed. 262 * 263 * If frame duping is used, or if set_command_buffers is used, 264 * the frontend will not wait for any semaphores. 265 * 266 * The src_queue_family is used to specify which queue family 267 * the image is currently owned by. If using multiple queue families 268 * (e.g. async compute), the frontend will need to acquire ownership of the 269 * image before rendering with it and release the image afterwards. 270 * 271 * If src_queue_family is equal to the queue family (queue_index), 272 * no ownership transfer will occur. 273 * Similarly, if src_queue_family is VK_QUEUE_FAMILY_IGNORED, 274 * no ownership transfer will occur. 275 * 276 * The frontend will always release ownership back to src_queue_family. 277 * Waiting for frontend to complete with wait_sync_index() ensures that 278 * the frontend has released ownership back to the application. 279 * Note that in Vulkan, transfering ownership is a two-part process. 280 * 281 * Example frame: 282 * - core releases ownership from src_queue_index to queue_index with VkImageMemoryBarrier. 283 * - core calls set_image with src_queue_index. 284 * - Frontend will acquire the image with src_queue_index -> queue_index as well, completing the ownership transfer. 285 * - Frontend renders the frame. 286 * - Frontend releases ownership with queue_index -> src_queue_index. 287 * - Next time image is used, core must acquire ownership from queue_index ... 288 * 289 * Since the frontend releases ownership, we cannot necessarily dupe the frame because 290 * the core needs to make the roundtrip of ownership transfer. 291 */ 292 retro_vulkan_set_image_t set_image; 293 294 /* Get the current sync index for this frame which is obtained in 295 * frontend by calling e.g. vkAcquireNextImageKHR before calling 296 * retro_run(). 297 * 298 * This index will correspond to which swapchain buffer is currently 299 * the active one. 300 * 301 * Knowing this index is very useful for maintaining safe asynchronous CPU 302 * and GPU operation without stalling. 303 * 304 * The common pattern for synchronization is to receive fences when 305 * submitting command buffers to Vulkan (vkQueueSubmit) and add this fence 306 * to a list of fences for frame number get_sync_index(). 307 * 308 * Next time we receive the same get_sync_index(), we can wait for the 309 * fences from before, which will usually return immediately as the 310 * frontend will generally also avoid letting the GPU run ahead too much. 311 * 312 * After the fence has signaled, we know that the GPU has completed all 313 * GPU work related to work submitted in the frame we last saw get_sync_index(). 314 * 315 * This means we can safely reuse or free resources allocated in this frame. 316 * 317 * In theory, even if we wait for the fences correctly, it is not technically 318 * safe to write to the image we earlier passed to the frontend since we're 319 * not waiting for the frontend GPU jobs to complete. 320 * 321 * The frontend will guarantee that the appropriate pipeline barrier 322 * in graphics_queue has been used such that 323 * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT cannot 324 * start until the frontend is done with the image. 325 */ 326 retro_vulkan_get_sync_index_t get_sync_index; 327 328 /* Returns a bitmask of how many swapchain images we currently have 329 * in the frontend. 330 * 331 * If bit #N is set in the return value, get_sync_index can return N. 332 * Knowing this value is useful for preallocating per-frame management 333 * structures ahead of time. 334 * 335 * While this value will typically remain constant throughout the 336 * applications lifecycle, it may for example change if the frontend 337 * suddently changes fullscreen state and/or latency. 338 * 339 * If this value ever changes, it is safe to assume that the device 340 * is completely idle and all synchronization objects can be deleted 341 * right away as desired. 342 */ 343 retro_vulkan_get_sync_index_mask_t get_sync_index_mask; 344 345 /* Instead of submitting the command buffer to the queue first, the core 346 * can pass along its command buffer to the frontend, and the frontend 347 * will submit the command buffer together with the frontends command buffers. 348 * 349 * This has the advantage that the overhead of vkQueueSubmit can be 350 * amortized into a single call. For this mode, semaphores in set_image 351 * will be ignored, so vkCmdPipelineBarrier must be used to synchronize 352 * the core and frontend. 353 * 354 * The command buffers in set_command_buffers are only executed once, 355 * even if frame duping is used. 356 * 357 * If frame duping is used, set_image should be used for the frames 358 * which should be duped instead. 359 * 360 * Command buffers passed to the frontend with set_command_buffers 361 * must not actually be submitted to the GPU until retro_video_refresh_t 362 * is called. 363 * 364 * The frontend must submit the command buffer before submitting any 365 * other command buffers provided by set_command_buffers. */ 366 retro_vulkan_set_command_buffers_t set_command_buffers; 367 368 /* Waits on CPU for device activity for the current sync index to complete. 369 * This is useful since the core will not have a relevant fence to sync with 370 * when the frontend is submitting the command buffers. */ 371 retro_vulkan_wait_sync_index_t wait_sync_index; 372 373 /* If the core submits command buffers itself to any of the queues provided 374 * in this interface, the core must lock and unlock the frontend from 375 * racing on the VkQueue. 376 * 377 * Queue submission can happen on any thread. 378 * Even if queue submission happens on the same thread as retro_run(), 379 * the lock/unlock functions must still be called. 380 * 381 * NOTE: Queue submissions are heavy-weight. */ 382 retro_vulkan_lock_queue_t lock_queue; 383 retro_vulkan_unlock_queue_t unlock_queue; 384 385 /* Sets a semaphore which is signaled when the image in set_image can safely be reused. 386 * The semaphore is consumed next call to retro_video_refresh_t. 387 * The semaphore will be signalled even for duped frames. 388 * The semaphore will be signalled only once, so set_signal_semaphore should be called every frame. 389 * The semaphore may be VK_NULL_HANDLE, which disables semaphore signalling for next call to retro_video_refresh_t. 390 * 391 * This is mostly useful to support use cases where you're rendering to a single image that 392 * is recycled in a ping-pong fashion with the frontend to save memory (but potentially less throughput). 393 */ 394 retro_vulkan_set_signal_semaphore_t set_signal_semaphore; 395 }; 396 397 #endif 398