aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvimene <vincent.menegaux@gmail.com>2025-06-26 01:12:08 +0200
committervimene <vincent.menegaux@gmail.com>2025-06-26 01:12:08 +0200
commit625d18a6053e28762c77efd3dd0d79fc01b0b0ef (patch)
treebd7bd31a40b9d8061c32c9953d78412e2cf90a48
parentfc8e5fc191822c244f51335e49d44f5a047b128e (diff)
downloadengine-625d18a6053e28762c77efd3dd0d79fc01b0b0ef.tar.gz
added validation layers to vulkanvulkan
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am8
-rw-r--r--configure.ac9
-rw-r--r--src/engine.cpp128
4 files changed, 137 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore
index 4414992..0e5e946 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,4 @@ Makefile.in
# vim
.*.swp
+*~
diff --git a/Makefile.am b/Makefile.am
index 60712f6..0a27d41 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,6 +5,14 @@ if ENABLE_TESTS
endif
ACLOCAL_AMFLAGS = -Im4 --install
+CXXFLAGS =
+if DEBUG
+CXXFLAGS += -ggdb
+else
+CXXFLAGS += -DNDEBUG
+endif
+CXXFLAGS += -O2
+
bin_PROGRAMS = engine
engine_SOURCES = \
diff --git a/configure.ac b/configure.ac
index 5d252bc..ebdbcad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,15 @@ PKG_CHECK_MODULES([CRITERION], [criterion >= 2.4.1], [
], [enable_tests=no])
AM_CONDITIONAL([ENABLE_TESTS], [test x$enable_tests = xyes])
+AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [enable debugging, default: no]),
+ [case "${enableval}" in
+ yes) debug=true ;;
+ no) debug=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
+ esac],
+ [debug=false])
+AM_CONDITIONAL([DEBUG], test x"$debug" = x"true")
+
AC_SUBST(TESTS_DEPS_CPPFLAGS)
AC_SUBST(TESTS_DEPS_LIBS)
diff --git a/src/engine.cpp b/src/engine.cpp
index d276d70..da28f75 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -292,6 +292,63 @@ static int main_term() {
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
+const std::vector<const char*> validation_layers = {
+ "VK_LAYER_KHRONOS_validation"
+};
+
+#ifdef NDEBUG
+const bool enable_validation_layers = false;
+#else
+const bool enable_validation_layers = true;
+#endif
+
+static bool check_validation_layer_support() {
+ uint32_t layer_count;
+ vkEnumerateInstanceLayerProperties(&layer_count, nullptr);
+
+ std::vector<VkLayerProperties> available_layers(layer_count);
+ vkEnumerateInstanceLayerProperties(&layer_count, available_layers.data());
+
+ for (const char* layer_name : validation_layers) {
+ bool layer_found = false;
+
+ for (const auto& layer_properties : available_layers) {
+ if (strcmp(layer_name, layer_properties.layerName) == 0) {
+ layer_found = true;
+ break;
+ }
+ }
+
+ if (!layer_found) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
+ VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
+ VkDebugUtilsMessageTypeFlagsEXT message_type,
+ const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
+ void* user_data) {
+ std::cerr << "validation layer: " << callback_data->pMessage << std::endl;
+ return VK_FALSE;
+}
+
+static void populate_msger_create_info(VkDebugUtilsMessengerCreateInfoEXT& msger_create_info) {
+ msger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+ msger_create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ msger_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ msger_create_info.pfnUserCallback = debug_callback;
+ msger_create_info.pUserData = nullptr;
+}
+
static int main_graphical() {
// init window
glfwInit();
@@ -301,6 +358,11 @@ static int main_graphical() {
// init Vulkan
// init Vulkan - create instance
+ if (enable_validation_layers && !check_validation_layer_support()) {
+ std::cerr << "validation layers requested, but not available!" << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+
VkApplicationInfo app_info{};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = "engine - test";
@@ -309,26 +371,52 @@ static int main_graphical() {
app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
app_info.apiVersion = VK_API_VERSION_1_0;
- uint32_t glfw_extension_count;
- const char** glfw_extensions;
- glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count);
+ std::vector<const char*> extensions;
+
+ {
+ uint32_t glfw_extension_count;
+ const char** glfw_extensions;
+ glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count);
+ extensions.insert(extensions.end(), glfw_extensions, glfw_extensions + glfw_extension_count);
+ }
+
+ if (enable_validation_layers) {
+ extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ }
uint32_t extension_count;
vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr);
- std::vector<VkExtensionProperties> extensions(extension_count);
- vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data());
+ std::vector<VkExtensionProperties> available_extensions(extension_count);
+ vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, available_extensions.data());
std::cout << "vulkan extensions:\n";
- for (const auto& extension : extensions)
+ for (const auto& extension : available_extensions)
std::cout << " " << extension.extensionName << "\n";
+ std::cout << "\n";
+
+ std::cout << "required extensions:\n";
+ for (const auto& extension_name : extensions)
+ std::cout << " " << extension_name << "\n";
+
VkInstanceCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.pApplicationInfo = &app_info;
- create_info.enabledExtensionCount = glfw_extension_count;
- create_info.ppEnabledExtensionNames = glfw_extensions;
- create_info.enabledLayerCount = 0;
+ create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
+ create_info.ppEnabledExtensionNames = extensions.data();
+
+ VkDebugUtilsMessengerCreateInfoEXT inst_msger_create_info{};
+ if (enable_validation_layers) {
+ create_info.enabledLayerCount = static_cast<uint32_t>(validation_layers.size());
+ create_info.ppEnabledLayerNames = validation_layers.data();
+
+ populate_msger_create_info(inst_msger_create_info);
+ create_info.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &inst_msger_create_info;
+ } else {
+ create_info.enabledLayerCount = 0;
+ create_info.pNext = nullptr;
+ }
VkInstance instance;
if (VkResult res = vkCreateInstance(&create_info, nullptr, &instance); res != VK_SUCCESS) {
@@ -336,12 +424,34 @@ static int main_graphical() {
std::exit(EXIT_FAILURE);
}
+ VkDebugUtilsMessengerEXT debug_messenger;
+ if (enable_validation_layers) {
+ VkDebugUtilsMessengerCreateInfoEXT msger_create_info{};
+ populate_msger_create_info(msger_create_info);
+
+ auto create_debug_messenger = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
+ if (!create_debug_messenger) {
+ std::cerr << "failed to set up debug messenger!" << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ create_debug_messenger(instance, &msger_create_info, nullptr, &debug_messenger);
+ }
+
// main loop
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
// cleanup
+ if (enable_validation_layers) {
+ auto destroy_debug_messenger = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
+ if (!destroy_debug_messenger) {
+ std::cerr << "failed to destroy debug messenger!" << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ destroy_debug_messenger(instance, debug_messenger, nullptr);
+ }
+
vkDestroyInstance(instance, nullptr);
glfwDestroyWindow(window);
glfwTerminate();