aboutsummaryrefslogtreecommitdiff
path: root/src/engine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine.cpp')
-rw-r--r--src/engine.cpp133
1 files changed, 119 insertions, 14 deletions
diff --git a/src/engine.cpp b/src/engine.cpp
index 0e29d60..f548e75 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -294,7 +294,7 @@ static int main_term() {
#define SCREEN_HEIGHT 480
static const std::vector<const char*> validation_layers = {
- "VK_LAYER_KHRONOS_validation"
+ "VK_LAYER_KHRONOS_validation",
};
static const std::vector<const char*> device_exts = {
@@ -335,13 +335,47 @@ static bool check_validation_layer_support() {
return true;
}
+static std::string severity_to_str(VkDebugUtilsMessageSeverityFlagBitsEXT severity) {
+ std::string s;
+ bool first = true;
+ if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
+ if (!first)
+ s += ", ";
+ else
+ first = false;
+ s += "VERBOSE";
+ }
+ if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
+ if (!first)
+ s += ", ";
+ else
+ first = false;
+ s += "INFO";
+ }
+ if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
+ if (!first)
+ s += ", ";
+ else
+ first = false;
+ s += "WARNING";
+ }
+ if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
+ if (!first)
+ s += ", ";
+ else
+ first = false;
+ s += "ERROR";
+ }
+ return s;
+}
+
// TODO: remove [[maybe_unused]]
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
- [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
+ VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
[[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT message_type,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
[[maybe_unused]] void* user_data) {
- std::cerr << "validation layer: " << callback_data->pMessage << std::endl;
+ std::cerr << "validation layer: [" << severity_to_str(message_severity) << "] " << callback_data->pMessage << std::endl;
return VK_FALSE;
}
@@ -358,6 +392,13 @@ static void populate_msger_create_info(VkDebugUtilsMessengerCreateInfoEXT& msger
msger_create_info.pUserData = nullptr;
}
+static uint32_t find_queue_family_index(const std::vector<VkQueueFamilyProperties2>& queue_family_properties) {
+ auto it = std::ranges::find_if(queue_family_properties, [](const auto& prop) {
+ return (prop.queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) != static_cast<VkQueueFlags>(0);
+ });
+ return static_cast<uint32_t>(std::distance(queue_family_properties.begin(), it));
+}
+
static int main_graphical() {
// init window
glfwInit();
@@ -366,6 +407,12 @@ static int main_graphical() {
GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Engine", nullptr, nullptr);
// init Vulkan
+ std::cout << "Vulkan loader version: "
+ << VK_API_VERSION_MAJOR(VK_HEADER_VERSION_COMPLETE)
+ << "." << VK_API_VERSION_MINOR(VK_HEADER_VERSION_COMPLETE)
+ << "." << VK_API_VERSION_PATCH(VK_HEADER_VERSION_COMPLETE)
+ << std::endl;
+
// init Vulkan - create instance
if (enable_validation_layers && !check_validation_layer_support()) {
std::cerr << "validation layers requested, but not available!" << std::endl;
@@ -399,14 +446,18 @@ static int main_graphical() {
vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, available_extensions.data());
std::cout << "vulkan extensions:\n";
- for (const auto& extension : available_extensions)
- std::cout << " " << extension.extensionName << "\n";
+ for (const auto& extension : available_extensions) {
+ std::cout
+ << (std::ranges::find_if(extensions, [avail_ext_name=extension.extensionName](const auto& ext_name) { return strcmp(ext_name, avail_ext_name) == 0; })
+ != extensions.end() ? "*" : " ");
+ std::cout << " " << extension.extensionName << "\n";
+ }
std::cout << "\n";
std::cout << "required extensions:\n";
for (const auto& extension_name : extensions)
- std::cout << " " << extension_name << "\n";
+ std::cout << " " << extension_name << "\n";
VkInstanceCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@@ -468,17 +519,19 @@ static int main_graphical() {
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
vkGetPhysicalDeviceFeatures2(physical_device, &features);
- uint32_t queue_family_properties_count;
- vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_properties_count, nullptr);
- std::vector<VkQueueFamilyProperties2> queue_family_properties(queue_family_properties_count);
- vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_properties_count, queue_family_properties.data());
-
// TODO: found a better name, too confusing with device_exts
uint32_t ext_props_count;
vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &ext_props_count, nullptr);
std::vector<VkExtensionProperties> ext_props(ext_props_count);
vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &ext_props_count, ext_props.data());
+ uint32_t queue_family_properties_count;
+ vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_properties_count, nullptr);
+ std::vector<VkQueueFamilyProperties2> queue_family_properties(queue_family_properties_count);
+ for (auto& elt : queue_family_properties)
+ elt.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
+ vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_properties_count, queue_family_properties.data());
+
std::cout << "structure type: " << string_VkStructureType(properties.sType) << std::endl;
std::cout << "pNext: " << properties.pNext << std::endl;
std::cout << "apiVersion: (variant " << VK_API_VERSION_VARIANT(properties.properties.apiVersion) << ") "
@@ -572,9 +625,7 @@ static int main_graphical() {
if (VK_API_VERSION_VARIANT(properties.properties.apiVersion) != 0
|| properties.properties.apiVersion < VK_API_VERSION_1_4)
return false;
- if (std::ranges::find_if(queue_family_properties, [](const auto& prop) {
- return (prop.queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) != static_cast<VkQueueFlags>(0);
- }) == queue_family_properties.end())
+ if (find_queue_family_index(queue_family_properties) == queue_family_properties.size())
return false;
if (std::ranges::find_if_not(device_exts, [&ext_props](const auto& device_ext) {
return std::ranges::find_if(ext_props,
@@ -598,12 +649,66 @@ static int main_graphical() {
std::exit(EXIT_FAILURE);
}
+ // TODO: shouldn't fetch twice (already fetched while selecting physical device)
+ uint32_t queue_family_index = [device]() {
+ uint32_t queue_family_properties_count;
+ vkGetPhysicalDeviceQueueFamilyProperties2(device, &queue_family_properties_count, nullptr);
+ std::vector<VkQueueFamilyProperties2> queue_family_properties(queue_family_properties_count);
+ for (auto& elt : queue_family_properties)
+ elt.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
+ vkGetPhysicalDeviceQueueFamilyProperties2(device, &queue_family_properties_count, queue_family_properties.data());
+
+ // don't need to check if it's found, we already checked that in device seleciton
+ return find_queue_family_index(queue_family_properties);
+ }();
+
+ float queue_priority = .5f;
+ VkDeviceQueueCreateInfo deviceQueueCreateInfo{};
+ deviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ deviceQueueCreateInfo.queueFamilyIndex = queue_family_index;
+ deviceQueueCreateInfo.queueCount = 1;
+ deviceQueueCreateInfo.pQueuePriorities = &queue_priority;
+
+ VkDeviceCreateInfo device_create_info{};
+ device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ device_create_info.queueCreateInfoCount = 1;
+ device_create_info.pQueueCreateInfos = &deviceQueueCreateInfo;
+ device_create_info.enabledExtensionCount = static_cast<uint32_t>(device_exts.size());
+ device_create_info.ppEnabledExtensionNames = device_exts.data();
+
+ // set everything to false
+ VkPhysicalDeviceFeatures2 device_features{};
+ device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ device_create_info.pNext = &device_features;
+
+ VkPhysicalDeviceVulkan13Features device_vk13_features{};
+ device_vk13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
+ device_vk13_features.dynamicRendering = VK_TRUE;
+ device_features.pNext = &device_vk13_features;
+
+ VkPhysicalDeviceExtendedDynamicStateFeaturesEXT device_eds_features{};
+ device_eds_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
+ device_eds_features.extendedDynamicState = VK_TRUE;
+ device_vk13_features.pNext = &device_eds_features;
+
+ // TODO: rename to just "device", and rename "device" to "physical_device"
+ VkDevice logical_device;
+ if (VkResult res = vkCreateDevice(device, &device_create_info, nullptr, &logical_device); res != VK_SUCCESS) {
+ std::cerr << "failed to create device: " << string_VkResult(res) << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+
+ VkQueue graphics_queue;
+ vkGetDeviceQueue(logical_device, queue_family_index, 0, &graphics_queue);
+
// main loop
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
// cleanup
+ vkDestroyDevice(logical_device, nullptr);
+
if (enable_validation_layers) {
auto destroy_debug_messenger = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
if (!destroy_debug_messenger) {