Added pick device support
This commit is contained in:
21
main.cpp
21
main.cpp
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace PB::Renderer
|
namespace PB::Renderer
|
||||||
{
|
{
|
||||||
void CleanupAllAndExit()
|
void CleanupAllAndExit(int code)
|
||||||
{
|
{
|
||||||
if (!GLFWManager::Cleanup())
|
if (!GLFWManager::Cleanup())
|
||||||
std::exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
@@ -13,7 +13,7 @@ namespace PB::Renderer
|
|||||||
if (VulkanManager::Cleanup())
|
if (VulkanManager::Cleanup())
|
||||||
std::exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
|
|
||||||
std::exit(EXIT_SUCCESS);
|
std::exit(code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,17 +29,20 @@ int main()
|
|||||||
if (!window)
|
if (!window)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Creates the Vulkan instance and surface */
|
/* Runs Vulkan initialisation functions */
|
||||||
if (std::optional<VkInstance> instance = VulkanManager::Init(); !instance)
|
if (const std::optional<VkInstance> instance = VulkanManager::Init(); !instance)
|
||||||
{
|
{
|
||||||
GLFWManager::Cleanup();
|
GLFWManager::Cleanup();
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::optional<VkSurfaceKHR> surface = VulkanManager::CreateSurface(window); !surface)
|
if (const std::optional<VkSurfaceKHR> surface = VulkanManager::CreateSurface(window); !surface)
|
||||||
{
|
{
|
||||||
CleanupAllAndExit();
|
CleanupAllAndExit(EXIT_FAILURE);
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
|
if (!VulkanManager::PickPhysicalDevice())
|
||||||
|
{
|
||||||
|
CleanupAllAndExit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Polls window events whilst it is still open */
|
/* Polls window events whilst it is still open */
|
||||||
@@ -49,5 +52,5 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up GLFW and Vulkan */
|
/* Cleans up GLFW and Vulkan */
|
||||||
CleanupAllAndExit();
|
CleanupAllAndExit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,3 +12,4 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ namespace PB::Renderer
|
|||||||
std::optional<VkInstance> VulkanManager::s_Instance = std::nullopt;
|
std::optional<VkInstance> VulkanManager::s_Instance = std::nullopt;
|
||||||
std::optional<VkSurfaceKHR> VulkanManager::s_Surface = 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()
|
std::optional<VkInstance> VulkanManager::Init()
|
||||||
{
|
{
|
||||||
/* Stops multi initialisation */
|
/* Stops multi initialisation */
|
||||||
@@ -47,6 +50,12 @@ namespace PB::Renderer
|
|||||||
|
|
||||||
std::optional<VkSurfaceKHR> VulkanManager::CreateSurface(GLFWwindow* window)
|
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;
|
VkSurfaceKHR surface;
|
||||||
if (glfwCreateWindowSurface(s_Instance.value(), window, nullptr, &surface) != VK_SUCCESS)
|
if (glfwCreateWindowSurface(s_Instance.value(), window, nullptr, &surface) != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -54,9 +63,130 @@ namespace PB::Renderer
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_Surface = surface;
|
||||||
return 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()
|
bool VulkanManager::Cleanup()
|
||||||
{
|
{
|
||||||
if (s_Surface != std::nullopt)
|
if (s_Surface != std::nullopt)
|
||||||
|
|||||||
@@ -4,16 +4,35 @@
|
|||||||
|
|
||||||
namespace PB::Renderer
|
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
|
class VulkanManager
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
static std::optional<VkInstance> s_Instance;
|
|
||||||
static std::optional<VkSurfaceKHR> s_Surface;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::optional<VkInstance> Init();
|
static std::optional<VkInstance> Init();
|
||||||
static bool Cleanup();
|
static bool Cleanup();
|
||||||
|
|
||||||
static std::optional<VkSurfaceKHR> CreateSurface(GLFWwindow* window);
|
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