RetroArch
libretro_vulkan.h
Go to the documentation of this file.
1 /* Copyright (C) 2010-2018 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 
33 {
34  VkImageView image_view;
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);
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 
58 {
59  VkPhysicalDevice gpu;
60  VkDevice device;
61  VkQueue queue;
65 };
66 
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 
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 
89 {
90  /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN. */
92  /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION. */
94 
95  /* If non-NULL, returns a VkApplicationInfo struct that the frontend can use instead of
96  * its "default" application info.
97  */
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  */
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  */
137 };
138 
140 {
141  /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN. */
143  /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN_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. */
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  */
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  */
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  */
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. */
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. */
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. */
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  */
395 };
396 
397 #endif
398 
retro_vulkan_get_sync_index_t get_sync_index
Definition: libretro_vulkan.h:326
VkImageLayout image_layout
Definition: libretro_vulkan.h:35
retro_vulkan_set_image_t set_image
Definition: libretro_vulkan.h:292
retro_vulkan_set_signal_semaphore_t set_signal_semaphore
Definition: libretro_vulkan.h:394
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetDeviceProcAddr)(VkDevice device, const char *pName)
Definition: vulkan_core.h:2731
PFN_vkGetInstanceProcAddr get_instance_proc_addr
Definition: libretro_vulkan.h:170
unsigned interface_version
Definition: libretro_vulkan.h:93
VkPhysicalDevice gpu
Definition: libretro_vulkan.h:163
void(* retro_vulkan_set_command_buffers_t)(void *handle, uint32_t num_cmd, const VkCommandBuffer *cmd)
Definition: libretro_vulkan.h:47
retro_vulkan_create_device_t create_device
Definition: libretro_vulkan.h:125
VkInstance instance
Definition: libretro_vulkan.h:161
void(* retro_vulkan_set_image_t)(void *handle, const struct retro_vulkan_image *image, uint32_t num_semaphores, const VkSemaphore *semaphores, uint32_t src_queue_family)
Definition: libretro_vulkan.h:39
PFN_vkGetDeviceProcAddr get_device_proc_addr
Definition: libretro_vulkan.h:169
typedef void(__stdcall *PFN_DESTRUCTION_CALLBACK)(void *pData)
unsigned queue_index
Definition: libretro_vulkan.h:180
typedef bool(RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index
retro_hw_render_interface_type
Definition: libretro.h:1203
uint32_t(* retro_vulkan_get_sync_index_mask_t)(void *handle)
Definition: libretro_vulkan.h:46
VkQueue queue
Definition: libretro_vulkan.h:61
Definition: libretro_vulkan.h:139
VkImageViewCreateInfo create_info
Definition: libretro_vulkan.h:36
VkImageLayout
Definition: vulkan_core.h:798
uint32_t queue_family_index
Definition: libretro_vulkan.h:62
ubyte cmd
Definition: wiiuse_internal.h:319
VkPhysicalDevice gpu
Definition: libretro_vulkan.h:59
void(* retro_vulkan_lock_queue_t)(void *handle)
Definition: libretro_vulkan.h:51
retro_vulkan_get_application_info_t get_application_info
Definition: libretro_vulkan.h:98
VkImageView image_view
Definition: libretro_vulkan.h:34
Definition: vulkan_core.h:1674
void(* retro_vulkan_set_signal_semaphore_t)(void *handle, VkSemaphore semaphore)
Definition: libretro_vulkan.h:53
Definition: vulkan_core.h:1615
VkQueue queue
Definition: libretro_vulkan.h:179
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: glext.h:6305
Definition: libretro_vulkan.h:32
retro_hw_render_context_negotiation_interface_type
Definition: libretro.h:1257
uint32_t(* retro_vulkan_get_sync_index_t)(void *handle)
Definition: libretro_vulkan.h:45
void(* retro_vulkan_unlock_queue_t)(void *handle)
Definition: libretro_vulkan.h:52
retro_vulkan_wait_sync_index_t wait_sync_index
Definition: libretro_vulkan.h:371
VkQueue presentation_queue
Definition: libretro_vulkan.h:63
void(* retro_vulkan_destroy_device_t)(void)
Definition: libretro_vulkan.h:79
enum retro_hw_render_interface_type interface_type
Definition: libretro_vulkan.h:142
VkDevice device
Definition: libretro_vulkan.h:60
bool(* retro_vulkan_create_device_t)(struct retro_vulkan_context *context, VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface, PFN_vkGetInstanceProcAddr get_instance_proc_addr, const char **required_device_extensions, unsigned num_required_device_extensions, const char **required_device_layers, unsigned num_required_device_layers, const VkPhysicalDeviceFeatures *required_features)
Definition: libretro_vulkan.h:67
uint32_t presentation_queue_family_index
Definition: libretro_vulkan.h:64
enum retro_hw_render_context_negotiation_interface_type interface_type
Definition: libretro_vulkan.h:91
retro_vulkan_destroy_device_t destroy_device
Definition: libretro_vulkan.h:136
Definition: libretro_vulkan.h:57
const VkApplicationInfo *(* retro_vulkan_get_application_info_t)(void)
Definition: libretro_vulkan.h:55
retro_vulkan_set_command_buffers_t set_command_buffers
Definition: libretro_vulkan.h:366
unsigned interface_version
Definition: libretro_vulkan.h:144
Definition: vulkan_core.h:2138
retro_vulkan_unlock_queue_t unlock_queue
Definition: libretro_vulkan.h:383
void(* retro_vulkan_wait_sync_index_t)(void *handle)
Definition: libretro_vulkan.h:50
unsigned int uint32_t
Definition: stdint.h:126
retro_vulkan_lock_queue_t lock_queue
Definition: libretro_vulkan.h:382
retro_vulkan_get_sync_index_mask_t get_sync_index_mask
Definition: libretro_vulkan.h:343
void * handle
Definition: libretro_vulkan.h:158
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
Definition: vulkan_core.h:2730
VkDevice device
Definition: libretro_vulkan.h:165