Add support for signalling semaphores from frontend.

Useful for conserving framebuffer memory.
This commit is contained in:
Hans-Kristian Arntzen 2016-06-26 18:58:59 +02:00
parent 36c235556a
commit 4729ec9e1b
3 changed files with 49 additions and 21 deletions

View File

@ -354,6 +354,7 @@ typedef struct vk
const struct retro_vulkan_image *image;
const VkSemaphore *semaphores;
uint32_t num_semaphores;
VkSemaphore signal_semaphore;
VkPipelineStageFlags *wait_dst_stages;

View File

@ -925,6 +925,12 @@ static void vulkan_unlock_queue(void *handle)
#endif
}
static void vulkan_set_signal_semaphore(void *handle, VkSemaphore semaphore)
{
vk_t *vk = (vk_t*)handle;
vk->hw.signal_semaphore = semaphore;
}
static void vulkan_init_hw_render(vk_t *vk)
{
struct retro_hw_render_interface_vulkan *iface =
@ -935,25 +941,26 @@ static void vulkan_init_hw_render(vk_t *vk)
if (hwr->context_type != RETRO_HW_CONTEXT_VULKAN)
return;
vk->hw.enable = true;
vk->hw.enable = true;
iface->interface_type = RETRO_HW_RENDER_INTERFACE_VULKAN;
iface->interface_version = RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION;
iface->instance = vk->context->instance;
iface->gpu = vk->context->gpu;
iface->device = vk->context->device;
iface->interface_type = RETRO_HW_RENDER_INTERFACE_VULKAN;
iface->interface_version = RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION;
iface->instance = vk->context->instance;
iface->gpu = vk->context->gpu;
iface->device = vk->context->device;
iface->queue = vk->context->queue;
iface->queue_index = vk->context->graphics_queue_index;
iface->queue = vk->context->queue;
iface->queue_index = vk->context->graphics_queue_index;
iface->handle = vk;
iface->set_image = vulkan_set_image;
iface->get_sync_index = vulkan_get_sync_index;
iface->get_sync_index_mask = vulkan_get_sync_index_mask;
iface->wait_sync_index = vulkan_wait_sync_index;
iface->set_command_buffers = vulkan_set_command_buffers;
iface->lock_queue = vulkan_lock_queue;
iface->unlock_queue = vulkan_unlock_queue;
iface->handle = vk;
iface->set_image = vulkan_set_image;
iface->get_sync_index = vulkan_get_sync_index;
iface->get_sync_index_mask = vulkan_get_sync_index_mask;
iface->wait_sync_index = vulkan_wait_sync_index;
iface->set_command_buffers = vulkan_set_command_buffers;
iface->lock_queue = vulkan_lock_queue;
iface->unlock_queue = vulkan_unlock_queue;
iface->set_signal_semaphore = vulkan_set_signal_semaphore;
iface->get_device_proc_addr = vkGetDeviceProcAddr;
iface->get_instance_proc_addr = vulkan_symbol_wrapper_instance_proc_addr();
@ -1474,6 +1481,7 @@ static bool vulkan_frame(void *data, const void *frame,
static struct retro_perf_counter swapbuffers = {0};
static struct retro_perf_counter queue_submit = {0};
bool waits_for_semaphores = false;
VkSemaphore signal_semaphores[2];
VkCommandBufferBeginInfo begin_info = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
@ -1812,10 +1820,17 @@ static bool vulkan_frame(void *data, const void *frame,
vk->hw.valid_semaphore = false;
}
submit_info.signalSemaphoreCount =
vk->context->swapchain_semaphores[frame_index] != VK_NULL_HANDLE ? 1 : 0;
submit_info.pSignalSemaphores =
&vk->context->swapchain_semaphores[frame_index];
submit_info.signalSemaphoreCount = 0;
if (vk->context->swapchain_semaphores[frame_index] != VK_NULL_HANDLE)
signal_semaphores[submit_info.signalSemaphoreCount++] = vk->context->swapchain_semaphores[frame_index];
if (vk->hw.signal_semaphore != VK_NULL_HANDLE)
{
signal_semaphores[submit_info.signalSemaphoreCount++] = vk->hw.signal_semaphore;
vk->hw.signal_semaphore = VK_NULL_HANDLE;
}
submit_info.pSignalSemaphores = submit_info.signalSemaphoreCount ? signal_semaphores : NULL;
performance_counter_stop(&frame_run);

View File

@ -26,7 +26,7 @@
#include <libretro.h>
#include <vulkan/vulkan.h>
#define RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION 3
#define RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION 4
#define RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION 1
struct retro_vulkan_image
@ -50,6 +50,7 @@ typedef void (*retro_vulkan_set_command_buffers_t)(void *handle,
typedef void (*retro_vulkan_wait_sync_index_t)(void *handle);
typedef void (*retro_vulkan_lock_queue_t)(void *handle);
typedef void (*retro_vulkan_unlock_queue_t)(void *handle);
typedef void (*retro_vulkan_set_signal_semaphore_t)(void *handle, VkSemaphore semaphore);
typedef const VkApplicationInfo *(*retro_vulkan_get_application_info_t)(void);
@ -373,6 +374,17 @@ struct retro_hw_render_interface_vulkan
* NOTE: Queue submissions are heavy-weight. */
retro_vulkan_lock_queue_t lock_queue;
retro_vulkan_unlock_queue_t unlock_queue;
/* Sets a semaphore which is signaled when the image in set_image can safely be reused.
* The semaphore is consumed next call to retro_video_refresh_t.
* The semaphore will be signalled even for duped frames.
* The semaphore will be signalled only once, so set_signal_semaphore should be called every frame.
* The semaphore may be VK_NULL_HANDLE, which disables semaphore signalling for next call to retro_video_refresh_t.
*
* This is mostly useful to support use cases where you're rendering to a single image that
* is recycled in a ping-pong fashion with the frontend to save memory (but potentially less throughput).
*/
retro_vulkan_set_signal_semaphore_t set_signal_semaphore;
};
#endif