add validation layers + debug callback
This commit is contained in:
10
README.md
10
README.md
@@ -74,6 +74,16 @@ $ gcovr -r .. --filter "../src"
|
|||||||
Basically these are some tricky situations that I encountered when trying to execute this app throughout this development phase. If you are running on WSL Ubuntu 26.04 like me, then you mightr run into these too, hopefully my steps help fix.
|
Basically these are some tricky situations that I encountered when trying to execute this app throughout this development phase. If you are running on WSL Ubuntu 26.04 like me, then you mightr run into these too, hopefully my steps help fix.
|
||||||
note: I am running an x86_64 system with an Nvidia GPU so some things may be slightly different if your system doesn't match.
|
note: I am running an x86_64 system with an Nvidia GPU so some things may be slightly different if your system doesn't match.
|
||||||
|
|
||||||
|
### [WARN: COPY MODE]
|
||||||
|
This seems like a WSL specific error and causes real issues with relaying graphics from linux to windows. I fixed this by installing new mesa drivers as reccommended by https://github.com/microsoft/wslg/discussions/312:
|
||||||
|
```bash
|
||||||
|
$ sudo add-apt-repository ppa:kisak/kisak-mesa
|
||||||
|
$ sudo apt-get update && sudo apt upgrade
|
||||||
|
```
|
||||||
|
Note: this resulted in the following erre "WARNING: dzn is not a conformant Vulkan implementation, testing use only." Running `$ vkcube` showed that this indeed was just a warning.
|
||||||
|
|
||||||
|
(for those curious, dzn is a compaitibility layer between DirectX12 and Vulkan for that WSL conformity)
|
||||||
|
|
||||||
|
|
||||||
## Development Roadmap
|
## Development Roadmap
|
||||||
### lots of todo here
|
### lots of todo here
|
||||||
|
|||||||
@@ -45,9 +45,7 @@ bool Engine::createInstance() {
|
|||||||
.apiVersion = VK_API_VERSION_1_4 // this one is most important
|
.apiVersion = VK_API_VERSION_1_4 // this one is most important
|
||||||
};
|
};
|
||||||
|
|
||||||
// get extensions that our windowing library requires
|
std::vector<const char*> requiredInstanceExtensions = getRequiredInstanceExtensions();
|
||||||
uint32_t instanceExtensionsCount = 0;
|
|
||||||
char const* const* instanceExtensions{ SDL_Vulkan_GetInstanceExtensions(&instanceExtensionsCount) };
|
|
||||||
|
|
||||||
// get all available extensions
|
// get all available extensions
|
||||||
auto extensionProperties = context_.enumerateInstanceExtensionProperties();
|
auto extensionProperties = context_.enumerateInstanceExtensionProperties();
|
||||||
@@ -56,23 +54,23 @@ bool Engine::createInstance() {
|
|||||||
std::cout << "Available Vulkan Extensions: " << std::endl;
|
std::cout << "Available Vulkan Extensions: " << std::endl;
|
||||||
for(const auto& extensionProperty : extensionProperties) {
|
for(const auto& extensionProperty : extensionProperties) {
|
||||||
std::cout << "\t" << extensionProperty.extensionName << std::endl;
|
std::cout << "\t" << extensionProperty.extensionName << std::endl;
|
||||||
}
|
} // this would be a logger.debug(...)
|
||||||
|
|
||||||
// check that all required extensions are available
|
// check that all required extensions are available
|
||||||
for(uint32_t i = 0; i < instanceExtensionsCount; i++) { // for each extension that we require
|
for(uint32_t i = 0; i < requiredInstanceExtensions.size(); i++) { // for each extension that we require
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for(const auto& extensionProperty : extensionProperties) { // see if it matches any extensions that are provided
|
for(const auto& extensionProperty : extensionProperties) { // see if it matches any extensions that are provided
|
||||||
if(strcmp(extensionProperty.extensionName, instanceExtensions[i]) == 0) {
|
if(strcmp(extensionProperty.extensionName, requiredInstanceExtensions[i]) == 0) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!found) {
|
if(!found) {
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Required SDL3 extension not supported: " << instanceExtensions[i] << std::endl;
|
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Required SDL3 extension not supported: " << requiredInstanceExtensions[i] << std::endl;
|
||||||
errorCount++;
|
errorCount++;
|
||||||
} else {
|
} else {
|
||||||
// in case you're curious
|
// in case you're curious
|
||||||
//std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] SDL3 extension located: " << instanceExtensions[i] << std::endl;
|
//std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] SDL3 extension located: " << requiredInstanceExtensions[i] << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,15 +105,78 @@ bool Engine::createInstance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if any we had errors then we must exit
|
// if any we had errors then we must exit
|
||||||
if(errorCount != 0) return false;
|
if(errorCount != 0) {
|
||||||
|
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Unable to create Vulkan instance. Error count: " << errorCount << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
vk::InstanceCreateInfo instanceCreateInfo {
|
vk::InstanceCreateInfo instanceCreateInfo {
|
||||||
.pApplicationInfo = &appInfo,
|
.pApplicationInfo = &appInfo,
|
||||||
.enabledExtensionCount = instanceExtensionsCount,
|
.enabledLayerCount = static_cast<uint32_t>(requiredValidationLayers.size()),
|
||||||
.ppEnabledExtensionNames = instanceExtensions,
|
.ppEnabledLayerNames = requiredValidationLayers.data(),
|
||||||
|
.enabledExtensionCount = static_cast<uint32_t>(requiredInstanceExtensions.size()),
|
||||||
|
.ppEnabledExtensionNames = requiredInstanceExtensions.data()
|
||||||
};
|
};
|
||||||
|
|
||||||
instance_ = vk::raii::Instance(context_, instanceCreateInfo);
|
instance_ = vk::raii::Instance(context_, instanceCreateInfo);
|
||||||
return (instance_ != nullptr);
|
return (instance_ != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<const char*> Engine::getRequiredInstanceExtensions() {
|
||||||
|
|
||||||
|
// get extensions that our windowing library requires
|
||||||
|
uint32_t sdlExtensionsCount = 0;
|
||||||
|
const char* const* sdlExtensions{ SDL_Vulkan_GetInstanceExtensions(&sdlExtensionsCount) };
|
||||||
|
// what in the world is this kind of pointer btw
|
||||||
|
|
||||||
|
std::vector<const char*> requiredExtensions(sdlExtensions, sdlExtensions + static_cast<size_t>(sdlExtensionsCount));
|
||||||
|
|
||||||
|
// manually add an extension for handling validation layers
|
||||||
|
if(enableValidationLayers) {
|
||||||
|
requiredExtensions.push_back(vk::EXTDebugUtilsExtensionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return requiredExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Engine::initDebugMessenger() {
|
||||||
|
|
||||||
|
if(!enableValidationLayers) return false;
|
||||||
|
|
||||||
|
// masks for which debug messages we want to see
|
||||||
|
vk::DebugUtilsMessageSeverityFlagsEXT severityFlags(vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError);
|
||||||
|
vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags( vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation);
|
||||||
|
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT{.messageSeverity = severityFlags,
|
||||||
|
.messageType = messageTypeFlags,
|
||||||
|
.pfnUserCallback = &debugCallback};
|
||||||
|
debugMessenger_ = instance_.createDebugUtilsMessengerEXT( debugUtilsMessengerCreateInfoEXT );
|
||||||
|
// we could get rid of this and just pass all the control to the logger
|
||||||
|
// like: "treat all messages of severity vk::eVerbose as our own DebugVerbosity::Info"
|
||||||
|
|
||||||
|
return (debugMessenger_ != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
VKAPI_ATTR vk::Bool32 VKAPI_CALL Engine::debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity,
|
||||||
|
vk::DebugUtilsMessageTypeFlagsEXT type,
|
||||||
|
const vk::DebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||||
|
void* pUserData) {
|
||||||
|
|
||||||
|
// this will eventually go through our logger
|
||||||
|
std::cout << "[ Validation Layer ] [Type: " << to_string(type) << "] " << pCallbackData->pMessage << std::endl;
|
||||||
|
/*
|
||||||
|
vk severity types:
|
||||||
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose
|
||||||
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo
|
||||||
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning
|
||||||
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError
|
||||||
|
|
||||||
|
vk message types:
|
||||||
|
vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral
|
||||||
|
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation
|
||||||
|
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance
|
||||||
|
*/
|
||||||
|
|
||||||
|
// returns whether or not we should abort, we'll always say no
|
||||||
|
return vk::False;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public:
|
|||||||
Engine(Window* window);
|
Engine(Window* window);
|
||||||
~Engine() = default;
|
~Engine() = default;
|
||||||
|
|
||||||
|
// initializes and sets up the vulkan instance. outside of constructor to allow control of order the order of initialization
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
// draw is called every render iteration in that while loop
|
// draw is called every render iteration in that while loop
|
||||||
@@ -20,14 +21,29 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Window* window_;
|
// returns a list of the required extensions needed by our engine
|
||||||
|
std::vector<const char*> getRequiredInstanceExtensions();
|
||||||
|
|
||||||
|
// helper for organizing the creation of the vulkan instance. returns success or failure
|
||||||
bool createInstance();
|
bool createInstance();
|
||||||
|
|
||||||
// Vulkan specific
|
// helper for attaching callbacks to the instance
|
||||||
|
bool initDebugMessenger();
|
||||||
|
|
||||||
|
// callback function for the vulkan debug extension: routes debug messages from validation layers to our app
|
||||||
|
static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity,
|
||||||
|
vk::DebugUtilsMessageTypeFlagsEXT type,
|
||||||
|
const vk::DebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||||
|
void* pUserData);
|
||||||
|
|
||||||
|
Window* window_;
|
||||||
|
|
||||||
|
// Vulkan specific instance members
|
||||||
vk::raii::Context context_;
|
vk::raii::Context context_;
|
||||||
vk::raii::Instance instance_ = nullptr;
|
vk::raii::Instance instance_ = nullptr;
|
||||||
|
vk::raii::DebugUtilsMessengerEXT debugMessenger_ = nullptr;
|
||||||
|
|
||||||
|
// members for control over validation layers
|
||||||
static constexpr bool enableValidationLayers = true; // TODO: only true in debug mode
|
static constexpr bool enableValidationLayers = true; // TODO: only true in debug mode
|
||||||
const std::vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" };
|
const std::vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user