This commit is contained in:
Joshua Ashton 2022-08-03 05:33:52 +01:00
parent 6f44e7e8b1
commit 72f6214fdf
9 changed files with 203 additions and 157 deletions

View File

@ -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)>;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
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)
: m_instance{ instance }
{}
Instance::Instance(VkInstance instance, Span<PhysicalDevice> physicalDevices)
: m_instance { instance }
, m_physicalDevices{ physicalDevices }
{
}
Instance::~Instance()
{

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -3,7 +3,8 @@ orange_src = [
'Render/Instance.cpp',
'Render/PhysicalDevice.cpp',
'Render/Renderer.cpp',
'Render/Device.cpp',
'Render/Utils.cpp',
'Render/Window.cpp',
]