121 lines
3.1 KiB
C++
121 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include "result.hpp"
|
|
#include "props.hpp"
|
|
#include "Instance.hpp"
|
|
#include "Surface.hpp"
|
|
#include "resources/GpuAllocator.h"
|
|
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <stdexcept>
|
|
|
|
/**
|
|
* Abstract interface for a GPU
|
|
*/
|
|
class Gpu {
|
|
private:
|
|
const Instance* m_instance;
|
|
VkPhysicalDevice m_gpu = VK_NULL_HANDLE;
|
|
VkDevice m_dev = VK_NULL_HANDLE;
|
|
VkDescriptorPool m_descriptorPool{};
|
|
|
|
// Queue for a general commands
|
|
VkQueue m_graphicsQueue{};
|
|
uint32_t m_graphicsQueueIdx{};
|
|
VkCommandPool m_graphicsCommandPool{};
|
|
|
|
// Queue for a transfer commands
|
|
VkQueue m_transferQueue{};
|
|
uint32_t m_transferQueueIdx{};
|
|
VkCommandPool m_transferCommandPool{};
|
|
|
|
// Queue for present commands
|
|
VkQueue m_presentQueue{};
|
|
uint32_t m_presentQueueIdx{};
|
|
VkCommandPool m_presentCommandPool{};
|
|
|
|
VkCommandBuffer m_tracyCommandBuffer;
|
|
|
|
std::vector<int32_t> get_queues(std::optional<Surface*> surface);
|
|
|
|
ResultCode create_logical_device(std::optional<Surface*> surface);
|
|
|
|
ResultCode choose_gpu(VkPhysicalDevice *pOut);
|
|
|
|
ResultCode create_descriptor_pool();
|
|
|
|
std::unique_ptr<GpuAllocator> m_pAllocator;
|
|
|
|
public:
|
|
GET(m_gpu, gpu);
|
|
GET(m_dev, dev);
|
|
|
|
[[nodiscard]] const Instance* instance() const {
|
|
return m_instance;
|
|
}
|
|
|
|
GET(m_descriptorPool, descriptor_pool);
|
|
|
|
GET(m_graphicsCommandPool, graphics_command_pool);
|
|
GET(m_graphicsQueue, graphics_queue);
|
|
|
|
GET(m_transferCommandPool, transfer_command_pool);
|
|
GET(m_transferQueue, transfer_queue);
|
|
|
|
GET(m_tracyCommandBuffer, tracy_cmd_buf);
|
|
|
|
GET(m_pAllocator.get(), memory);
|
|
|
|
explicit
|
|
Gpu(const Instance* instance, std::optional<Surface*> surface);
|
|
|
|
~Gpu();
|
|
|
|
// Forbid copy
|
|
Gpu(const Gpu&) = delete;
|
|
|
|
static result<Gpu, ResultCode> create(std::shared_ptr<const Instance> instance, VkSurfaceKHR surface);
|
|
|
|
inline std::vector<uint32_t> present_queue_ids() const {
|
|
return {m_presentQueueIdx};
|
|
}
|
|
|
|
inline uint32_t transfer_queue_idx() const {
|
|
return m_transferQueueIdx;
|
|
}
|
|
|
|
|
|
void enqueue_present(VkPresentInfoKHR *pPresentInfo) const;
|
|
void enqueue_graphics(VkSubmitInfo2 *pSubmitInfo, VkFence fence) const;
|
|
void enqueue_transfer(VkSubmitInfo *pSubmitInfo, VkFence fence) const;
|
|
|
|
inline VkSemaphore create_semaphore() const {
|
|
VkSemaphoreCreateInfo semaphore_info = {
|
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
|
};
|
|
|
|
VkSemaphore semaphore = VK_NULL_HANDLE;
|
|
if(vkCreateSemaphore(this->dev(), &semaphore_info, nullptr, &semaphore)) {
|
|
throw std::runtime_error("Failed to create semaphore");
|
|
}
|
|
|
|
return semaphore;
|
|
}
|
|
|
|
inline VkFence create_fence(bool is_signaled) const {
|
|
VkFenceCreateInfo fence_info = {
|
|
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
|
.flags = is_signaled ? VK_FENCE_CREATE_SIGNALED_BIT : (VkFenceCreateFlagBits)0
|
|
};
|
|
|
|
VkFence fence = VK_NULL_HANDLE;
|
|
if(vkCreateFence(this->dev(), &fence_info, nullptr, &fence)) {
|
|
throw std::runtime_error("Failed to create fence");
|
|
}
|
|
|
|
return fence;
|
|
}
|
|
};
|