physical devices queue families yeah
This commit is contained in:
parent
d489322ab2
commit
a4c78acebf
180
src/main.cpp
180
src/main.cpp
|
@ -11,6 +11,10 @@
|
|||
#include "fmt/base.h"
|
||||
#include "util/types.h"
|
||||
|
||||
namespace vk {
|
||||
using DebugUtilsMessengerUnique = vk::UniqueHandle<vk::DebugUtilsMessengerEXT, vk::DispatchLoaderDynamic>;
|
||||
}
|
||||
|
||||
constexpr int WIDTH = 800;
|
||||
constexpr int HEIGHT = 600;
|
||||
|
||||
|
@ -36,9 +40,17 @@ class VulkanApp {
|
|||
|
||||
vk::UniqueInstance mInstance;
|
||||
|
||||
vk::UniqueHandle<vk::DebugUtilsMessengerEXT, vk::DispatchLoaderDynamic> mDebugMessenger;
|
||||
vk::DebugUtilsMessengerUnique mDebugMessenger;
|
||||
vk::DispatchLoaderDynamic mLoader;
|
||||
|
||||
vk::PhysicalDevice mPhysicalDevice;
|
||||
|
||||
struct QueueFamilyIndices {
|
||||
std::optional<u32> graphics_family;
|
||||
|
||||
fn isComplete() -> bool { return graphics_family.has_value(); }
|
||||
};
|
||||
|
||||
void initWindow() {
|
||||
glfwInit();
|
||||
|
||||
|
@ -51,6 +63,55 @@ class VulkanApp {
|
|||
void initVulkan() {
|
||||
createInstance();
|
||||
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() {
|
||||
|
@ -70,53 +131,70 @@ class VulkanApp {
|
|||
mDebugMessenger = mInstance->createDebugUtilsMessengerEXTUnique(messengerCreateInfo, nullptr, mLoader);
|
||||
}
|
||||
|
||||
void mainLoop() {
|
||||
while (!glfwWindowShouldClose(mWindow)) { glfwPollEvents(); }
|
||||
fn pickPhysicalDevice() -> void {
|
||||
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() {
|
||||
// NOTE: instance destruction is handled by UniqueInstance
|
||||
|
||||
glfwDestroyWindow(mWindow);
|
||||
|
||||
glfwTerminate();
|
||||
if (!mPhysicalDevice)
|
||||
throw std::runtime_error("Failed to find a suitable GPU!");
|
||||
}
|
||||
|
||||
fn createInstance() -> void {
|
||||
if (enableValidationLayers && !checkValidationLayerSupport())
|
||||
throw std::runtime_error("validation layers requested, but not available!");
|
||||
static fn isDeviceSuitable(vk::PhysicalDevice device) -> bool {
|
||||
QueueFamilyIndices indices = findQueueFamilies(device);
|
||||
|
||||
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();
|
||||
|
||||
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()));
|
||||
return indices.isComplete();
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -138,24 +216,6 @@ class VulkanApp {
|
|||
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(
|
||||
VkDebugUtilsMessageSeverityFlagBitsEXT /*messageSeverity*/,
|
||||
VkDebugUtilsMessageTypeFlagsEXT /*messageType*/,
|
||||
|
|
Loading…
Reference in a new issue