monado/src/xrt/auxiliary/vk/vk_helpers.h

564 lines
17 KiB
C
Raw Normal View History

// Copyright 2019-2020, Collabora, Ltd.
2019-03-18 05:52:32 +00:00
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Common Vulkan code header.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
#pragma once
#include "xrt/xrt_compositor.h"
#include "xrt/xrt_vulkan_includes.h"
#include "xrt/xrt_handles.h"
#include "util/u_logging.h"
#include "os/os_threading.h"
2019-03-18 05:52:32 +00:00
#ifdef __cplusplus
extern "C" {
#endif
/*
*
* Structs
*
*/
/*!
2020-02-23 11:55:11 +00:00
* A bundle of Vulkan functions and objects, used by both @ref comp and @ref
* comp_client. Note that they both have different instances of the object and
* as such VkInstance and so on.
2019-03-18 05:52:32 +00:00
*
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
struct vk_bundle
{
enum u_logging_level ll;
2019-03-18 05:52:32 +00:00
VkInstance instance;
VkPhysicalDevice physical_device;
int physical_device_index;
2019-03-18 05:52:32 +00:00
VkDevice device;
uint32_t queue_family_index;
uint32_t queue_index;
VkQueue queue;
2019-03-18 05:52:32 +00:00
struct os_mutex queue_mutex;
bool has_GOOGLE_display_timing;
2019-03-18 05:52:32 +00:00
VkDebugReportCallbackEXT debug_report_cb;
VkPhysicalDeviceMemoryProperties device_memory_props;
VkCommandPool cmd_pool;
struct os_mutex cmd_pool_mutex;
2019-03-18 05:52:32 +00:00
// clang-format off
// Loader functions
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
PFN_vkCreateInstance vkCreateInstance;
// Instance functions.
PFN_vkDestroyInstance vkDestroyInstance;
PFN_vkCreateDevice vkCreateDevice;
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;
2019-03-18 05:52:32 +00:00
#ifdef VK_USE_PLATFORM_XCB_KHR
PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
#endif
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT;
PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT;
PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT;
#endif
#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT) || defined(VK_USE_PLATFORM_DISPLAY_KHR)
2019-03-18 05:52:32 +00:00
PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR;
PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR;
2019-03-31 21:37:34 +00:00
PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR;
2019-03-18 05:52:32 +00:00
PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR;
PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR;
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
#endif
2019-03-18 05:52:32 +00:00
#ifdef VK_USE_PLATFORM_WIN32_KHR
PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
#endif
2019-03-18 05:52:32 +00:00
// Physical device functions.
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2;
2019-03-18 05:52:32 +00:00
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
2019-03-18 05:52:32 +00:00
// Device functions.
PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
PFN_vkDestroyDevice vkDestroyDevice;
PFN_vkDeviceWaitIdle vkDeviceWaitIdle;
PFN_vkAllocateMemory vkAllocateMemory;
PFN_vkFreeMemory vkFreeMemory;
PFN_vkMapMemory vkMapMemory;
PFN_vkUnmapMemory vkUnmapMemory;
PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR;
#ifdef VK_USE_PLATFORM_ANDROID_KHR
PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID;
PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID;
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR;
#endif
2019-03-18 05:52:32 +00:00
PFN_vkCreateBuffer vkCreateBuffer;
PFN_vkDestroyBuffer vkDestroyBuffer;
PFN_vkBindBufferMemory vkBindBufferMemory;
PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
2020-05-08 19:18:56 +00:00
PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
2019-03-18 05:52:32 +00:00
PFN_vkCreateImage vkCreateImage;
PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
PFN_vkBindImageMemory vkBindImageMemory;
PFN_vkDestroyImage vkDestroyImage;
PFN_vkCreateImageView vkCreateImageView;
PFN_vkDestroyImageView vkDestroyImageView;
PFN_vkCreateSampler vkCreateSampler;
PFN_vkDestroySampler vkDestroySampler;
PFN_vkCreateShaderModule vkCreateShaderModule;
PFN_vkDestroyShaderModule vkDestroyShaderModule;
PFN_vkCreateCommandPool vkCreateCommandPool;
PFN_vkDestroyCommandPool vkDestroyCommandPool;
PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;
PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;
PFN_vkCmdSetScissor vkCmdSetScissor;
PFN_vkCmdSetViewport vkCmdSetViewport;
PFN_vkCmdClearColorImage vkCmdClearColorImage;
PFN_vkCmdEndRenderPass vkCmdEndRenderPass;
PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets;
PFN_vkCmdBindPipeline vkCmdBindPipeline;
2019-10-07 23:12:06 +00:00
PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers;
2019-10-23 21:00:22 +00:00
PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer;
2019-03-18 05:52:32 +00:00
PFN_vkCmdDraw vkCmdDraw;
2019-10-23 21:00:22 +00:00
PFN_vkCmdDrawIndexed vkCmdDrawIndexed;
2019-03-18 05:52:32 +00:00
PFN_vkEndCommandBuffer vkEndCommandBuffer;
PFN_vkFreeCommandBuffers vkFreeCommandBuffers;
PFN_vkCreateRenderPass vkCreateRenderPass;
PFN_vkDestroyRenderPass vkDestroyRenderPass;
PFN_vkCreateFramebuffer vkCreateFramebuffer;
PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
PFN_vkCreatePipelineCache vkCreatePipelineCache;
PFN_vkDestroyPipelineCache vkDestroyPipelineCache;
PFN_vkCreateDescriptorPool vkCreateDescriptorPool;
PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool;
PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets;
2020-10-11 16:52:25 +00:00
PFN_vkFreeDescriptorSets vkFreeDescriptorSets;
2019-03-18 05:52:32 +00:00
PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;
PFN_vkDestroyPipeline vkDestroyPipeline;
PFN_vkCreatePipelineLayout vkCreatePipelineLayout;
PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout;
PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout;
PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets;
PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout;
PFN_vkGetDeviceQueue vkGetDeviceQueue;
PFN_vkQueueSubmit vkQueueSubmit;
PFN_vkQueueWaitIdle vkQueueWaitIdle;
PFN_vkCreateSemaphore vkCreateSemaphore;
PFN_vkDestroySemaphore vkDestroySemaphore;
PFN_vkCreateFence vkCreateFence;
PFN_vkWaitForFences vkWaitForFences;
PFN_vkDestroyFence vkDestroyFence;
2020-04-15 13:07:02 +00:00
PFN_vkResetFences vkResetFences;
2019-03-18 05:52:32 +00:00
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
PFN_vkQueuePresentKHR vkQueuePresentKHR;
#ifdef VK_USE_PLATFORM_WIN32_KHR
PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR;
#else
PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR;
PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR;
#endif
PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE;
2019-03-18 05:52:32 +00:00
// clang-format on
};
struct vk_buffer
{
VkBuffer handle;
VkDeviceMemory memory;
uint32_t size;
void *data;
};
2019-03-18 05:52:32 +00:00
2019-03-18 05:52:32 +00:00
/*
*
* String helper functions.
*
*/
const char *
vk_result_string(VkResult code);
const char *
vk_color_format_string(VkFormat code);
const char *
vk_present_mode_string(VkPresentModeKHR code);
const char *
vk_power_state_string(VkDisplayPowerStateEXT code);
const char *
vk_color_space_string(VkColorSpaceKHR code);
/*
*
* Function and helpers.
*
*/
#define VK_TRACE(d, ...) U_LOG_IFL_T(d->ll, __VA_ARGS__)
#define VK_DEBUG(d, ...) U_LOG_IFL_D(d->ll, __VA_ARGS__)
#define VK_INFO(d, ...) U_LOG_IFL_I(d->ll, __VA_ARGS__)
#define VK_WARN(d, ...) U_LOG_IFL_W(d->ll, __VA_ARGS__)
#define VK_ERROR(d, ...) U_LOG_IFL_E(d->ll, __VA_ARGS__)
2019-03-18 05:52:32 +00:00
2021-02-12 15:26:10 +00:00
/*!
* @brief Check a Vulkan VkResult, writing an error to the log and returning true if not VK_SUCCESS
*
* @param fun a string literal with the name of the Vulkan function, for logging purposes.
* @param res a VkResult from that function.
* @param file a string literal with the source code filename, such as from __FILE__
* @param line a source code line number, such as from __LINE__
*
* @see vk_check_error, vk_check_error_with_free which wrap this for easier usage.
*
* @ingroup aux_vk
*/
2020-05-06 10:19:49 +00:00
bool
vk_has_error(VkResult res, const char *fun, const char *file, int line);
2021-02-12 15:26:10 +00:00
/*!
2021-03-30 17:08:52 +00:00
* @def vk_check_error
2021-02-12 15:26:10 +00:00
* @brief Perform checking of a Vulkan result, returning in case it is not VK_SUCCESS.
*
* @param fun A string literal with the name of the Vulkan function, for logging purposes.
* @param res a VkResult from that function.
* @param ret value to return, if any, upon error
*
* @see vk_has_error which is wrapped by this macro
*
* @ingroup aux_vk
*/
2021-01-14 14:13:48 +00:00
#define vk_check_error(fun, res, ret) \
do { \
if (vk_has_error(res, fun, __FILE__, __LINE__)) \
return ret; \
} while (0)
2020-05-06 10:19:49 +00:00
2021-02-12 15:26:10 +00:00
/*!
2021-03-30 17:08:52 +00:00
* @def vk_check_error_with_free
2021-02-12 15:26:10 +00:00
* @brief Perform checking of a Vulkan result, freeing an allocation and returning in case it is not VK_SUCCESS.
*
* @param fun A string literal with the name of the Vulkan function, for logging purposes.
* @param res a VkResult from that function.
* @param ret value to return, if any, upon error
* @param to_free expression to pass to `free()` upon error
*
* @see vk_has_error which is wrapped by this macro
*
* @ingroup aux_vk
*/
2021-01-14 14:13:48 +00:00
#define vk_check_error_with_free(fun, res, ret, to_free) \
do { \
if (vk_has_error(res, fun, __FILE__, __LINE__)) { \
free(to_free); \
return ret; \
} \
} while (0)
/*!
* @ingroup aux_vk
*/
VkResult
vk_get_loader_functions(struct vk_bundle *vk, PFN_vkGetInstanceProcAddr g);
2019-03-18 05:52:32 +00:00
/*!
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_get_instance_functions(struct vk_bundle *vk);
/*!
* @brief Initialize mutexes in the @ref vk_bundle.
*
* Not required for all uses, but a precondition for some.
*
* @ingroup aux_vk
*/
VkResult
vk_init_mutex(struct vk_bundle *vk);
/*!
* @brief De-initialize mutexes in the @ref vk_bundle.
* @ingroup aux_vk
*/
VkResult
vk_deinit_mutex(struct vk_bundle *vk);
2019-03-18 05:52:32 +00:00
/*!
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_init_cmd_pool(struct vk_bundle *vk);
/*!
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_create_device(struct vk_bundle *vk,
int forced_index,
const char *const *required_device_extensions,
size_t num_required_device_extensions,
const char *const *optional_device_extensions,
size_t num_optional_device_extension);
2019-03-18 05:52:32 +00:00
/*!
* Initialize a bundle with objects given to us by client code,
* used by @ref client_vk_compositor in @ref comp_client.
*
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_init_from_given(struct vk_bundle *vk,
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
VkInstance instance,
VkPhysicalDevice physical_device,
VkDevice device,
uint32_t queue_family_index,
uint32_t queue_index);
/*!
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
bool
2021-01-14 14:13:48 +00:00
vk_get_memory_type(struct vk_bundle *vk, uint32_t type_bits, VkMemoryPropertyFlags memory_props, uint32_t *out_type_id);
2019-03-18 05:52:32 +00:00
/*!
* Allocate memory for an image and bind it to that image.
*
* Handles the following steps:
*
* - calling vkGetImageMemoryRequirements
* - comparing against the max_size
* - getting the memory type (as dictated by the VkMemoryRequirements and
* VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
* - calling vkAllocateMemory
* - calling vkBindImageMemory
* - calling vkDestroyMemory in case of an error.
*
* If this fails, it cleans up the VkDeviceMemory.
*
* @param vk Vulkan bundle
* @param image The VkImage to allocate for and bind.
* @param max_size The maximum value you'll allow for
* VkMemoryRequirements::size. Pass SIZE_MAX if you will accept any size
* that works.
* @param pNext_for_allocate (Optional) a pointer to use in the pNext chain of
* VkMemoryAllocateInfo.
* @param out_mem Output parameter: will be set to the allocated memory if
* everything succeeds. Not modified if there is an error.
* @param out_size (Optional) pointer to receive the value of
* VkMemoryRequirements::size.
*
* If this fails, you may want to destroy your VkImage as well, since this
* routine is usually used in combination with vkCreateImage.
*
* @ingroup aux_vk
*/
VkResult
vk_alloc_and_bind_image_memory(struct vk_bundle *vk,
VkImage image,
size_t max_size,
const void *pNext_for_allocate,
VkDeviceMemory *out_mem,
VkDeviceSize *out_size);
2019-03-18 05:52:32 +00:00
/*!
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_create_image_from_native(struct vk_bundle *vk,
const struct xrt_swapchain_create_info *info,
struct xrt_image_native *image_native,
VkImage *out_image,
VkDeviceMemory *out_mem);
2019-03-18 05:52:32 +00:00
/*!
* @ingroup aux_vk
*/
VkResult
2021-01-14 14:13:48 +00:00
vk_create_semaphore_from_native(struct vk_bundle *vk, xrt_graphics_sync_handle_t native, VkSemaphore *out_sem);
2019-03-18 05:52:32 +00:00
/*!
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_create_image_simple(struct vk_bundle *vk,
VkExtent2D extent,
2019-03-18 05:52:32 +00:00
VkFormat format,
VkImageUsageFlags usage,
2019-03-18 05:52:32 +00:00
VkDeviceMemory *out_mem,
VkImage *out_image);
/*!
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
2021-01-14 14:13:48 +00:00
vk_create_sampler(struct vk_bundle *vk, VkSamplerAddressMode clamp_mode, VkSampler *out_sampler);
2019-03-18 05:52:32 +00:00
/*!
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_create_view(struct vk_bundle *vk,
VkImage image,
VkFormat format,
2019-04-30 15:22:19 +00:00
VkImageSubresourceRange subresource_range,
2019-03-18 05:52:32 +00:00
VkImageView *out_view);
/*!
* @ingroup aux_vk
*/
VkResult
vk_create_view_swizzle(struct vk_bundle *vk,
VkImage image,
VkFormat format,
VkImageSubresourceRange subresource_range,
VkComponentMapping components,
VkImageView *out_view);
2019-03-18 05:52:32 +00:00
/*!
* @pre Requires successful call to vk_init_mutex
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_init_cmd_buffer(struct vk_bundle *vk, VkCommandBuffer *out_cmd_buffer);
/*!
* @pre Requires successful call to vk_init_mutex
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_set_image_layout(struct vk_bundle *vk,
VkCommandBuffer cmd_buffer,
VkImage image,
VkAccessFlags src_access_mask,
VkAccessFlags dst_access_mask,
VkImageLayout old_layout,
VkImageLayout new_layout,
VkImageSubresourceRange subresource_range);
/*!
* @pre Requires successful call to vk_init_mutex
* @ingroup aux_vk
2019-03-18 05:52:32 +00:00
*/
VkResult
vk_submit_cmd_buffer(struct vk_bundle *vk, VkCommandBuffer cmd_buffer);
2020-05-06 10:41:46 +00:00
VkAccessFlags
vk_get_access_flags(VkImageLayout layout);
VkAccessFlags
vk_swapchain_access_flags(enum xrt_swapchain_usage_bits bits);
/*!
* Always adds `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and
* `VK_IMAGE_USAGE_SAMPLED_BIT` to color formats so they can be used by the
* compositor and client.
*/
VkImageUsageFlags
2021-01-14 14:13:48 +00:00
vk_swapchain_usage_flags(struct vk_bundle *vk, VkFormat format, enum xrt_swapchain_usage_bits bits);
2020-05-06 14:44:24 +00:00
bool
vk_init_descriptor_pool(struct vk_bundle *vk,
const VkDescriptorPoolSize *pool_sizes,
uint32_t pool_size_count,
uint32_t set_count,
VkDescriptorPool *out_descriptor_pool);
bool
vk_allocate_descriptor_sets(struct vk_bundle *vk,
VkDescriptorPool descriptor_pool,
uint32_t count,
const VkDescriptorSetLayout *set_layout,
VkDescriptorSet *sets);
bool
vk_buffer_init(struct vk_bundle *vk,
VkDeviceSize size,
VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties,
VkBuffer *out_buffer,
VkDeviceMemory *out_mem);
void
vk_buffer_destroy(struct vk_buffer *self, struct vk_bundle *vk);
2020-05-06 14:44:24 +00:00
2020-08-20 01:25:12 +00:00
bool
2021-01-14 14:13:48 +00:00
vk_update_buffer(struct vk_bundle *vk, float *buffer, size_t buffer_size, VkDeviceMemory memory);
/*!
* @pre Requires successful call to vk_init_mutex
* @ingroup aux_vk
*/
VkResult
2021-01-14 14:13:48 +00:00
vk_locked_submit(struct vk_bundle *vk, VkQueue queue, uint32_t count, const VkSubmitInfo *infos, VkFence fence);
2019-03-18 05:52:32 +00:00
#ifdef __cplusplus
}
#endif