2022-08-04 03:00:54 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <Orange/Core/Types.h>
|
2022-08-13 07:18:10 +01:00
|
|
|
#include <Orange/Core/Traits.h>
|
2022-08-04 03:00:54 +01:00
|
|
|
#include <Orange/Core/Span.h>
|
|
|
|
#include <Orange/Core/Result.h>
|
|
|
|
|
|
|
|
#include <vulkan/vulkan_core.h>
|
|
|
|
|
|
|
|
namespace orange
|
|
|
|
{
|
2022-08-12 20:08:28 +01:00
|
|
|
struct BufferSlice
|
2022-08-12 13:34:04 +01:00
|
|
|
{
|
2022-08-12 20:08:28 +01:00
|
|
|
VkBuffer buffer;
|
|
|
|
VkDeviceSize offset;
|
|
|
|
VkDeviceSize size;
|
2022-08-13 21:41:19 +01:00
|
|
|
void* ptr;
|
2022-08-12 20:08:28 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct GPUMemoryBuffer
|
|
|
|
{
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
VkBuffer buffer;
|
|
|
|
VkDeviceSize size;
|
|
|
|
void* ptr;
|
|
|
|
};
|
|
|
|
|
2022-08-13 07:18:10 +01:00
|
|
|
class MemoryPool
|
2022-08-12 20:08:28 +01:00
|
|
|
{
|
|
|
|
public:
|
2022-08-13 07:18:10 +01:00
|
|
|
MemoryPool(GPUMemoryBuffer buffer)
|
2022-08-12 20:08:28 +01:00
|
|
|
: m_buffer{ buffer } {}
|
|
|
|
|
2022-08-13 07:18:10 +01:00
|
|
|
Result<BufferSlice> AllocSlice(VkDeviceSize size, VkDeviceSize alignment = 1u)
|
2022-08-12 20:08:28 +01:00
|
|
|
{
|
2022-08-13 07:18:10 +01:00
|
|
|
uint32_t offset = Align(m_offset, alignment);
|
2022-08-13 21:41:19 +01:00
|
|
|
BufferSlice slice{ m_buffer.buffer, offset, size,
|
|
|
|
m_buffer.ptr ? reinterpret_cast<uint8_t*>(m_buffer.ptr) + offset : nullptr };
|
2022-08-12 20:08:28 +01:00
|
|
|
|
2022-08-13 07:18:10 +01:00
|
|
|
if (offset + size > m_buffer.size)
|
2022-08-12 20:08:28 +01:00
|
|
|
return Result<BufferSlice>::Error();
|
|
|
|
|
2022-08-13 07:18:10 +01:00
|
|
|
m_offset = offset + size;
|
2022-08-12 20:08:28 +01:00
|
|
|
|
|
|
|
return Result<BufferSlice>::Success(slice);
|
|
|
|
}
|
2022-08-13 07:18:10 +01:00
|
|
|
|
|
|
|
VkDeviceMemory Memory() const
|
|
|
|
{
|
|
|
|
return m_buffer.memory;
|
|
|
|
}
|
2022-08-12 13:34:04 +01:00
|
|
|
private:
|
2022-08-12 20:08:28 +01:00
|
|
|
GPUMemoryBuffer m_buffer = {};
|
|
|
|
VkDeviceSize m_offset = 0u;
|
2022-08-12 13:34:04 +01:00
|
|
|
};
|
|
|
|
|
2023-01-18 08:53:40 +00:00
|
|
|
/*
|
|
|
|
template <typename T>
|
|
|
|
struct VkHandleDestructor
|
|
|
|
{
|
|
|
|
void destroy(T)
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
class VkHandle
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
VkHandle() { }
|
|
|
|
|
|
|
|
VkHandle(std::nullptr_t) { }
|
|
|
|
|
|
|
|
VkHandle(T handle)
|
|
|
|
: m_handle(handle) { }
|
|
|
|
|
|
|
|
~VkHandle()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
T get() const { return m_handle; }
|
|
|
|
|
|
|
|
T* operator & () { return &m_handle; }
|
|
|
|
const T* operator & () const { return &m_handle; }
|
|
|
|
|
|
|
|
T operator -> () const { return m_handle; }
|
|
|
|
operator T() const { return m_handle; }
|
|
|
|
operator bool() const { return handle != VK_NULL_HANDLE; }
|
|
|
|
|
|
|
|
bool operator == (T other) const { return m_handle == other; }
|
|
|
|
bool operator != (T other) const { return m_handle != other; }
|
|
|
|
|
|
|
|
bool operator == (std::nullptr_t) const { return m_ptr == VK_NULL_HANDLE; }
|
|
|
|
bool operator != (std::nullptr_t) const { return m_ptr != VK_NULL_HANDLE; }
|
|
|
|
private:
|
|
|
|
T m_handle = VK_NULL_HANDLE;
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
|
2022-08-04 03:00:54 +01:00
|
|
|
template <typename T>
|
|
|
|
using VulkanResult = Result<T, VkResult, VK_SUCCESS, VK_ERROR_UNKNOWN, VK_ERROR_UNKNOWN>;
|
|
|
|
|
2022-08-12 20:08:28 +01:00
|
|
|
struct VkMemoryTypes
|
|
|
|
{
|
|
|
|
uint32_t cpuTypeIdx = -1;
|
|
|
|
uint32_t gpuOnlyTypeIdx = -1;
|
|
|
|
uint32_t gpuHostVisibleTypeIdx = -1;
|
|
|
|
};
|
|
|
|
|
2022-08-04 03:00:54 +01:00
|
|
|
class RenderContext
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
~RenderContext();
|
|
|
|
|
2022-08-04 18:23:08 +01:00
|
|
|
static VulkanResult<RenderContext> Create(const char *appName);
|
2022-08-04 03:00:54 +01:00
|
|
|
|
|
|
|
VkInstance Instance() const { return m_instance; }
|
|
|
|
VkPhysicalDevice PhysicalDevice() const { return m_physicalDevice; }
|
|
|
|
VkDevice Device() const { return m_device; }
|
|
|
|
VkQueue Queue() const { return m_queue; }
|
2022-08-04 20:00:53 +01:00
|
|
|
VkCommandPool CommandPool() const { return m_commandPool; }
|
|
|
|
|
2022-08-12 20:08:28 +01:00
|
|
|
VulkanResult<VkFence> CreateFence(bool signalled);
|
|
|
|
VulkanResult<VkSemaphore> CreateSemaphore();
|
|
|
|
VulkanResult<VoidResult> BeginCommandBuffer(VkCommandBuffer buffer);
|
|
|
|
VulkanResult<VoidResult> EndCommandBuffer(VkCommandBuffer buffer);
|
|
|
|
VulkanResult<GPUMemoryBuffer> CreateBuffer(VkDeviceSize size);
|
2022-08-13 21:41:19 +01:00
|
|
|
VulkanResult<VkImage> CreateImage(MemoryPool& pool, uint32_t width, uint32_t height, VkFormat format, VkImageUsageFlags usage);
|
|
|
|
VulkanResult<VkImageView> CreateImageView(VkImage image, VkFormat format, VkImageAspectFlagBits aspect);
|
2022-08-07 06:09:59 +01:00
|
|
|
|
|
|
|
VulkanResult<VkShaderModule> CreateShader(Span<const uint32_t> code);
|
2022-08-13 07:18:10 +01:00
|
|
|
|
|
|
|
const VkPhysicalDeviceProperties& Props() const { return m_props; }
|
2022-08-04 03:00:54 +01:00
|
|
|
protected:
|
2022-08-04 18:23:08 +01:00
|
|
|
friend VulkanResult<RenderContext>;
|
|
|
|
RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,
|
|
|
|
VkQueue queue, VkCommandPool commandPool)
|
|
|
|
: m_instance{ instance }, m_physicalDevice{ physicalDevice }, m_device{ device }
|
2022-08-12 20:08:28 +01:00
|
|
|
, m_queue{ queue }, m_commandPool{ commandPool }
|
|
|
|
{
|
|
|
|
VkPhysicalDeviceMemoryProperties memoryProps;
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memoryProps);
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
uint32_t* ptr;
|
|
|
|
VkMemoryPropertyFlags flags;
|
|
|
|
} memoryTypeMapping[] =
|
|
|
|
{
|
|
|
|
{ &m_memoryTypes.gpuHostVisibleTypeIdx,
|
|
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
|
|
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT },
|
|
|
|
|
|
|
|
{ &m_memoryTypes.gpuOnlyTypeIdx,
|
|
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT },
|
|
|
|
|
|
|
|
{ &m_memoryTypes.cpuTypeIdx,
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
|
|
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT },
|
|
|
|
};
|
|
|
|
|
|
|
|
for (auto& mapping : memoryTypeMapping)
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < memoryProps.memoryTypeCount; i++)
|
|
|
|
{
|
|
|
|
if (memoryProps.memoryTypes[i].propertyFlags & mapping.flags)
|
|
|
|
{
|
|
|
|
*mapping.ptr = i;
|
|
|
|
|
|
|
|
if (memoryProps.memoryTypes[i].propertyFlags == mapping.flags)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-13 07:18:10 +01:00
|
|
|
vkGetPhysicalDeviceProperties(m_physicalDevice, &m_props);
|
2022-08-12 20:08:28 +01:00
|
|
|
}
|
2022-08-04 03:00:54 +01:00
|
|
|
private:
|
|
|
|
VkInstance m_instance = VK_NULL_HANDLE;
|
|
|
|
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
|
|
|
VkDevice m_device = VK_NULL_HANDLE;
|
|
|
|
VkQueue m_queue = VK_NULL_HANDLE;
|
2022-08-04 18:23:08 +01:00
|
|
|
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
2022-08-12 20:08:28 +01:00
|
|
|
|
2022-08-13 07:18:10 +01:00
|
|
|
VkPhysicalDeviceProperties m_props{};
|
2022-08-12 20:08:28 +01:00
|
|
|
VkMemoryTypes m_memoryTypes{};
|
2022-08-04 03:00:54 +01:00
|
|
|
};
|
|
|
|
}
|