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 "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*/,
|
||||||
|
|
Loading…
Reference in a new issue