physical devices queue families yeah

This commit is contained in:
Mars 2024-09-30 00:31:08 -04:00
parent d489322ab2
commit a4c78acebf
Signed by untrusted user: pupbrained
GPG key ID: 874E22DF2F9DFCB5

View file

@ -11,6 +11,10 @@
#include "fmt/base.h" #include "fmt/base.h"
#include "util/types.h" #include "util/types.h"
namespace vk {
using DebugUtilsMessengerUnique = vk::UniqueHandle<vk::DebugUtilsMessengerEXT, vk::DispatchLoaderDynamic>;
}
constexpr int WIDTH = 800; constexpr int WIDTH = 800;
constexpr int HEIGHT = 600; constexpr int HEIGHT = 600;
@ -36,9 +40,17 @@ class VulkanApp {
vk::UniqueInstance mInstance; vk::UniqueInstance mInstance;
vk::UniqueHandle<vk::DebugUtilsMessengerEXT, vk::DispatchLoaderDynamic> mDebugMessenger; vk::DebugUtilsMessengerUnique mDebugMessenger;
vk::DispatchLoaderDynamic mLoader; vk::DispatchLoaderDynamic mLoader;
vk::PhysicalDevice mPhysicalDevice;
struct QueueFamilyIndices {
std::optional<u32> graphics_family;
fn isComplete() -> bool { return graphics_family.has_value(); }
};
void initWindow() { void initWindow() {
glfwInit(); glfwInit();
@ -51,6 +63,55 @@ class VulkanApp {
void initVulkan() { void initVulkan() {
createInstance(); createInstance();
setupDebugMessenger(); setupDebugMessenger();
pickPhysicalDevice();
}
void mainLoop() {
while (!glfwWindowShouldClose(mWindow)) { glfwPollEvents(); }
}
void cleanup() {
glfwDestroyWindow(mWindow);
glfwTerminate();
}
fn createInstance() -> void {
if (enableValidationLayers && !checkValidationLayerSupport())
throw std::runtime_error("validation layers requested, but not available!");
vk::ApplicationInfo appInfo { .pApplicationName = "Hello Triangle",
.applicationVersion = 1,
.pEngineName = "No Engine",
.engineVersion = 1,
.apiVersion = VK_API_VERSION_1_0 };
// Retrieve extensions using custom function
std::vector<const char*> extensions = getRequiredExtensions();
// Enable the portability extension and set flags
extensions.push_back("VK_KHR_portability_enumeration");
vk::InstanceCreateInfo createInfo {
.flags = vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR,
.pApplicationInfo = &appInfo,
.enabledLayerCount = enableValidationLayers ? static_cast<uint32_t>(validationLayers.size()) : 0,
.ppEnabledLayerNames = enableValidationLayers ? validationLayers.data() : nullptr,
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
.ppEnabledExtensionNames = extensions.data()
};
#ifndef NDEBUG
fmt::println("Available extensions:");
for (const char* extension : extensions) fmt::println("\t{}", extension);
#endif
try {
mInstance = vk::createInstanceUnique(createInfo);
mLoader = vk::DispatchLoaderDynamic(mInstance.get(), vkGetInstanceProcAddr);
} catch (const vk::SystemError& err) {
throw std::runtime_error("Failed to create instance: " + std::string(err.what()));
}
} }
void setupDebugMessenger() { void setupDebugMessenger() {
@ -70,53 +131,70 @@ class VulkanApp {
mDebugMessenger = mInstance->createDebugUtilsMessengerEXTUnique(messengerCreateInfo, nullptr, mLoader); mDebugMessenger = mInstance->createDebugUtilsMessengerEXTUnique(messengerCreateInfo, nullptr, mLoader);
} }
void mainLoop() { fn pickPhysicalDevice() -> void {
while (!glfwWindowShouldClose(mWindow)) { glfwPollEvents(); } std::vector<vk::PhysicalDevice> devices = mInstance->enumeratePhysicalDevices();
if (devices.empty())
throw std::runtime_error("Failed to find GPUs with Vulkan support!");
#ifndef NDEBUG
fmt::println("Available devices:");
#endif
for (const auto& device : devices) {
#ifndef NDEBUG
vk::PhysicalDeviceProperties properties = device.getProperties();
fmt::println("Device: {}", properties.deviceName.data());
#endif
if (isDeviceSuitable(device)) {
mPhysicalDevice = device;
break;
}
} }
void cleanup() { if (!mPhysicalDevice)
// NOTE: instance destruction is handled by UniqueInstance throw std::runtime_error("Failed to find a suitable GPU!");
glfwDestroyWindow(mWindow);
glfwTerminate();
} }
fn createInstance() -> void { static fn isDeviceSuitable(vk::PhysicalDevice device) -> bool {
if (enableValidationLayers && !checkValidationLayerSupport()) QueueFamilyIndices indices = findQueueFamilies(device);
throw std::runtime_error("validation layers requested, but not available!");
vk::ApplicationInfo appInfo { .pApplicationName = "Hello Triangle", return indices.isComplete();
.applicationVersion = 1,
.pEngineName = "No Engine",
.engineVersion = 1,
.apiVersion = VK_API_VERSION_1_0 };
// Retrieve extensions using custom function
std::vector<const char*> extensions = getRequiredExtensions();
vk::InstanceCreateInfo createInfo {
.pApplicationInfo = &appInfo,
.enabledLayerCount = enableValidationLayers ? static_cast<uint32_t>(validationLayers.size()) : 0,
.ppEnabledLayerNames = enableValidationLayers ? validationLayers.data() : nullptr
};
// Enable the portability extension and set flags
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
createInfo.setEnabledExtensionCount(static_cast<uint32_t>(extensions.size()))
.setPpEnabledExtensionNames(extensions.data())
.setFlags(vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR);
fmt::println("Available extensions:");
for (const char* extension : extensions) fmt::println("\t{}", extension);
try {
mInstance = vk::createInstanceUnique(createInfo);
mLoader = vk::DispatchLoaderDynamic(mInstance.get(), vkGetInstanceProcAddr);
} catch (const vk::SystemError& err) {
throw std::runtime_error("Failed to create instance: " + std::string(err.what()));
} }
static fn findQueueFamilies(vk::PhysicalDevice device) -> QueueFamilyIndices {
QueueFamilyIndices indices;
std::vector<vk::QueueFamilyProperties> queueFamilies = device.getQueueFamilyProperties();
for (u32 i = 0; i < queueFamilies.size(); i++) {
if (queueFamilies[i].queueFlags & vk::QueueFlagBits::eGraphics)
indices.graphics_family = i;
if (indices.isComplete())
break;
}
return indices;
}
static fn getRequiredExtensions() -> std::vector<const char*> {
u32 glfwExtensionCount = 0;
const char** glfwExtensions = nullptr;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
std::vector<const char*> extensions;
if (glfwExtensions) {
std::span<const char*> extSpan(glfwExtensions, glfwExtensionCount);
extensions.assign(extSpan.begin(), extSpan.end());
}
if (enableValidationLayers)
extensions.push_back("VK_EXT_debug_utils");
return extensions;
} }
static fn checkValidationLayerSupport() -> bool { static fn checkValidationLayerSupport() -> bool {
@ -138,24 +216,6 @@ class VulkanApp {
return true; return true;
} }
static fn getRequiredExtensions() -> std::vector<const char*> {
u32 glfwExtensionCount = 0;
const char** glfwExtensions = nullptr;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
std::vector<const char*> extensions;
if (glfwExtensions) {
std::span<const char*> extSpan(glfwExtensions, glfwExtensionCount);
extensions.assign(extSpan.begin(), extSpan.end());
}
if (enableValidationLayers)
extensions.push_back("VK_EXT_debug_utils");
return extensions;
}
static VKAPI_ATTR fn VKAPI_CALL debugCallback( static VKAPI_ATTR fn VKAPI_CALL debugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT /*messageSeverity*/, VkDebugUtilsMessageSeverityFlagBitsEXT /*messageSeverity*/,
VkDebugUtilsMessageTypeFlagsEXT /*messageType*/, VkDebugUtilsMessageTypeFlagsEXT /*messageType*/,