Work
This commit is contained in:
parent
6f44e7e8b1
commit
72f6214fdf
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <Orange/Core/AlignedStorage.h>
|
||||
#include <Orange/Core/Span.h>
|
||||
|
||||
namespace orange
|
||||
{
|
||||
|
@ -11,6 +12,12 @@ namespace orange
|
|||
|
||||
SmallVector() {}
|
||||
SmallVector(size_t size) { Resize(size); }
|
||||
SmallVector(Span<T> span)
|
||||
{
|
||||
Reserve(span.size);
|
||||
for (const auto& val : span)
|
||||
PushBack(val);
|
||||
}
|
||||
|
||||
SmallVector (const SmallVector&) = delete;
|
||||
SmallVector& operator = (const SmallVector&) = delete;
|
||||
|
@ -114,6 +121,8 @@ namespace orange
|
|||
T& back() { return *Ptr(m_size - 1); }
|
||||
const T& back() const { return *Ptr(m_size - 1); }
|
||||
|
||||
operator Span<T>() { return Span<T>(*this); }
|
||||
|
||||
private:
|
||||
using Storage = AlignedStorage<sizeof(T), alignof(T)>;
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ namespace orange
|
|||
template <size_t Count>
|
||||
Span(T (&array)[Count]) : data(array), size(Count) {}
|
||||
|
||||
template <typename J>
|
||||
Span(J& x)
|
||||
: data(x.begin())
|
||||
, size(x.end() - x.begin()) {}
|
||||
|
||||
explicit Span(T* data) : data(data), size(1) {}
|
||||
explicit Span(T& data) : data(&data), size(1) {}
|
||||
|
||||
|
@ -20,11 +25,17 @@ namespace orange
|
|||
|
||||
bool IsEmpty() const { return size == 0; }
|
||||
|
||||
T& front() { return *data[idx]; }
|
||||
const T& front() const { return *data[idx]; }
|
||||
T* begin() { return &data[0]; }
|
||||
const T* begin() const { return &data[0]; }
|
||||
|
||||
T& back() { return *data[size - 1]; }
|
||||
const T& back() const { return *data[size - 1]; }
|
||||
T* end() { return &data[size]; }
|
||||
const T* end() const { return &data[size]; }
|
||||
|
||||
T& front() { return data[0]; }
|
||||
const T& front() const { return data[0]; }
|
||||
|
||||
T& back() { return data[size - 1]; }
|
||||
const T& back() const { return data[size - 1]; }
|
||||
|
||||
T* data;
|
||||
size_t size;
|
||||
|
|
|
@ -1,31 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <Orange/Core/Types.h>
|
||||
#include <Orange/Core/Span.h>
|
||||
#include <Orange/Core/Result.h>
|
||||
#include <Orange/Core/SmallVector.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace orange
|
||||
{
|
||||
class Window;
|
||||
|
||||
class Instance
|
||||
{
|
||||
public:
|
||||
~Instance();
|
||||
|
||||
static Result<Instance> Create(Window& window, const char* name);
|
||||
|
||||
VkInstance operator *() { return m_instance; }
|
||||
protected:
|
||||
friend Result<Instance>;
|
||||
Instance(VkInstance instance);
|
||||
private:
|
||||
VkInstance m_instance = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
class PhysicalDevice
|
||||
{
|
||||
public:
|
||||
|
@ -50,15 +35,48 @@ namespace orange
|
|||
uint32_t m_graphicsQueueFamilyIndex = ~0u;
|
||||
};
|
||||
|
||||
class Renderer
|
||||
class Instance
|
||||
{
|
||||
public:
|
||||
~Renderer();
|
||||
~Instance();
|
||||
|
||||
static Result<Renderer> Create(Instance& instance);
|
||||
static Result<Instance> Create(Window& window, const char* name);
|
||||
|
||||
VkInstance operator *() { return m_instance; }
|
||||
|
||||
Span<PhysicalDevice> PhysicalDevices() { return m_physicalDevices; }
|
||||
protected:
|
||||
friend Result<Renderer>;
|
||||
Renderer(Instance& instance, PhysicalDevice physicalDevice, VkDevice device);
|
||||
friend Result<Instance>;
|
||||
Instance(VkInstance instance, Span<PhysicalDevice> physicalDevice);
|
||||
private:
|
||||
VkInstance m_instance = VK_NULL_HANDLE;
|
||||
|
||||
SmallVector<PhysicalDevice, 32> m_physicalDevices;
|
||||
};
|
||||
|
||||
class GPUBuffer
|
||||
{
|
||||
public:
|
||||
~GPUBuffer();
|
||||
|
||||
static Result<GPUBuffer> Create();
|
||||
protected:
|
||||
friend Result<GPUBuffer>;
|
||||
GPUBuffer(VkDeviceMemory memory, VkBuffer buffer, void* ptr);
|
||||
private:
|
||||
VkDeviceMemory m_memory;
|
||||
VkBuffer m_buffer;
|
||||
};
|
||||
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
~Device();
|
||||
|
||||
static Result<Device> Create(Instance& instance, PhysicalDevice physicalDevice);
|
||||
protected:
|
||||
friend Result<Device>;
|
||||
Device(Instance& instance, PhysicalDevice physicalDevice, VkDevice device);
|
||||
private:
|
||||
Instance& m_instance;
|
||||
PhysicalDevice m_physicalDevice;
|
||||
|
@ -66,4 +84,13 @@ namespace orange
|
|||
VkQueue m_queue = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
class Swapchain
|
||||
{
|
||||
public:
|
||||
~Swapchain();
|
||||
|
||||
static Result<Swapchain> Create();
|
||||
};
|
||||
|
||||
PhysicalDevice PickBestPhysicalDevice(Span<PhysicalDevice> physDevs);
|
||||
}
|
|
@ -17,8 +17,10 @@ int main(int argc, char** argv)
|
|||
if (!r_instance)
|
||||
return 1;
|
||||
|
||||
Result<Renderer> r_renderer = Renderer::Create(*r_instance);
|
||||
if (!r_renderer)
|
||||
PhysicalDevice physicalDevice = PickBestPhysicalDevice(r_instance->PhysicalDevices());
|
||||
|
||||
Result<Device> r_device = Device::Create(*r_instance, physicalDevice);
|
||||
if (!r_device)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#include "Orange/Core/Log.h"
|
||||
#include "Orange/Core/Result.h"
|
||||
#include <Orange/Render/Renderer.h>
|
||||
|
||||
namespace orange
|
||||
{
|
||||
static VkDevice CreateDevice(PhysicalDevice physDev)
|
||||
{
|
||||
constexpr float queuePriority = 1.0f;
|
||||
VkDeviceQueueCreateInfo queueInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||
.queueFamilyIndex = physDev.GraphicsQueueFamilyIndex(),
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = &queuePriority,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceFeatures features{};
|
||||
|
||||
VkDeviceCreateInfo deviceInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &queueInfo,
|
||||
.pEnabledFeatures = &features,
|
||||
};
|
||||
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
if (vkCreateDevice(*physDev, &deviceInfo, nullptr, &device) != VK_SUCCESS)
|
||||
{
|
||||
log::err("Failed to create Vulkan logical device");
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
Result<Device> Device::Create(Instance& instance, PhysicalDevice physicalDevice)
|
||||
{
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
if (!(device = CreateDevice(physicalDevice)))
|
||||
{
|
||||
log::err("Failed to create Vulkan device");
|
||||
return Result<Device>::Error(BasicErrorCode::Failed);
|
||||
}
|
||||
|
||||
return Result<Device>::Success(instance, physicalDevice, device);
|
||||
}
|
||||
|
||||
Device::Device(Instance& instance, PhysicalDevice physicalDevice, VkDevice device)
|
||||
: m_instance { instance }
|
||||
, m_physicalDevice{ physicalDevice }
|
||||
, m_device { device }
|
||||
{
|
||||
vkGetDeviceQueue(m_device, m_physicalDevice.GraphicsQueueFamilyIndex(), 0, &m_queue);
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
vkDestroyDevice(m_device, nullptr);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
#include "Orange/Core/Log.h"
|
||||
#include <Orange/Core/Log.h>
|
||||
#include <Orange/Render/Renderer.h>
|
||||
#include <Orange/Render/Window.h>
|
||||
|
||||
|
@ -58,12 +58,48 @@ namespace orange
|
|||
return Result<Instance>::Error(BasicErrorCode::Failed);
|
||||
}
|
||||
|
||||
return Result<Instance>::Success(instance);
|
||||
SmallVector<PhysicalDevice, 32> physicalDevices;
|
||||
{
|
||||
uint32_t vulkanPhysicalDeviceCount = {};
|
||||
if (vkEnumeratePhysicalDevices(instance, &vulkanPhysicalDeviceCount, nullptr) != VK_SUCCESS)
|
||||
{
|
||||
log::err("Failed to get physical device count");
|
||||
return Result<Instance>::Error(BasicErrorCode::Failed);
|
||||
}
|
||||
|
||||
Instance::Instance(VkInstance instance)
|
||||
if (!vulkanPhysicalDeviceCount)
|
||||
{
|
||||
log::err("No physical devices found");
|
||||
return Result<Instance>::Error(BasicErrorCode::Failed);
|
||||
}
|
||||
|
||||
{
|
||||
SmallVector<VkPhysicalDevice, 32> vulkanPhysicalDevices{ vulkanPhysicalDeviceCount };
|
||||
if (vkEnumeratePhysicalDevices(instance, &vulkanPhysicalDeviceCount, vulkanPhysicalDevices.Data()) != VK_SUCCESS)
|
||||
{
|
||||
log::err("Failed to enumerate physical devices");
|
||||
return Result<Instance>::Error(BasicErrorCode::Failed);
|
||||
}
|
||||
|
||||
for (auto& physDev : vulkanPhysicalDevices)
|
||||
{
|
||||
Result<PhysicalDevice> r_physDev = PhysicalDevice::Create(physDev);
|
||||
if (!r_physDev)
|
||||
continue;
|
||||
|
||||
physicalDevices.PushBack(*r_physDev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result<Instance>::Success(instance, physicalDevices);
|
||||
}
|
||||
|
||||
Instance::Instance(VkInstance instance, Span<PhysicalDevice> physicalDevices)
|
||||
: m_instance { instance }
|
||||
{}
|
||||
, m_physicalDevices{ physicalDevices }
|
||||
{
|
||||
}
|
||||
|
||||
Instance::~Instance()
|
||||
{
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
#include "Orange/Core/Log.h"
|
||||
#include "Orange/Core/Result.h"
|
||||
#include <Orange/Render/Renderer.h>
|
||||
|
||||
namespace orange
|
||||
{
|
||||
static PhysicalDevice PickBestPhysicalDevice(PhysicalDevice *physDevs, size_t count)
|
||||
{
|
||||
PhysicalDevice bestPhysDev;
|
||||
int bestScore = -1;
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
PhysicalDevice physDev = physDevs[i];
|
||||
if (int score = physDev.Score() > bestScore)
|
||||
{
|
||||
bestPhysDev = physDev;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
|
||||
return bestPhysDev;
|
||||
}
|
||||
|
||||
static PhysicalDevice FindPhysicalDevice(Instance& instance)
|
||||
{
|
||||
uint32_t vulkanPhysicalDeviceCount = {};
|
||||
if (vkEnumeratePhysicalDevices(*instance, &vulkanPhysicalDeviceCount, nullptr) != VK_SUCCESS)
|
||||
{
|
||||
log::err("Failed to get physical device count");
|
||||
return PhysicalDevice{};
|
||||
}
|
||||
|
||||
if (!vulkanPhysicalDeviceCount)
|
||||
{
|
||||
log::err("No physical devices found");
|
||||
return PhysicalDevice{};
|
||||
}
|
||||
|
||||
SmallVector<PhysicalDevice, 32> physicalDevices;
|
||||
{
|
||||
SmallVector<VkPhysicalDevice, 32> vulkanPhysicalDevices{ vulkanPhysicalDeviceCount };
|
||||
if (vkEnumeratePhysicalDevices(*instance, &vulkanPhysicalDeviceCount, vulkanPhysicalDevices.Data()) != VK_SUCCESS)
|
||||
{
|
||||
log::err("Failed to enumerate physical devices");
|
||||
return PhysicalDevice{};
|
||||
}
|
||||
|
||||
for (auto& physDev : vulkanPhysicalDevices)
|
||||
{
|
||||
Result<PhysicalDevice> r_physDev = PhysicalDevice::Create(physDev);
|
||||
if (!r_physDev)
|
||||
continue;
|
||||
|
||||
physicalDevices.PushBack(*r_physDev);
|
||||
}
|
||||
}
|
||||
|
||||
return PickBestPhysicalDevice(physicalDevices.Data(), physicalDevices.Size());
|
||||
}
|
||||
|
||||
static VkDevice CreateDevice(PhysicalDevice physDev)
|
||||
{
|
||||
constexpr float queuePriority = 1.0f;
|
||||
VkDeviceQueueCreateInfo queueInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||
.queueFamilyIndex = physDev.GraphicsQueueFamilyIndex(),
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = &queuePriority,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceFeatures features{};
|
||||
|
||||
VkDeviceCreateInfo deviceInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &queueInfo,
|
||||
.pEnabledFeatures = &features,
|
||||
};
|
||||
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
if (vkCreateDevice(*physDev, &deviceInfo, nullptr, &device) != VK_SUCCESS)
|
||||
{
|
||||
log::err("Failed to create Vulkan logical device");
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
Result<Renderer> Renderer::Create(Instance& instance)
|
||||
{
|
||||
PhysicalDevice physicalDevice;
|
||||
if (!(physicalDevice = FindPhysicalDevice(instance)))
|
||||
{
|
||||
log::err("Failed to find a physical device");
|
||||
return Result<Renderer>::Error(BasicErrorCode::Failed);
|
||||
}
|
||||
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
if (!(device = CreateDevice(physicalDevice)))
|
||||
{
|
||||
log::err("Failed to create Vulkan device");
|
||||
return Result<Renderer>::Error(BasicErrorCode::Failed);
|
||||
}
|
||||
|
||||
return Result<Renderer>::Success(instance, physicalDevice, device);
|
||||
}
|
||||
|
||||
Renderer::Renderer(Instance& instance, PhysicalDevice physicalDevice, VkDevice device)
|
||||
: m_instance { instance }
|
||||
, m_physicalDevice{ physicalDevice }
|
||||
, m_device { device }
|
||||
{
|
||||
vkGetDeviceQueue(m_device, m_physicalDevice.GraphicsQueueFamilyIndex(), 0, &m_queue);
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
vkDestroyDevice(m_device, nullptr);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#include <Orange/Core/Log.h>
|
||||
#include <Orange/Render/Renderer.h>
|
||||
|
||||
namespace orange
|
||||
{
|
||||
PhysicalDevice PickBestPhysicalDevice(Span<PhysicalDevice> physDevs)
|
||||
{
|
||||
PhysicalDevice bestPhysDev;
|
||||
int bestScore = -1;
|
||||
for (auto physDev : physDevs)
|
||||
{
|
||||
if (int score = physDev.Score() > bestScore)
|
||||
{
|
||||
bestPhysDev = physDev;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
|
||||
return bestPhysDev;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,8 @@ orange_src = [
|
|||
|
||||
'Render/Instance.cpp',
|
||||
'Render/PhysicalDevice.cpp',
|
||||
'Render/Renderer.cpp',
|
||||
'Render/Device.cpp',
|
||||
'Render/Utils.cpp',
|
||||
'Render/Window.cpp',
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue