vulkan-project/vulkan_util.hpp
2022-10-14 20:58:20 +02:00

159 lines
5.5 KiB
C++

#pragma once
#include "vertex.hpp"
#include <optional>
#include <set>
#include <unordered_map>
#include <vulkan/vulkan_core.h>
namespace gz::vk {
/**
* @name Convenience structs
* @details
* Structures and functionas making usiing the vulkan api more convenient
* @{
*/
/**
* @brief Struct containing all physical device features structs
* @details
* Make sure to call vkGetPhysicalDeviceFeatures2 with the f member, not this struct itself
*/
struct PhysicalDeviceFeatures {
/**
* @brief Initialize the structs with sType and pNext chain f -> f11 -> f12 -> f13
*/
PhysicalDeviceFeatures();
VkPhysicalDeviceFeatures2 f{};
VkPhysicalDeviceVulkan11Features f11{};
VkPhysicalDeviceVulkan12Features f12{};
VkPhysicalDeviceVulkan13Features f13{};
/**
* @brief Check if all features enabled in requiredFeatures are enabled in this
*/
bool requiredFeaturesAvailable(const PhysicalDeviceFeatures& requiredFeatures) const;
};
enum PipelineT {
PL_3D, PL_2D
};
struct Pipeline {
VkPipeline pipeline;
VkPipelineLayout layout;
void operator=(const Pipeline& other) = delete;
};
/**
* @brief Map holding pipelines
*/
class PipelineContainer {
public:
using iterator = std::unordered_map<PipelineT, Pipeline>::iterator;
Pipeline& operator[](const PipelineT& key) { return pipelines[key]; }
/**
* @brief Destroy the pipeline+layout and then remove the handles from the underlying map
*/
void erase(const PipelineT& key, VkDevice& device, const VkAllocationCallbacks* pAllocator=nullptr);
/**
* @brief Destroy the pipeline+layout and then remove the handles from the underlying map
*/
iterator erase(const iterator& it, VkDevice& device, const VkAllocationCallbacks* pAllocator=nullptr);
/**
* @brief Destroy all pipelines#layouts and then remove the handles from the underlying map
*/
void destroy(VkDevice& device, const VkAllocationCallbacks* pAllocator=nullptr);
iterator begin() { return pipelines.begin(); }
iterator end() { return pipelines.end(); }
size_t size() const { return pipelines.size(); }
private:
std::unordered_map<PipelineT, Pipeline> pipelines;
};
struct SwapChainSupport {
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
template<typename T>
concept SupportedIndexType = std::same_as<T, uint16_t> or std::same_as<T, uint32_t>;
template<SupportedIndexType T>
struct VerticesAndIndices {
std::vector<Vertex3D> vertices;
std::vector<T> indices;
constexpr VkIndexType getIndexType() const {
if (std::same_as<T, uint16_t>) {
return VK_INDEX_TYPE_UINT16;
}
else if (std::same_as<T, uint32_t>) {
return VK_INDEX_TYPE_UINT32;
}
}
};
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
std::optional<uint32_t> transferFamily;
bool hasNecessaryValues() {
return graphicsFamily.has_value() && presentFamily.has_value();
}
bool hasAllValues() {
return graphicsFamily.has_value() && presentFamily.has_value() && transferFamily.has_value();
}
std::string toString() const {
std::string s = "[ ";
s += "graphicsFamily: ";
if (graphicsFamily.has_value()) { s += std::to_string(graphicsFamily.value()); }
else { s += "not set"; }
s += ", presentFamily: ";
if (presentFamily.has_value()) { s += std::to_string(presentFamily.value()); }
else { s += "not set"; }
s += ", transferFamily: ";
if (transferFamily.has_value()) { s += std::to_string(transferFamily.value()); }
else { s += "not set"; }
return s + " ]";
}
};
/**
* @brief Get a VkDependencyInfo struct for a single image memory barrier
*/
VkDependencyInfo getDepInfo(const VkImageMemoryBarrier2& barrier);
/// @}
/**
* @brief Used for debugging
* @see VulkanInstance::debugLog
* @details
* Handles like VkDevice are pointers to the actual handle.
* Register the handle to a vulkan object with this struct and call updateHandles().
* The handles set will then contain the actual address of the handle, as printed by the validation layers.
* That means you can check a handle returned by a validation layer
* with this struct and see if this handle belongs to object that created this struct.
* @warning
* Every pointer you submit to this must stay valid!
* Use this struct only when debugging!
*/
struct ObjectUsingVulkan {
ObjectUsingVulkan(std::string&& name, std::vector<void*>&& ptrsToHandles, std::vector<void*>&& vectorWithPtrsToHandles);
std::string objectName;
std::vector<void*> ptrToHandle;
std::vector<std::vector<void*>*> vectorWithPtrToHandle;
std::set<uint64_t> handles;
/**
* @brief Update the handles map with the current handle (aka segfault generator)
*/
void updateHandles();
};
} // namespace gz::vk