| // 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_UTILS_H_ |
| #define SRC_GRAPHICS_LIB_COMPUTE_TESTS_COMMON_VK_UTILS_H_ |
| |
| #include <stdbool.h> |
| #include <vulkan/vulkan.h> |
| |
| #include "utils.h" // For FUNC_ATTRIBUTE_NORETURN |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| // Technical note: |
| // |
| // The Vulkan specification reserves the following for its own use: |
| // |
| // - Function names with a "vk" prefix, followed by a capital letter. |
| // - Macro names with a "VK_" prefix. |
| |
| // Check that |result| is VK_SUCCESS, if not, immediately panic. |
| // |
| // Usage example: |
| // VkResult result = vkCreateDevice(...); |
| // VK_CHECK(result); |
| // |
| #define VK_CHECK(result) \ |
| do \ |
| { \ |
| VkResult vk_result_ = (result); \ |
| if (vk_result_ != VK_SUCCESS) \ |
| vk_panic_(vk_result_, __FILE__, __LINE__, NULL); \ |
| } \ |
| while (0) |
| |
| // Check that |result| is VK_SUCCESS. If not, panic immediately with a formatted message. |
| // |
| // Usage example: |
| // VkResult result = vkCreateDevice(...); |
| // VK_CHECK_MSG(result, "Could not create device for instance %p", instance); |
| // |
| #define VK_CHECK_MSG(result, ...) \ |
| do \ |
| { \ |
| VkResult vk_result_ = (result); \ |
| if (vk_result_ != VK_SUCCESS) \ |
| vk_panic_(vk_result_, __FILE__, __LINE__, __VA_ARGS__); \ |
| } \ |
| while (0) |
| |
| // Convenience macro used to embed a Vulkan function call and panic if it fails. |
| // Usage example: |
| // vk(CreateInstance(....)); |
| // |
| // Equivalent to: |
| // VK_CHECK(vkCreateInstance(...)); |
| // |
| #define vk(...) \ |
| do \ |
| { \ |
| VkResult vk_result_ = vk##__VA_ARGS__; \ |
| if (vk_result_ != VK_SUCCESS) \ |
| vk_panic_(vk_result_, __FILE__, __LINE__, NULL); \ |
| } \ |
| while (0) |
| |
| // Internal panic function to call in case of a failed Vulkan call with |result|. |
| // See vk_check() below for usage. |
| extern void |
| vk_panic_(VkResult result, const char * file, int line, const char * fmt, ...) |
| FUNC_ATTRIBUTE_NORETURN; |
| |
| // Convert VkResult value to a string. |
| extern const char * |
| vk_result_to_string(VkResult result); |
| |
| // Helper macro to define a local variable pointing a global Vulkan entry point, |
| // i.e. those that are available before VkInstance creation. |
| // |
| // Usage example: |
| // GET_VULKAN_GLOBAL_PROC_ADDR(vkEnumerateInstanceLayerProperties); |
| // VkResult result = vkEnumerateInstanceLayerProperties(...); |
| // |
| #define GET_VULKAN_GLOBAL_PROC_ADDR(name) \ |
| PFN_##name name = (PFN_##name)vkGetInstanceProcAddr(NULL, #name) |
| |
| // Helper macro to define a local variable pointing an instance-specific |
| // Vulkan entry point, i.e. those available just after VkInstance creation. |
| // WARNING: This assumes the VkInstance handle to use is named 'instance'. |
| // |
| // Usage example: |
| // VkInstance instance = ...; |
| // GET_VULKAN_INSTANCE_PROC_ADDR(vkCreateDevice); |
| // VkResult result = vkCreateDevice(...); |
| // |
| #define GET_VULKAN_INSTANCE_PROC_ADDR(name) \ |
| PFN_##name name = (PFN_##name)vkGetInstanceProcAddr(instance, #name) |
| |
| // Helper macro to define a local variable pointing a device-specific |
| // Vulkan entry point, i.e. those available just after VkInstance creation. |
| // WARNING: This assumes the VkDevice handle to use is named 'device'. |
| // |
| // Usage example: |
| // VkDevice device = ...; |
| // GET_VULKAN_DEVICE_PROC_ADDR(vkCreateBuffer); |
| // VkResult result = vkCreateBuffer(...); |
| // |
| #define GET_VULKAN_DEVICE_PROC_ADDR(name) \ |
| PFN_##name name = (PFN_##name)vkGetDeviceProcAddr(device, #name) |
| |
| // Print the content of a given VkInstanceCreateInfo to stderr. Useful for debugging. |
| extern void |
| vk_instance_create_info_print(const VkInstanceCreateInfo * info); |
| |
| // Print the content of a given VkDeviceCreateInfo to stderr. Useful for debugging. |
| extern void |
| vk_device_create_info_print(const VkDeviceCreateInfo * info); |
| |
| // Check that all bits in |image_usage| are supported by |format_features| |
| // when that makes sense (i.e. not all image usage bits have a corresponding |
| // format feature bit). |
| extern bool |
| vk_check_image_usage_vs_format_features(VkImageUsageFlags image_usage, |
| VkFormatFeatureFlags format_features); |
| |
| // Helper function to perform a single submit on |command_queue|. |
| // |wait_semaphore| is either null or a valid semaphore handle to wait for. |
| // |wait_stages| is pipeline stage mask, used only if |wait_semaphore| is not null. |
| // |signal_semaphore| is either null or a valid semaphore handle to signal. |
| // |command_queue| is the queue where the submit happens. |
| // |command_buffer| is either null or a valid command buffer handle. |
| // |signal_fence| is either null or a fence to signal on completion. |
| extern void |
| vk_submit_one(VkSemaphore wait_semaphore, |
| VkPipelineStageFlags wait_stages, |
| VkSemaphore signal_semaphore, |
| VkQueue command_queue, |
| VkCommandBuffer command_buffer, |
| VkFence signal_fence); |
| |
| // Return the number of bytes per pixel corresponding to a given |format|. |
| // NOTE: This will return 0 for compressed formats, as well as depth/stencil |
| // ones. |
| extern uint32_t |
| vk_format_to_bytes_per_pixel(VkFormat format); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif // SRC_GRAPHICS_LIB_COMPUTE_TESTS_COMMON_VK_UTILS_H_ |