Files
LearningVulkan/Learning Vulkan.cpp
onTheZero 5b32d32b0b Base Code
Instance
Validation Layers
2026-01-04 07:07:45 -05:00

261 lines
5.7 KiB
C++

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include "Logger.h"
const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600;
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif
class HelloTriangleApplication
{
private:
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
{
std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;
return VK_FALSE;
}
private:
GLFWwindow* window;
VkInstance instance;
std::vector<const char*> GetRequiredExtensions()
{
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
if (enableValidationLayers)
{
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
return extensions;
}
bool CheckValidationLayerSupport()
{
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
for (const char* layerName : validationLayers)
{
bool layerFound = false;
for (const auto& layerProperties : availableLayers)
{
if (strcmp(layerName, layerProperties.layerName) == 0)
{
layerFound = true;
break;
}
}
if (!layerFound)
{
return false;
}
}
return true;
}
// VkResult vkCreateInstance(
// const VkInstanceCreateInfo* pCreateInfo,
// const VkAllocationCallbacks* pAllocator,
// VkInstance* instance)
//{
// if (pCreateInfo == nullptr || instance == nullptr) {
// log("Null pointer passed to required parameter!");
// return VK_ERROR_INITIALIZATION_FAILED;
// }
// return vkCreateInstance(pCreateInfo, pAllocator, instance);
//}
public:
void Run()
{
InitWindow();
InitVulkan();
MainLoop();
Cleanup();
}
private:
void CheckExtensions(const char* requiredExtensions[], uint32_t requiredExtensionsCount)
{
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> extensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
std::string required;
std::string available;
required += "Required extensions:\n";
bool found = false;
for (uint32_t i = 0; i < requiredExtensionsCount; i++)
{
std::string requiredExtension = requiredExtensions[i];
for (const auto& extension : extensions)
{
found = strcmp(extension.extensionName, requiredExtensions[i]);
if (found)
{
break;
}
}
std::string status = found ? "FOUND" : "NOT FOUND";
required += "\t" + requiredExtension + " : " + status + "\n";
}
available += "available extensions:\n";
for (const auto& extension : extensions)
{
std::string extensionName = extension.extensionName;
available += "\t" + extensionName + "\n";
}
log(INFO, required);
log(INFO, available);
}
void CreateInstance()
{
log(INFO, "Creating Vulkan instance");
if (enableValidationLayers && !CheckValidationLayerSupport())
{
throw std::runtime_error("validation layers requested, but not available!");
}
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Hello Triangle";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;
if (enableValidationLayers)
{
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
}
else
{
createInfo.enabledLayerCount = 0;
}
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS)
{
throw std::runtime_error("failed to create instance!");
}
CheckExtensions(glfwExtensions, glfwExtensionCount);
auto extensions = GetRequiredExtensions();
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
}
void InitWindow()
{
log(INFO, "Initializing GLFW window...");
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
}
void InitVulkan()
{
log(INFO, "Initializing Vulkan...");
CreateInstance();
}
void MainLoop()
{
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
}
}
void Cleanup()
{
vkDestroyInstance(instance, nullptr);
glfwDestroyWindow(window);
glfwTerminate();
}
};
int main()
{
HelloTriangleApplication app;
try
{
app.Run();
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}