Added pick device support
This commit is contained in:
21
main.cpp
21
main.cpp
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace PB::Renderer
|
||||
{
|
||||
void CleanupAllAndExit()
|
||||
void CleanupAllAndExit(int code)
|
||||
{
|
||||
if (!GLFWManager::Cleanup())
|
||||
std::exit(EXIT_FAILURE);
|
||||
@@ -13,7 +13,7 @@ namespace PB::Renderer
|
||||
if (VulkanManager::Cleanup())
|
||||
std::exit(EXIT_FAILURE);
|
||||
|
||||
std::exit(EXIT_SUCCESS);
|
||||
std::exit(code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,17 +29,20 @@ int main()
|
||||
if (!window)
|
||||
return -1;
|
||||
|
||||
/* Creates the Vulkan instance and surface */
|
||||
if (std::optional<VkInstance> instance = VulkanManager::Init(); !instance)
|
||||
/* Runs Vulkan initialisation functions */
|
||||
if (const std::optional<VkInstance> instance = VulkanManager::Init(); !instance)
|
||||
{
|
||||
GLFWManager::Cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (std::optional<VkSurfaceKHR> surface = VulkanManager::CreateSurface(window); !surface)
|
||||
if (const std::optional<VkSurfaceKHR> surface = VulkanManager::CreateSurface(window); !surface)
|
||||
{
|
||||
CleanupAllAndExit();
|
||||
return -1;
|
||||
CleanupAllAndExit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!VulkanManager::PickPhysicalDevice())
|
||||
{
|
||||
CleanupAllAndExit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Polls window events whilst it is still open */
|
||||
@@ -49,5 +52,5 @@ int main()
|
||||
}
|
||||
|
||||
/* Cleans up GLFW and Vulkan */
|
||||
CleanupAllAndExit();
|
||||
CleanupAllAndExit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -12,3 +12,4 @@
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
@@ -5,6 +5,9 @@ namespace PB::Renderer
|
||||
std::optional<VkInstance> VulkanManager::s_Instance = std::nullopt;
|
||||
std::optional<VkSurfaceKHR> VulkanManager::s_Surface = std::nullopt;
|
||||
|
||||
VkPhysicalDevice VulkanManager::s_PhysicalDevice = VK_NULL_HANDLE;
|
||||
QueueFamilyIndices VulkanManager::s_QueueIndices;
|
||||
|
||||
std::optional<VkInstance> VulkanManager::Init()
|
||||
{
|
||||
/* Stops multi initialisation */
|
||||
@@ -47,6 +50,12 @@ namespace PB::Renderer
|
||||
|
||||
std::optional<VkSurfaceKHR> VulkanManager::CreateSurface(GLFWwindow* window)
|
||||
{
|
||||
if (s_Instance == std::nullopt)
|
||||
{
|
||||
std::cout << "PB::Renderer::VulkanManager::CreateSurface(): No Vulkan instance" << std::endl;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
VkSurfaceKHR surface;
|
||||
if (glfwCreateWindowSurface(s_Instance.value(), window, nullptr, &surface) != VK_SUCCESS)
|
||||
{
|
||||
@@ -54,9 +63,130 @@ namespace PB::Renderer
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
s_Surface = surface;
|
||||
return surface;
|
||||
}
|
||||
|
||||
bool VulkanManager::PickPhysicalDevice()
|
||||
{
|
||||
if (s_Instance == std::nullopt || s_Surface == std::nullopt)
|
||||
{
|
||||
std::cout << "PB::Renderer::VulkanManager::PickPhysicalDevice(): No Vulkan instance or surface" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const VkInstance& instance = s_Instance.value();
|
||||
const VkSurfaceKHR& surface = s_Surface.value();
|
||||
|
||||
uint32_t deviceCount = 0;
|
||||
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
||||
if (deviceCount == 0)
|
||||
{
|
||||
std::cout << "PB::Renderer::VulkanManager::PickPhysicalDevice(): No GPU with Vulkan support" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<VkPhysicalDevice> devices(deviceCount);
|
||||
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
|
||||
|
||||
for (const auto& device : devices)
|
||||
{
|
||||
if (IsDeviceSuitable(device, surface))
|
||||
{
|
||||
s_PhysicalDevice = device;
|
||||
s_QueueIndices = FindQueueFamilies(device, surface);
|
||||
|
||||
VkPhysicalDeviceProperties deviceProperties;
|
||||
vkGetPhysicalDeviceProperties(device, &deviceProperties);
|
||||
|
||||
std::cout << "Selected GPU: "<< deviceProperties.deviceName << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Failed to find a suitable GPU" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VulkanManager::IsDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface)
|
||||
{
|
||||
const QueueFamilyIndices indices = FindQueueFamilies(device, surface);
|
||||
|
||||
if (const bool extensionsSupported = CheckDeviceExtensionSupport(device); !extensionsSupported)
|
||||
return false;
|
||||
|
||||
VkSurfaceCapabilitiesKHR capabilities;
|
||||
uint32_t formatCount, presentCount;
|
||||
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &capabilities);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentCount, nullptr);
|
||||
const bool swapChainAdequate = formatCount > 0 && presentCount > 0;
|
||||
|
||||
VkPhysicalDeviceProperties deviceProperties;
|
||||
vkGetPhysicalDeviceProperties(device, &deviceProperties);
|
||||
|
||||
const bool discreteGPU = deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
|
||||
return indices.Complete() && swapChainAdequate && discreteGPU;
|
||||
}
|
||||
|
||||
QueueFamilyIndices VulkanManager::FindQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface)
|
||||
{
|
||||
QueueFamilyIndices indices;
|
||||
|
||||
uint32_t queueFamilyCount;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
|
||||
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
|
||||
|
||||
int index = -1;
|
||||
for (const auto& family : queueFamilies)
|
||||
{
|
||||
if (family.queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
{
|
||||
indices.graphicsFamily = index;
|
||||
}
|
||||
|
||||
VkBool32 presentSupport = false;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(device, index, surface, &presentSupport);
|
||||
if (presentSupport)
|
||||
{
|
||||
indices.presentFamily = index;
|
||||
}
|
||||
|
||||
if (indices.Complete())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
bool VulkanManager::CheckDeviceExtensionSupport(VkPhysicalDevice device)
|
||||
{
|
||||
const std::vector<const char*> REQUIRED_EXTENSIONS = {
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
uint32_t extensionCount;
|
||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
|
||||
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
|
||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
|
||||
|
||||
std::set<std::string> required(REQUIRED_EXTENSIONS.begin(), REQUIRED_EXTENSIONS.end());
|
||||
for (const auto& [extensionName, specVersion] : availableExtensions)
|
||||
{
|
||||
required.erase(extensionName);
|
||||
}
|
||||
|
||||
return required.empty();
|
||||
|
||||
}
|
||||
|
||||
bool VulkanManager::Cleanup()
|
||||
{
|
||||
if (s_Surface != std::nullopt)
|
||||
|
||||
@@ -4,16 +4,35 @@
|
||||
|
||||
namespace PB::Renderer
|
||||
{
|
||||
struct QueueFamilyIndices
|
||||
{
|
||||
std::optional<uint32_t> graphicsFamily = std::nullopt;
|
||||
std::optional<uint32_t> presentFamily = std::nullopt;
|
||||
|
||||
[[nodiscard]] bool Complete() const
|
||||
{
|
||||
return graphicsFamily && presentFamily;
|
||||
}
|
||||
};
|
||||
|
||||
class VulkanManager
|
||||
{
|
||||
private:
|
||||
static std::optional<VkInstance> s_Instance;
|
||||
static std::optional<VkSurfaceKHR> s_Surface;
|
||||
|
||||
public:
|
||||
static std::optional<VkInstance> Init();
|
||||
static bool Cleanup();
|
||||
|
||||
static std::optional<VkSurfaceKHR> CreateSurface(GLFWwindow* window);
|
||||
static bool PickPhysicalDevice();
|
||||
|
||||
private:
|
||||
static bool IsDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface);
|
||||
static QueueFamilyIndices FindQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface);
|
||||
static bool CheckDeviceExtensionSupport(VkPhysicalDevice device);
|
||||
|
||||
static std::optional<VkInstance> s_Instance;
|
||||
static std::optional<VkSurfaceKHR> s_Surface;
|
||||
|
||||
static VkPhysicalDevice s_PhysicalDevice;
|
||||
static QueueFamilyIndices s_QueueIndices;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user