diff --git a/include/Orange/Core/SmallVector.h b/include/Orange/Core/SmallVector.h index e3e9c20..4a30cdb 100644 --- a/include/Orange/Core/SmallVector.h +++ b/include/Orange/Core/SmallVector.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace orange { @@ -11,6 +12,12 @@ namespace orange SmallVector() {} SmallVector(size_t size) { Resize(size); } + SmallVector(Span 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() { return Span(*this); } + private: using Storage = AlignedStorage; diff --git a/include/Orange/Core/Span.h b/include/Orange/Core/Span.h index a572388..a835b8f 100644 --- a/include/Orange/Core/Span.h +++ b/include/Orange/Core/Span.h @@ -12,6 +12,11 @@ namespace orange template Span(T (&array)[Count]) : data(array), size(Count) {} + template + 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; diff --git a/include/Orange/Render/Renderer.h b/include/Orange/Render/Renderer.h index a86498e..b93c93f 100644 --- a/include/Orange/Render/Renderer.h +++ b/include/Orange/Render/Renderer.h @@ -1,31 +1,16 @@ #pragma once #include +#include #include #include -#include #include namespace orange { class Window; - class Instance - { - public: - ~Instance(); - - static Result Create(Window& window, const char* name); - - VkInstance operator *() { return m_instance; } - protected: - friend Result; - 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 Create(Instance& instance); + static Result Create(Window& window, const char* name); + + VkInstance operator *() { return m_instance; } + + Span PhysicalDevices() { return m_physicalDevices; } protected: - friend Result; - Renderer(Instance& instance, PhysicalDevice physicalDevice, VkDevice device); + friend Result; + Instance(VkInstance instance, Span physicalDevice); + private: + VkInstance m_instance = VK_NULL_HANDLE; + + SmallVector m_physicalDevices; + }; + + class GPUBuffer + { + public: + ~GPUBuffer(); + + static Result Create(); + protected: + friend Result; + GPUBuffer(VkDeviceMemory memory, VkBuffer buffer, void* ptr); + private: + VkDeviceMemory m_memory; + VkBuffer m_buffer; + }; + + class Device + { + public: + ~Device(); + + static Result Create(Instance& instance, PhysicalDevice physicalDevice); + protected: + friend Result; + 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 Create(); + }; + + PhysicalDevice PickBestPhysicalDevice(Span physDevs); } \ No newline at end of file diff --git a/src/Apps/Tools/CubeTest.cpp b/src/Apps/Tools/CubeTest.cpp index d3c5723..182bded 100644 --- a/src/Apps/Tools/CubeTest.cpp +++ b/src/Apps/Tools/CubeTest.cpp @@ -17,8 +17,10 @@ int main(int argc, char** argv) if (!r_instance) return 1; - Result r_renderer = Renderer::Create(*r_instance); - if (!r_renderer) + PhysicalDevice physicalDevice = PickBestPhysicalDevice(r_instance->PhysicalDevices()); + + Result r_device = Device::Create(*r_instance, physicalDevice); + if (!r_device) return 1; return 0; diff --git a/src/Orange/Render/Device.cpp b/src/Orange/Render/Device.cpp new file mode 100644 index 0000000..64ea588 --- /dev/null +++ b/src/Orange/Render/Device.cpp @@ -0,0 +1,63 @@ +#include "Orange/Core/Log.h" +#include "Orange/Core/Result.h" +#include + +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::Create(Instance& instance, PhysicalDevice physicalDevice) + { + VkDevice device = VK_NULL_HANDLE; + if (!(device = CreateDevice(physicalDevice))) + { + log::err("Failed to create Vulkan device"); + return Result::Error(BasicErrorCode::Failed); + } + + return Result::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); + } + +} diff --git a/src/Orange/Render/Instance.cpp b/src/Orange/Render/Instance.cpp index 1d82f5a..e3a7761 100644 --- a/src/Orange/Render/Instance.cpp +++ b/src/Orange/Render/Instance.cpp @@ -1,4 +1,4 @@ -#include "Orange/Core/Log.h" +#include #include #include @@ -58,12 +58,48 @@ namespace orange return Result::Error(BasicErrorCode::Failed); } - return Result::Success(instance); + SmallVector physicalDevices; + { + uint32_t vulkanPhysicalDeviceCount = {}; + if (vkEnumeratePhysicalDevices(instance, &vulkanPhysicalDeviceCount, nullptr) != VK_SUCCESS) + { + log::err("Failed to get physical device count"); + return Result::Error(BasicErrorCode::Failed); + } + + if (!vulkanPhysicalDeviceCount) + { + log::err("No physical devices found"); + return Result::Error(BasicErrorCode::Failed); + } + + { + SmallVector vulkanPhysicalDevices{ vulkanPhysicalDeviceCount }; + if (vkEnumeratePhysicalDevices(instance, &vulkanPhysicalDeviceCount, vulkanPhysicalDevices.Data()) != VK_SUCCESS) + { + log::err("Failed to enumerate physical devices"); + return Result::Error(BasicErrorCode::Failed); + } + + for (auto& physDev : vulkanPhysicalDevices) + { + Result r_physDev = PhysicalDevice::Create(physDev); + if (!r_physDev) + continue; + + physicalDevices.PushBack(*r_physDev); + } + } + } + + return Result::Success(instance, physicalDevices); } - Instance::Instance(VkInstance instance) - : m_instance{ instance } - {} + Instance::Instance(VkInstance instance, Span physicalDevices) + : m_instance { instance } + , m_physicalDevices{ physicalDevices } + { + } Instance::~Instance() { diff --git a/src/Orange/Render/Renderer.cpp b/src/Orange/Render/Renderer.cpp deleted file mode 100644 index 8806187..0000000 --- a/src/Orange/Render/Renderer.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include "Orange/Core/Log.h" -#include "Orange/Core/Result.h" -#include - -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 physicalDevices; - { - SmallVector vulkanPhysicalDevices{ vulkanPhysicalDeviceCount }; - if (vkEnumeratePhysicalDevices(*instance, &vulkanPhysicalDeviceCount, vulkanPhysicalDevices.Data()) != VK_SUCCESS) - { - log::err("Failed to enumerate physical devices"); - return PhysicalDevice{}; - } - - for (auto& physDev : vulkanPhysicalDevices) - { - Result 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::Create(Instance& instance) - { - PhysicalDevice physicalDevice; - if (!(physicalDevice = FindPhysicalDevice(instance))) - { - log::err("Failed to find a physical device"); - return Result::Error(BasicErrorCode::Failed); - } - - VkDevice device = VK_NULL_HANDLE; - if (!(device = CreateDevice(physicalDevice))) - { - log::err("Failed to create Vulkan device"); - return Result::Error(BasicErrorCode::Failed); - } - - return Result::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); - } - -} diff --git a/src/Orange/Render/Utils.cpp b/src/Orange/Render/Utils.cpp new file mode 100644 index 0000000..8def08c --- /dev/null +++ b/src/Orange/Render/Utils.cpp @@ -0,0 +1,21 @@ +#include +#include + +namespace orange +{ + PhysicalDevice PickBestPhysicalDevice(Span physDevs) + { + PhysicalDevice bestPhysDev; + int bestScore = -1; + for (auto physDev : physDevs) + { + if (int score = physDev.Score() > bestScore) + { + bestPhysDev = physDev; + bestScore = score; + } + } + + return bestPhysDev; + } +} \ No newline at end of file diff --git a/src/Orange/meson.build b/src/Orange/meson.build index 267c334..775df3d 100644 --- a/src/Orange/meson.build +++ b/src/Orange/meson.build @@ -3,7 +3,8 @@ orange_src = [ 'Render/Instance.cpp', 'Render/PhysicalDevice.cpp', - 'Render/Renderer.cpp', + 'Render/Device.cpp', + 'Render/Utils.cpp', 'Render/Window.cpp', ]