Program Listing for File device.hpp¶
↰ Return to documentation for file (inexor/vulkan-renderer/wrapper/device.hpp)
#pragma once
#include "inexor/vulkan-renderer/tools/exception.hpp"
#include "inexor/vulkan-renderer/tools/representation.hpp"
#include "inexor/vulkan-renderer/wrapper/commands/command_pool.hpp"
#include "inexor/vulkan-renderer/wrapper/make_info.hpp"
#include <array>
#include <functional>
#include <optional>
#include <shared_mutex>
#include <span>
#include <string>
namespace inexor::vulkan_renderer::wrapper {
// Forward declaration
class Instance;
// Using declarations
using tools::InexorException;
using tools::VulkanException;
using wrapper::commands::CommandBuffer;
using wrapper::commands::CommandPool;
enum class VulkanQueueType {
QUEUE_TYPE_GRAPHICS,
QUEUE_TYPE_COMPUTE,
QUEUE_TYPE_TRANSFER,
QUEUE_TYPE_SPARSE_BINDING,
};
class Device {
private:
VkDevice m_device{VK_NULL_HANDLE};
VkPhysicalDevice m_physical_device{VK_NULL_HANDLE};
VmaAllocator m_allocator{VK_NULL_HANDLE};
std::string m_gpu_name;
VkPhysicalDeviceFeatures m_enabled_features{};
std::array<std::uint8_t, VK_UUID_SIZE> m_pipeline_cache_uuid{};
VkQueue m_graphics_queue{VK_NULL_HANDLE};
VkQueue m_transfer_queue{VK_NULL_HANDLE};
VkQueue m_compute_queue{VK_NULL_HANDLE};
VkQueue m_sparse_binding_queue{VK_NULL_HANDLE};
VkQueue m_present_queue{VK_NULL_HANDLE};
std::optional<std::uint32_t> m_graphics_queue_family_index{0};
std::optional<std::uint32_t> m_compute_queue_family_index{0};
std::optional<std::uint32_t> m_transfer_queue_family_index{0};
std::optional<std::uint32_t> m_sparse_binding_queue_family_index{0};
std::optional<std::uint32_t> m_present_queue_family_index{0};
mutable std::vector<std::unique_ptr<CommandPool>> m_cmd_pools;
mutable std::shared_mutex m_mutex;
CommandPool &get_thread_command_pool(VulkanQueueType queue_type) const;
// @TODO Implement get_thread_command_pool with "transfer if available, graphics otherwise" for copy operations.
public:
Device(const Instance &inst, VkSurfaceKHR surface, VkPhysicalDevice physical_device,
const VkPhysicalDeviceFeatures &required_features, std::span<const char *> required_extensions);
Device(const Device &) = delete;
Device(Device &&) noexcept;
~Device();
Device &operator=(const Device &) = delete;
Device &operator=(Device &&) = delete;
[[nodiscard]] auto device() const {
return m_device;
}
[[nodiscard]] VkSurfaceCapabilitiesKHR get_surface_capabilities(VkSurfaceKHR surface) const;
[[nodiscard]] bool is_presentation_supported(VkSurfaceKHR surface, std::uint32_t queue_family_index) const;
void execute(const std::string &name, const VulkanQueueType queue_type,
const std::function<void(const CommandBuffer &cmd_buf)> &cmd_lambda) const;
[[nodiscard]] VkPhysicalDevice physical_device() const {
return m_physical_device;
}
[[nodiscard]] VmaAllocator allocator() const {
return m_allocator;
}
[[nodiscard]] const VkPhysicalDeviceFeatures &enabled_features() const {
return m_enabled_features;
}
[[nodiscard]] const std::string &gpu_name() const {
return m_gpu_name;
}
[[nodiscard]] std::span<const std::uint8_t, VK_UUID_SIZE> pipeline_cache_uuid() const {
return m_pipeline_cache_uuid;
}
[[nodiscard]] bool has_any_compute_queue() const {
return m_compute_queue != VK_NULL_HANDLE;
}
[[nodiscard]] bool has_any_transfer_queue() const {
return m_transfer_queue != VK_NULL_HANDLE;
}
[[nodiscard]] bool has_any_sparse_binding_queue() const {
return m_transfer_queue != VK_NULL_HANDLE;
}
// TODO: Move to command buffer wrapper!
[[nodiscard]] VkQueue compute_queue() const {
return m_graphics_queue;
}
// TODO: Move to command buffer wrapper!
[[nodiscard]] VkQueue graphics_queue() const {
return m_graphics_queue;
}
// TODO: Move to command buffer wrapper!
[[nodiscard]] VkQueue present_queue() const {
return m_present_queue;
}
// TODO: Move to command buffer wrapper!
[[nodiscard]] VkQueue transfer_queue() const {
return m_transfer_queue;
}
[[nodiscard]] const CommandBuffer &request_command_buffer(VulkanQueueType queue_type, const std::string &name);
[[nodiscard]] bool surface_supports_usage(VkSurfaceKHR surface, VkImageUsageFlagBits usage) const;
template <typename VulkanObjectType>
void set_debug_name(const VulkanObjectType &vk_object, const std::string &name) const {
if (!vk_object) {
throw InexorException("Error: Parameter 'vk_object' is invalid!");
}
const auto dbg_obj_name = wrapper::make_info<VkDebugUtilsObjectNameInfoEXT>({
.objectType = tools::get_vk_object_type(vk_object),
.objectHandle = reinterpret_cast<std::uint64_t>(vk_object),
.pObjectName = name.c_str(),
});
if (const auto result = vkSetDebugUtilsObjectNameEXT(m_device, &dbg_obj_name); result != VK_SUCCESS) {
throw VulkanException("Error: vkSetDebugUtilsObjectNameEXT failed!", result);
}
}
void wait_idle(VkQueue queue = VK_NULL_HANDLE) const;
};
} // namespace inexor::vulkan_renderer::wrapper