blob: 121116a0062168a017a9e6c9de08873a6a374e0b [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_GRAPHICS_LIB_COMPUTE_TESTS_COMMON_VK_SWAPCHAIN_QUEUE_H_
#define SRC_GRAPHICS_LIB_COMPUTE_TESTS_COMMON_VK_SWAPCHAIN_QUEUE_H_
#include <stdbool.h>
#include <stdint.h>
#include <vulkan/vulkan.h>
#include "vk_swapchain.h"
#ifdef __cplusplus
extern "C" {
#endif
//
//
//
// |vk_swapchain_queue_t| implements a convenience struct to simplify simple
// applications that need to render frames to swapchain images. Usage is the
// following:
//
// 1) Call vk_swapchain_queue_create() to create your queue.
//
// Note that this creates an array of |vk_swapchain_queue_image_t|
// structs. Each one provides a command_buffer, synchronization fence,
// image framebuffer and synchronization semaphore.
//
// 2) For each frame to draw:
//
// a) Call vk_swapchain_queue_acquire_next_image() to acquire the next
// swapchain image, and ensure its matching command buffer has
// completed its previous submit. The function returns a pointer to
// the current |vk_swapchain_queue_image_t| to use in steps below.
//
// b) Optionally change the content of the framebuffer with
// vkBeginCmdBuffer ... vkEndCmdBuffer. Otherwise, it's existing
// content will be used as is.
//
// c) Call vk_swapchain_queue_submit_and_present_image() to submit
// the image's command buffer then send the image content's for
// presentation.
//
// Example:
//
// vk_swapchain_queue_t * queue = vk_swapchain_queue_create(...);
//
// // For each frame
// {
// const vk_swapchain_queue_image_t * image =
// vk_swapchain_queue_acquire_next_image(&queue);
//
// if (!image) {
// // display surface was resized or invalidated, exit loop
// break;
// }
//
// // Optionally change the content of |image->command_buffer| here.
// // If not, the buffer's current content will be used.
//
// vk_swapchain_queue_submit_and_present_image(&queue);
// }
//
// vk_swapchain_queue_destroy(queue);
//
//
//
typedef struct vk_swapchain_queue vk_swapchain_queue_t;
// Configuration parameters to initialize a vk_swapchain_queue_t instance.
//
// |swapchain| is the target |vk_swapchain_t| instance to use by the queue.
//
// |queue_family| and |queue_index| are Vulkan queue family and indices where
// the queue's image-specific command buffers will be allocated/submitted.
//
// |device| and |allocator| are the Vulkan device and allocator function pointers.
//
// |enable_framebuffers| is either null, or a VkRenderPass handle that will be
// used to create image-specific framebuffers.
//
// |enable_sync_semaphores| is the number of per-image sync_semaphores to create.
// These are only useful when performing manual vkQueueSubmit() calls between
// vk_swapchain_queue_acquire_next_image() and vk_swapchain_queue_submit_xxx().
// The value should be <= MAX_VK_SYNC_SEMAPHORES.
//
typedef struct vk_swapchain_queue_config
{
vk_swapchain_t * swapchain;
uint32_t queue_family;
uint32_t queue_index;
VkDevice device;
const VkAllocationCallbacks * allocator;
VkRenderPass enable_framebuffers;
uint32_t sync_semaphores_count;
} vk_swapchain_queue_config_t;
#define MAX_VK_SYNC_SEMAPHORES 4
// The data associated with each swapchain image in a queue.
//
// |image| and |image_view| come directly from the original vk_swapchain_t
// instance.
//
// |command_buffer| is the image-specific command buffer. The caller should
// setup its content at least once before calling
// vk_swapchain_queue_submit_and_present_image().
//
// |fence| is the synchronization fence used when submitting the command buffer
// through vk_swapchain_queue_submit_and_present_image(). Most clients should
// just ignore it.
//
// |framebuffer| is an optional VkFramebuffer instance associated with |image|.
// It is VK_NULL_HANDLE by default, unless the queue is created with a non-null
// |vk_swapchain_queue_config_t::enable_framebuffers| value.
//
// |sync_semaphores| is an array of additional semaphores available to the client.
// This can be useful when performing manual submits between
// vk_swapchain_queue_acquire_next_image() and
// vk_swapchain_queue_submit_and_present_image().
// All entries are VK_NULL_HANDLE by default, unless
// |vk_swapchain_queue_config_t::sync_semaphores_count| is > 0.
//
typedef struct vk_swapchain_queue_image
{
VkImage image;
VkImageView image_view;
VkCommandBuffer command_buffer;
VkFramebuffer framebuffer;
VkFence fence;
VkSemaphore sync_semaphores[MAX_VK_SYNC_SEMAPHORES];
} vk_swapchain_queue_image_t;
typedef struct vk_swapchain_queue vk_swapchain_queue_t;
// Initialize a new swapchain queue instance based on |config|.
extern vk_swapchain_queue_t *
vk_swapchain_queue_create(const vk_swapchain_queue_config_t * config);
extern uint32_t
vk_swapchain_queue_get_size(const vk_swapchain_queue_t * queue);
extern uint32_t
vk_swapchain_queue_get_index(const vk_swapchain_queue_t * queue);
extern const vk_swapchain_queue_image_t *
vk_swapchain_queue_get_image(const vk_swapchain_queue_t * queue, uint32_t image_index);
// Acquire the next swapchain image and ensure its matching command buffer
// has completed its previous submit. On success, return a pointer to the
// current queue image, which is equivalent to |&queue->images[queue->index]|.
// On failure, i.e. if the display surface was invalidated, return NULL.
extern const vk_swapchain_queue_image_t *
vk_swapchain_queue_acquire_next_image(vk_swapchain_queue_t * queue);
// Submit the current image's command buffer, then send the image content for
// presentation. This automatically synchronizes with the swapchain.
extern void
vk_swapchain_queue_submit_and_present_image(vk_swapchain_queue_t * queue);
// A variant of vk_swapchain_queue_submit_and_present_image() which allows the
// submit to wait on a different semaphore. Useful when a manual vkQueueSubmit
// between vk_swapchain_queue_acquire_next_image() and this call.
//
// |wait_semaphore| can be any valid semaphore that has already been enqueued
// for signaling. Clients are encourages to use the |sync_semaphore| of the
// current image.
extern void
vk_swapchain_queue_submit_and_present_image_wait_one(vk_swapchain_queue_t * queue,
VkSemaphore wait_semaphore,
VkPipelineStageFlags wait_stages);
// Destroy the swapchain queue and release its resources.
extern void
vk_swapchain_queue_destroy(vk_swapchain_queue_t * queue);
//
//
//
#ifdef __cplusplus
}
#endif
#endif // SRC_GRAPHICS_LIB_COMPUTE_TESTS_COMMON_VK_SWAPCHAIN_QUEUE_H_