source: opengl-game/vulkan-game-ref.cpp@ 7dcd925

feature/imgui-sdl points-test
Last change on this file since 7dcd925 was 7dcd925, checked in by Dmitry Portnoy <dmitry.portnoy@…>, 6 years ago

Add a working reference example for validation layers

  • Property mode set to 100644
File size: 6.4 KB
Line 
1#include <vulkan/vulkan.h>
2
3#include <SDL2/SDL.h>
4#include <SDL2/SDL_vulkan.h>
5
6#include <iostream>
7#include <stdexcept>
8#include <vector>
9#include <cstring>
10#include <cstdlib>
11
12using namespace std;
13
14const int SCREEN_WIDTH = 800;
15const int SCREEN_HEIGHT = 600;
16
17const vector<const char*> validationLayers = {
18 "VK_LAYER_KHRONOS_validation"
19};
20
21#ifdef NDEBUG
22const bool enableValidationLayers = false;
23#else
24const bool enableValidationLayers = true;
25#endif
26
27VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {
28 auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
29 if (func != nullptr) {
30 return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
31 } else {
32 return VK_ERROR_EXTENSION_NOT_PRESENT;
33 }
34}
35
36class HelloTriangleApplication {
37public:
38 void run() {
39 initWindow();
40 initVulkan();
41 mainLoop();
42 cleanup();
43 }
44
45private:
46 SDL_Window* window;
47
48 VkInstance instance;
49 VkDebugUtilsMessengerEXT debugMessenger;
50
51 void initWindow() {
52 SDL_Init(SDL_INIT_EVERYTHING);
53
54 window = SDL_CreateWindow("Vulkan Game",
55 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
56 SCREEN_WIDTH, SCREEN_HEIGHT,
57 SDL_WINDOW_VULKAN | SDL_WINDOW_SHOWN);
58 }
59
60 void initVulkan() {
61 createInstance();
62 setupDebugMessenger();
63 }
64
65 void mainLoop() {
66 SDL_Event e;
67 bool quit = false;
68
69 while(!quit) {
70 while (SDL_PollEvent(&e)) {
71 if (e.type == SDL_QUIT) {
72 quit = true;
73 }
74 if (e.type == SDL_KEYDOWN) {
75 quit = true;
76 }
77 if (e.type == SDL_MOUSEBUTTONDOWN) {
78 quit = true;
79 }
80 }
81 }
82 }
83
84 void cleanup() {
85 vkDestroyInstance(instance, nullptr);
86
87 SDL_DestroyWindow(window);
88
89 SDL_Quit();
90 }
91
92 void createInstance() {
93 if (enableValidationLayers && !checkValidationLayerSupport()) {
94 throw runtime_error("validation layers requested, but not available!");
95 }
96
97 VkApplicationInfo appInfo = {};
98 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
99 appInfo.pApplicationName = "Hello Triangle";
100 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
101 appInfo.pEngineName = "No Engine";
102 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
103 appInfo.apiVersion = VK_API_VERSION_1_0;
104
105 VkInstanceCreateInfo createInfo = {};
106 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
107 createInfo.pApplicationInfo = &appInfo;
108
109 auto extensions = getRequiredExtensions();
110 createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
111 createInfo.ppEnabledExtensionNames = extensions.data();
112
113 if (enableValidationLayers) {
114 createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
115 createInfo.ppEnabledLayerNames = validationLayers.data();
116 } else {
117 createInfo.enabledLayerCount = 0;
118 }
119
120 if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
121 throw runtime_error("failed to create instance!");
122 }
123 }
124
125 void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
126 createInfo = {};
127 createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
128 createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
129 createInfo.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;
130 createInfo.pfnUserCallback = debugCallback;
131 }
132
133 void setupDebugMessenger() {
134 if (!enableValidationLayers) return;
135
136 VkDebugUtilsMessengerCreateInfoEXT createInfo = {};
137 createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
138 createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
139 createInfo.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;
140 createInfo.pfnUserCallback = debugCallback;
141
142 if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
143 throw runtime_error("failed to set up debug messenger!");
144 }
145 }
146
147 vector<const char*> getRequiredExtensions() {
148 uint32_t extensionCount = 0;
149 SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, nullptr);
150
151 vector<const char*> extensions(extensionCount);
152 SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, extensions.data());
153
154 if (enableValidationLayers) {
155 extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
156 }
157
158 return extensions;
159 }
160
161 bool checkValidationLayerSupport() {
162 uint32_t layerCount;
163 vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
164
165 vector<VkLayerProperties> availableLayers(layerCount);
166 vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
167
168 for (const char* layerName : validationLayers) {
169 bool layerFound = false;
170
171 for (const auto& layerProperties : availableLayers) {
172 if (strcmp(layerName, layerProperties.layerName) == 0) {
173 layerFound = true;
174 break;
175 }
176 }
177
178 if (!layerFound) {
179 return false;
180 }
181 }
182
183 return true;
184 }
185
186 static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
187 cerr << "validation layer: " << pCallbackData->pMessage << endl;
188
189 return VK_FALSE;
190 }
191};
192
193int main() {
194 HelloTriangleApplication app;
195
196 try {
197 app.run();
198 } catch (const exception& e) {
199 cerr << e.what() << endl;
200 return EXIT_FAILURE;
201 }
202
203 return EXIT_SUCCESS;
204}
Note: See TracBrowser for help on using the repository browser.