312 lines
12 KiB
C++
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
|