125 lines
3.8 KiB
C++
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);
|
|
}
|
|
|
|
}
|