Files
face_sdk/vulkan/framework/common/vk_common.h
T

312 lines
12 KiB
C++

/* Copyright (c) 2018-2025, Arm Limited and Contributors
* Copyright (c) 2019-2025, Sascha Willems
* Copyright (c) 2024-2025, Mobica Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstdio>
#include <map>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
#include "common/error.h"
#include <vk_mem_alloc.h>
#include <volk.h>
#define VK_FLAGS_NONE 0 // Custom define for better code readability
#define DEFAULT_FENCE_TIMEOUT 100000000000 // Default fence timeout in nanoseconds
template <class T>
using ShaderStageMap = std::map<VkShaderStageFlagBits, T>;
template <class T>
using BindingMap = std::map<uint32_t, std::map<uint32_t, T>>;
namespace vkb
{
enum class BindingType
{
C,
Cpp
};
enum class CommandBufferResetMode
{
ResetPool,
ResetIndividually,
AlwaysAllocate,
};
/**
* @brief Helper function to determine if a Vulkan format is depth only.
* @param format Vulkan format to check.
* @return True if format is a depth only, false otherwise.
*/
bool is_depth_only_format(VkFormat format);
/**
* @brief Helper function to determine if a Vulkan format is depth with stencil.
* @param format Vulkan format to check.
* @return True if format is a depth with stencil, false otherwise.
*/
bool is_depth_stencil_format(VkFormat format);
/**
* @brief Helper function to determine if a Vulkan format is depth.
* @param format Vulkan format to check.
* @return True if format is a depth, false otherwise.
*/
bool is_depth_format(VkFormat format);
/**
* @brief Helper function to determine a suitable supported depth format based on a priority list
* @param physical_device The physical device to check the depth formats against
* @param depth_only (Optional) Wether to include the stencil component in the format or not
* @param depth_format_priority_list (Optional) The list of depth formats to prefer over one another
* By default we start with the highest precision packed format
* @return The valid suited depth format
*/
VkFormat get_suitable_depth_format(VkPhysicalDevice physical_device,
bool depth_only = false,
const std::vector<VkFormat> &depth_format_priority_list = {
VK_FORMAT_D32_SFLOAT,
VK_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D16_UNORM});
/**
* @brief Helper function to pick a blendable format from a priority ordered list
* @param physical_device The physical device to check the formats against
* @param format_priority_list List of formats in order of priority
* @return The selected format
*/
VkFormat choose_blendable_format(VkPhysicalDevice physical_device, const std::vector<VkFormat> &format_priority_list);
/**
* @brief Helper function to check support for linear filtering and adjust its parameters if required
* @param physical_device The physical device to check the depth formats against
* @param format The format to check against
* @param filter The preferred filter to adjust
* @param mipmapMode (Optional) The preferred mipmap mode to adjust
*/
void make_filters_valid(VkPhysicalDevice physical_device, VkFormat format, VkFilter *filter, VkSamplerMipmapMode *mipmapMode = nullptr);
/**
* @brief Helper function to determine if a Vulkan descriptor type is a dynamic storage buffer or dynamic uniform buffer.
* @param descriptor_type Vulkan descriptor type to check.
* @return True if type is dynamic buffer, false otherwise.
*/
bool is_dynamic_buffer_descriptor_type(VkDescriptorType descriptor_type);
/**
* @brief Helper function to determine if a Vulkan descriptor type is a buffer (either uniform or storage buffer, dynamic or not).
* @param descriptor_type Vulkan descriptor type to check.
* @return True if type is buffer, false otherwise.
*/
bool is_buffer_descriptor_type(VkDescriptorType descriptor_type);
/**
* @brief Helper function to get the bits per pixel of a Vulkan format.
* @param format Vulkan format to check.
* @return The bits per pixel of the given format, -1 for invalid formats.
*/
int32_t get_bits_per_pixel(VkFormat format);
enum class ShadingLanguage
{
GLSL,
HLSL,
SLANG,
};
/**
* @brief Helper function to create a VkShaderModule from a SPIR-V shader file
* @param filename The shader location
* @param device The logical device
* @param stage The shader stage
* @return The shader module containing the loaded shader
*/
VkShaderModule load_shader(const std::string &filename, VkDevice device, VkShaderStageFlagBits stage);
/**
* @brief Helper function to select a VkSurfaceFormatKHR
* @param gpu The VkPhysicalDevice to select a format for.
* @param surface The VkSurfaceKHR to select a format for.
* @param preferred_formats List of preferred VkFormats to use.
* @return The preferred VkSurfaceFormatKHR.
*/
VkSurfaceFormatKHR select_surface_format(VkPhysicalDevice gpu,
VkSurfaceKHR surface,
std::vector<VkFormat> const &preferred_formats = {
VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_A8B8G8R8_SRGB_PACK32});
/**
* @brief Image memory barrier structure used to define
* memory access for an image view during command recording.
*/
struct ImageMemoryBarrier
{
VkPipelineStageFlags src_stage_mask{VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT};
VkPipelineStageFlags dst_stage_mask{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
VkAccessFlags src_access_mask{0};
VkAccessFlags dst_access_mask{0};
VkImageLayout old_layout{VK_IMAGE_LAYOUT_UNDEFINED};
VkImageLayout new_layout{VK_IMAGE_LAYOUT_UNDEFINED};
uint32_t src_queue_family{VK_QUEUE_FAMILY_IGNORED};
uint32_t dst_queue_family{VK_QUEUE_FAMILY_IGNORED};
};
/**
* @brief Buffer memory barrier structure used to define
* memory access for a buffer during command recording.
*/
struct BufferMemoryBarrier
{
VkPipelineStageFlags src_stage_mask{VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT};
VkPipelineStageFlags dst_stage_mask{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
VkAccessFlags src_access_mask{0};
VkAccessFlags dst_access_mask{0};
};
/**
* @brief Put an image memory barrier for a layout transition of an image, using explicitly give transition parameters.
* @param command_buffer The VkCommandBuffer to record the barrier.
* @param image The VkImage to transition.
* @param src_stage_mask The VkPipelineStageFlags to use as source.
* @param dst_stage_mask The VkPipelineStageFlags to use as destination.
* @param src_access_mask The VkAccessFlags to use as source.
* @param dst_access_mask The VkAccessFlags to use as destination.
* @param old_layout The VkImageLayout to transition from.
* @param new_layout The VkImageLayout to transition to.
* @param subresource_range The VkImageSubresourceRange to use with the transition.
*/
void image_layout_transition(VkCommandBuffer command_buffer,
VkImage image,
VkPipelineStageFlags src_stage_mask,
VkPipelineStageFlags dst_stage_mask,
VkAccessFlags src_access_mask,
VkAccessFlags dst_access_mask,
VkImageLayout old_layout,
VkImageLayout new_layout,
VkImageSubresourceRange const &subresource_range);
/**
* @brief Put an image memory barrier for a layout transition of an image, on a given subresource range.
*
* The src_stage_mask, dst_stage_mask, src_access_mask, and dst_access_mask used are determined from old_layout and new_layout.
*
* @param command_buffer The VkCommandBuffer to record the barrier.
* @param image The VkImage to transition.
* @param old_layout The VkImageLayout to transition from.
* @param new_layout The VkImageLayout to transition to.
* @param subresource_range The VkImageSubresourceRange to use with the transition.
*/
void image_layout_transition(VkCommandBuffer command_buffer,
VkImage image,
VkImageLayout old_layout,
VkImageLayout new_layout,
VkImageSubresourceRange const &subresource_range);
/**
* @brief Put an image memory barrier for a layout transition of an image, on a fixed subresource with first mip level and layer.
*
* The src_stage_mask, dst_stage_mask, src_access_mask, and dst_access_mask used are determined from old_layout and new_layout.
*
* @param command_buffer The VkCommandBuffer to record the barrier.
* @param image The VkImage to transition.
* @param old_layout The VkImageLayout to transition from.
* @param new_layout The VkImageLayout to transition to.
*/
void image_layout_transition(VkCommandBuffer command_buffer,
VkImage image,
VkImageLayout old_layout,
VkImageLayout new_layout);
/**
* @brief Put an image memory barrier for a layout transition of a vector of images, with a given subresource range per image.
*
* The src_stage_mask, dst_stage_mask, src_access_mask, and dst_access_mask used are determined from old_layout and new_layout.
*
* @param command_buffer The VkCommandBuffer to record the barrier.
* @param imagesAndRanges The images to transition, with accompanying subresource ranges.
* @param old_layout The VkImageLayout to transition from.
* @param new_layout The VkImageLayout to transition to.
*/
void image_layout_transition(VkCommandBuffer command_buffer,
std::vector<std::pair<VkImage, VkImageSubresourceRange>> const &imagesAndRanges,
VkImageLayout old_layout,
VkImageLayout new_layout);
/**
* @brief Helper functions for compression controls
*/
std::vector<VkImageCompressionFixedRateFlagBitsEXT> fixed_rate_compression_flags_to_vector(VkImageCompressionFixedRateFlagsEXT flags);
VkImageCompressionPropertiesEXT query_supported_fixed_rate_compression(VkPhysicalDevice gpu, const VkImageCreateInfo &create_info);
VkImageCompressionPropertiesEXT query_applied_compression(VkDevice device, VkImage image);
/**
* @brief Load and store info for a render pass attachment.
*/
struct LoadStoreInfo
{
VkAttachmentLoadOp load_op = VK_ATTACHMENT_LOAD_OP_CLEAR;
VkAttachmentStoreOp store_op = VK_ATTACHMENT_STORE_OP_STORE;
};
namespace gbuffer
{
/**
* @return Load store info to load all and store only the swapchain
*/
std::vector<LoadStoreInfo> get_load_all_store_swapchain();
/**
* @return Load store info to clear all and store only the swapchain
*/
std::vector<LoadStoreInfo> get_clear_all_store_swapchain();
/**
* @return Load store info to clear and store all images
*/
std::vector<LoadStoreInfo> get_clear_store_all();
/**
* @return Default clear values for the G-buffer
*/
std::vector<VkClearValue> get_clear_value();
} // namespace gbuffer
uint32_t get_queue_family_index(std::vector<VkQueueFamilyProperties> const &queue_family_properties, VkQueueFlagBits queue_flag);
} // namespace vkb