Orange/src/Orange/Render/Renderer.cpp

125 lines
3.8 KiB
C++

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