source: opengl-game/vulkan-game.cpp@ 84216c7

feature/imgui-sdl points-test
Last change on this file since 84216c7 was 84216c7, checked in by Dmitry Portnoy <dmp1488@…>, 6 years ago

Finish creating the rendering pipeline

  • Property mode set to 100644
File size: 27.7 KB
RevLine 
[826df16]1#include <vulkan/vulkan.h>
[03f4c64]2
[826df16]3#include <SDL2/SDL.h>
4#include <SDL2/SDL_vulkan.h>
5
6//#define _USE_MATH_DEFINES // Will be needed when/if I need to # include <cmath>
[03f4c64]7
8#define GLM_FORCE_RADIANS
9#define GLM_FORCE_DEPTH_ZERO_TO_ONE
10#include <glm/vec4.hpp>
11#include <glm/mat4x4.hpp>
12
13#include <iostream>
[826df16]14#include <vector>
[b3671b5]15#include <set>
[826df16]16#include <stdexcept>
17#include <cstdlib>
[909b51a]18#include <optional>
[bfd620e]19#include <algorithm>
[e09ad38]20#include <fstream>
[826df16]21
22#include "game-gui-sdl.hpp"
[03f4c64]23
24using namespace std;
[bfd620e]25//using namespace glm;
[03f4c64]26
[826df16]27const int SCREEN_WIDTH = 800;
28const int SCREEN_HEIGHT = 600;
29
30#ifdef NDEBUG
31 const bool enableValidationLayers = false;
32#else
33 const bool enableValidationLayers = true;
34#endif
35
[bfd620e]36const vector<const char*> validationLayers = {
37 "VK_LAYER_KHRONOS_validation"
38};
39
40const vector<const char*> deviceExtensions = {
41 VK_KHR_SWAPCHAIN_EXTENSION_NAME
42};
43
[909b51a]44struct QueueFamilyIndices {
45 optional<uint32_t> graphicsFamily;
[b3671b5]46 optional<uint32_t> presentFamily;
[909b51a]47
48 bool isComplete() {
[b3671b5]49 return graphicsFamily.has_value() && presentFamily.has_value();
[909b51a]50 }
51};
52
[bfd620e]53struct SwapChainSupportDetails {
54 VkSurfaceCapabilitiesKHR capabilities;
55 vector<VkSurfaceFormatKHR> formats;
56 vector<VkPresentModeKHR> presentModes;
57};
58
[b6127d2]59VkResult CreateDebugUtilsMessengerEXT(VkInstance instance,
60 const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
61 const VkAllocationCallbacks* pAllocator,
62 VkDebugUtilsMessengerEXT* pDebugMessenger) {
63 auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(
64 instance, "vkCreateDebugUtilsMessengerEXT");
65
66 if (func != nullptr) {
67 return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
68 } else {
69 return VK_ERROR_EXTENSION_NOT_PRESENT;
70 }
71}
72
[80de39d]73void DestroyDebugUtilsMessengerEXT(VkInstance instance,
74 VkDebugUtilsMessengerEXT debugMessenger,
75 const VkAllocationCallbacks* pAllocator) {
76 auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(
77 instance, "vkDestroyDebugUtilsMessengerEXT");
78
79 if (func != nullptr) {
80 func(instance, debugMessenger, pAllocator);
81 }
82}
83
[826df16]84class VulkanGame {
85 public:
86 void run() {
87 if (initWindow() == RTWO_ERROR) {
88 return;
89 }
90 initVulkan();
91 mainLoop();
92 cleanup();
93 }
94 private:
[98f3232]95 GameGui* gui = new GameGui_SDL();
[80de39d]96 SDL_Window* window = nullptr;
[826df16]97
98 VkInstance instance;
[b6127d2]99 VkDebugUtilsMessengerEXT debugMessenger;
[b3671b5]100 VkSurfaceKHR surface;
[321272c]101 SDL_Surface* sdlSurface = nullptr;
[b3671b5]102
[909b51a]103 VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
104 VkDevice device;
[b3671b5]105
[909b51a]106 VkQueue graphicsQueue;
[b3671b5]107 VkQueue presentQueue;
[826df16]108
[bfd620e]109 VkSwapchainKHR swapChain;
110 vector<VkImage> swapChainImages;
111 VkFormat swapChainImageFormat;
112 VkExtent2D swapChainExtent;
113
114 vector<VkImageView> swapChainImageViews;
[84216c7]115 VkPipelineLayout pipelineLayout;
[bfd620e]116
[826df16]117 // both SDL and GLFW create window functions return NULL on failure
118 bool initWindow() {
[98f3232]119 if (gui->Init() == RTWO_ERROR) {
[826df16]120 cout << "UI library could not be initialized!" << endl;
121 return RTWO_ERROR;
122 } else {
123 // On Apple's OS X you must set the NSHighResolutionCapable Info.plist property to YES,
124 // otherwise you will not receive a High DPI OpenGL canvas.
125
126 // TODO: Move this into some generic method in game-gui-sdl
127 window = SDL_CreateWindow("Vulkan Game",
128 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
129 SCREEN_WIDTH, SCREEN_HEIGHT,
130 SDL_WINDOW_VULKAN | SDL_WINDOW_SHOWN);
131
[80de39d]132 if (window == nullptr) {
[826df16]133 cout << "Window could not be created!" << endl;
134 return RTWO_ERROR;
135 } else {
136 return RTWO_SUCCESS;
137 }
138 }
139 }
140
141 void initVulkan() {
142 createInstance();
[7dcd925]143 setupDebugMessenger();
[b3671b5]144 createSurface();
[909b51a]145 pickPhysicalDevice();
146 createLogicalDevice();
[bfd620e]147 createSwapChain();
148 createImageViews();
[4befb76]149 createGraphicsPipeline();
[826df16]150 }
151
152 void createInstance() {
[b6127d2]153 if (enableValidationLayers && !checkValidationLayerSupport()) {
154 throw runtime_error("validation layers requested, but not available!");
155 }
156
[826df16]157 VkApplicationInfo appInfo = {};
158 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
159 appInfo.pApplicationName = "Vulkan Game";
160 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
161 appInfo.pEngineName = "No Engine";
162 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
163 appInfo.apiVersion = VK_API_VERSION_1_0;
164
165 VkInstanceCreateInfo createInfo = {};
166 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
167 createInfo.pApplicationInfo = &appInfo;
168
[a8f0577]169 vector<const char*> extensions = getRequiredExtensions();
[b6127d2]170 createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
171 createInfo.ppEnabledExtensionNames = extensions.data();
[826df16]172
[b3671b5]173 cout << endl << "SDL extensions:" << endl;
174 for (const char* extensionName : extensions) {
175 cout << extensionName << endl;
176 }
177 cout << endl;
178
[80de39d]179 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
[b6127d2]180 if (enableValidationLayers) {
181 createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
182 createInfo.ppEnabledLayerNames = validationLayers.data();
[80de39d]183
184 populateDebugMessengerCreateInfo(debugCreateInfo);
185 createInfo.pNext = &debugCreateInfo;
[b6127d2]186 } else {
187 createInfo.enabledLayerCount = 0;
[80de39d]188
189 createInfo.pNext = nullptr;
[b6127d2]190 }
[826df16]191
192 if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
193 throw runtime_error("failed to create instance!");
194 }
195 }
196
[80de39d]197 void setupDebugMessenger() {
198 if (!enableValidationLayers) return;
199
200 VkDebugUtilsMessengerCreateInfoEXT createInfo;
201 populateDebugMessengerCreateInfo(createInfo);
[b6127d2]202
203 if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
204 throw runtime_error("failed to setup debug messenger!");
205 }
206 }
207
[b3671b5]208 void createSurface() {
[321272c]209 sdlSurface = SDL_GetWindowSurface(window);
210
211 if (sdlSurface == nullptr) {
212 cout << "Could not get SDL Surface! =(" << endl;
213 }
[b3671b5]214
215 if (!SDL_Vulkan_CreateSurface(window, instance, &surface)) {
216 throw runtime_error("failed to create window surface!");
217 }
218
219 /*
220 if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {
221 throw runtime_error("failed to create window surface!");
222 }
223 */
224 }
225
[909b51a]226 void pickPhysicalDevice() {
227 uint32_t deviceCount = 0;
228 vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
229
230 if (deviceCount == 0) {
231 throw runtime_error("failed to find GPUs with Vulkan support!");
232 }
233
234 vector<VkPhysicalDevice> devices(deviceCount);
235 vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
236
237 cout << endl << "Graphics cards:" << endl;
238 for (const VkPhysicalDevice& device : devices) {
239 if (isDeviceSuitable(device)) {
240 physicalDevice = device;
241 break;
242 }
243 }
244 cout << endl;
245
246 if (physicalDevice == VK_NULL_HANDLE) {
247 throw runtime_error("failed to find a suitable GPU!");
248 }
249 }
250
251 bool isDeviceSuitable(VkPhysicalDevice device) {
252 VkPhysicalDeviceProperties deviceProperties;
253 VkPhysicalDeviceFeatures deviceFeatures;
254
255 vkGetPhysicalDeviceProperties(device, &deviceProperties);
256 vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
257
258 cout << "Device: " << deviceProperties.deviceName << endl;
259
260 QueueFamilyIndices indices = findQueueFamilies(device);
261
[bfd620e]262 bool extensionsSupported = checkDeviceExtensionSupport(device);
263
264 bool swapChainAdequate = false;
265
266 if (extensionsSupported) {
267 SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device);
268 swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
269 }
270
271 return indices.isComplete() && extensionsSupported && swapChainAdequate;
272 }
273
274 bool checkDeviceExtensionSupport(VkPhysicalDevice device) {
275 uint32_t extensionCount;
276 vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
277
278 vector<VkExtensionProperties> availableExtensions(extensionCount);
279 vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
280
281 set<string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
282
283 for (const auto& extension : availableExtensions) {
284 requiredExtensions.erase(extension.extensionName);
285 }
286
287 return requiredExtensions.empty();
[909b51a]288 }
289
290 void createLogicalDevice() {
291 QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
292
[b3671b5]293 vector<VkDeviceQueueCreateInfo> queueCreateInfos;
294 set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()};
[909b51a]295
296 float queuePriority = 1.0f;
[b3671b5]297 for (uint32_t queueFamily : uniqueQueueFamilies) {
298 VkDeviceQueueCreateInfo queueCreateInfo = {};
299
300 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
301 queueCreateInfo.queueFamilyIndex = queueFamily;
302 queueCreateInfo.queueCount = 1;
303 queueCreateInfo.pQueuePriorities = &queuePriority;
304
305 queueCreateInfos.push_back(queueCreateInfo);
306 }
[909b51a]307
308 VkPhysicalDeviceFeatures deviceFeatures = {};
309
310 VkDeviceCreateInfo createInfo = {};
311 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
312
[b3671b5]313 createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());;
314 createInfo.pQueueCreateInfos = queueCreateInfos.data();
[909b51a]315
316 createInfo.pEnabledFeatures = &deviceFeatures;
317
[bfd620e]318 createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
319 createInfo.ppEnabledExtensionNames = deviceExtensions.data();
[909b51a]320
321 // These fields are ignored by up-to-date Vulkan implementations,
322 // but it's a good idea to set them for backwards compatibility
323 if (enableValidationLayers) {
324 createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
325 createInfo.ppEnabledLayerNames = validationLayers.data();
326 } else {
327 createInfo.enabledLayerCount = 0;
328 }
329
330 if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
331 throw runtime_error("failed to create logical device!");
332 }
333
334 vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
[b3671b5]335 vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
[909b51a]336 }
337
[a8f0577]338 bool checkValidationLayerSupport() {
339 uint32_t layerCount;
340 vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
341
342 vector<VkLayerProperties> availableLayers(layerCount);
343 vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
344
345 for (const char* layerName : validationLayers) {
346 bool layerFound = false;
347
348 for (const auto& layerProperties : availableLayers) {
349 if (strcmp(layerName, layerProperties.layerName) == 0) {
350 layerFound = true;
351 break;
352 }
353 }
354
355 if (!layerFound) {
356 return false;
357 }
358 }
359
360 return true;
361 }
362
[909b51a]363 QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
364 QueueFamilyIndices indices;
365
366 uint32_t queueFamilyCount = 0;
367 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
368
369 vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
370 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
371
372 int i = 0;
373 for (const auto& queueFamily : queueFamilies) {
374 if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
375 indices.graphicsFamily = i;
376 }
377
[b3671b5]378 VkBool32 presentSupport = false;
379 vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
380
381 if (queueFamily.queueCount > 0 && presentSupport) {
382 indices.presentFamily = i;
383 }
384
[909b51a]385 if (indices.isComplete()) {
386 break;
387 }
388
389 i++;
390 }
391
392 return indices;
393 }
394
[bfd620e]395 SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) {
396 SwapChainSupportDetails details;
397
398 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
399
400 uint32_t formatCount;
401 vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
402
403 if (formatCount != 0) {
404 details.formats.resize(formatCount);
405 vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
406 }
407
408 uint32_t presentModeCount;
409 vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
410
411 if (presentModeCount != 0) {
412 details.presentModes.resize(presentModeCount);
413 vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
414 }
415
416 return details;
417 }
418
419 VkSurfaceFormatKHR chooseSwapSurfaceFormat(const vector<VkSurfaceFormatKHR>& availableFormats) {
420 for (const auto& availableFormat : availableFormats) {
421 if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
422 return availableFormat;
423 }
424 }
425
426 return availableFormats[0];
427 }
428
429 VkPresentModeKHR chooseSwapPresentMode(const vector<VkPresentModeKHR>& availablePresentModes) {
430 VkPresentModeKHR bestMode = VK_PRESENT_MODE_FIFO_KHR;
431
432 for (const auto& availablePresentMode : availablePresentModes) {
433 if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
434 return availablePresentMode;
435 } else if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) {
436 bestMode = availablePresentMode;
437 }
438 }
439
440 return bestMode;
441 }
442
443 VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) {
444 if (capabilities.currentExtent.width != numeric_limits<uint32_t>::max()) {
445 return capabilities.currentExtent;
446 } else {
447 VkExtent2D actualExtent = { SCREEN_WIDTH, SCREEN_HEIGHT };
448
449 actualExtent.width = max(capabilities.minImageExtent.width, min(capabilities.maxImageExtent.width, actualExtent.width));
450 actualExtent.height = max(capabilities.minImageExtent.height, min(capabilities.maxImageExtent.height, actualExtent.height));
451
452 return actualExtent;
453 }
454 }
455
[909b51a]456 void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
457 createInfo = {};
458 createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
459 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;
460 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;
461 createInfo.pfnUserCallback = debugCallback;
462 }
463
[a8f0577]464 vector<const char*> getRequiredExtensions() {
465 uint32_t extensionCount = 0;
466 SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, nullptr);
467
468 vector<const char*> extensions(extensionCount);
469 SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, extensions.data());
470
471 if (enableValidationLayers) {
472 extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
473 }
474
475 return extensions;
476 }
477
[bfd620e]478 void createSwapChain() {
479 SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);
480
481 VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
482 VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
483 VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
484
485 uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
486 if (swapChainSupport.capabilities.maxImageCount > 0 &&
487 imageCount > swapChainSupport.capabilities.maxImageCount) {
488 imageCount = swapChainSupport.capabilities.maxImageCount;
489 }
490
491 VkSwapchainCreateInfoKHR createInfo = {};
492
493 createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
494 createInfo.surface = surface;
495 createInfo.minImageCount = imageCount;
496 createInfo.imageFormat = surfaceFormat.format;
497 createInfo.imageColorSpace = surfaceFormat.colorSpace;
498 createInfo.imageExtent = extent;
499 createInfo.imageArrayLayers = 1;
500 createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
501
502 QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
503 uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()};
504
505 if (indices.graphicsFamily != indices.presentFamily) {
506 createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
507 createInfo.queueFamilyIndexCount = 2;
508 createInfo.pQueueFamilyIndices = queueFamilyIndices;
509 } else {
510 createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
511 createInfo.queueFamilyIndexCount = 0; // Optional
512 createInfo.pQueueFamilyIndices = nullptr;
513 }
514
515 createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
516 createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
517 createInfo.presentMode = presentMode;
518 createInfo.clipped = VK_TRUE;
519 createInfo.oldSwapchain = VK_NULL_HANDLE;
520
521 if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
522 throw runtime_error("failed to create swap chain!");
523 }
524
525 vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
526 swapChainImages.resize(imageCount);
527 vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());
528
529 swapChainImageFormat = surfaceFormat.format;
530 swapChainExtent = extent;
531 }
532
533 void createImageViews() {
534 swapChainImageViews.resize(swapChainImages.size());
535
536 for (size_t i=0; i<swapChainImages.size(); i++) {
537 VkImageViewCreateInfo createInfo = {};
538 createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
539 createInfo.image = swapChainImages[i];
540
541 createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
542 createInfo.format = swapChainImageFormat;
543
544 createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
545 createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
546 createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
547 createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
548
549 createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
550 createInfo.subresourceRange.baseMipLevel = 0;
551 createInfo.subresourceRange.levelCount = 1;
552 createInfo.subresourceRange.baseArrayLayer = 0;
553 createInfo.subresourceRange.layerCount = 1;
554
555 if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {
556 throw runtime_error("failed to create image views!");
557 }
558 }
559 }
560
[4befb76]561 void createGraphicsPipeline() {
[e09ad38]562 auto vertShaderCode = readFile("shaders/vert.spv");
563 auto fragShaderCode = readFile("shaders/frag.spv");
564
565 VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
566 VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
567
568 VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
569 vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
570 vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
571 vertShaderStageInfo.module = vertShaderModule;
572 vertShaderStageInfo.pName = "main";
573
574 VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
575 fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
576 fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
577 fragShaderStageInfo.module = fragShaderModule;
578 fragShaderStageInfo.pName = "main";
579
580 VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
581
[84216c7]582 VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
583 vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
584 vertexInputInfo.vertexBindingDescriptionCount = 0;
585 vertexInputInfo.vertexAttributeDescriptionCount = 0;
586
587 VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
588 inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
589 inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
590 inputAssembly.primitiveRestartEnable = VK_FALSE;
591
592 VkViewport viewport = {};
593 viewport.x = 0.0f;
594 viewport.y = 0.0f;
595 viewport.width = (float) swapChainExtent.width;
596 viewport.height = (float) swapChainExtent.height;
597 viewport.minDepth = 0.0f;
598 viewport.maxDepth = 1.0f;
599
600 VkRect2D scissor = {};
601 scissor.offset = { 0, 0 };
602 scissor.extent = swapChainExtent;
603
604 VkPipelineViewportStateCreateInfo viewportState = {};
605 viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
606 viewportState.viewportCount = 1;
607 viewportState.pViewports = &viewport;
608 viewportState.scissorCount = 1;
609 viewportState.pScissors = &scissor;
610
611 VkPipelineRasterizationStateCreateInfo rasterizer = {};
612 rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
613 rasterizer.depthClampEnable = VK_FALSE;
614 rasterizer.rasterizerDiscardEnable = VK_FALSE;
615 rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
616 rasterizer.lineWidth = 1.0f;
617 rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
618 rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
619 rasterizer.depthBiasEnable = false;
620
621 VkPipelineMultisampleStateCreateInfo multisampling = {};
622 multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
623 multisampling.sampleShadingEnable = VK_FALSE;
624 multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
625
626 VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
627 colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
628 colorBlendAttachment.blendEnable = VK_FALSE;
629
630 VkPipelineColorBlendStateCreateInfo colorBlending = {};
631 colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
632 colorBlending.logicOpEnable = VK_FALSE;
633 colorBlending.logicOp = VK_LOGIC_OP_COPY;
634 colorBlending.attachmentCount = 1;
635 colorBlending.pAttachments = &colorBlendAttachment;
636 colorBlending.blendConstants[0] = 0.0f;
637 colorBlending.blendConstants[1] = 0.0f;
638 colorBlending.blendConstants[2] = 0.0f;
639 colorBlending.blendConstants[3] = 0.0f;
640
641 VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
642 pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
643 pipelineLayoutInfo.setLayoutCount = 0;
644 pipelineLayoutInfo.pushConstantRangeCount = 0;
645
646 if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
647 throw runtime_error("failed to create pipeline layout!");
648 }
649
[e09ad38]650 vkDestroyShaderModule(device, vertShaderModule, nullptr);
651 vkDestroyShaderModule(device, fragShaderModule, nullptr);
652 }
653
654 VkShaderModule createShaderModule(const vector<char>& code) {
655 VkShaderModuleCreateInfo createInfo = {};
656 createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
657 createInfo.codeSize = code.size();
658 createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
659
660 VkShaderModule shaderModule;
661 if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
662 throw runtime_error("failed to create shader module!");
663 }
664
665 return shaderModule;
[4befb76]666 }
667
[826df16]668 void mainLoop() {
669 // TODO: Create some generic event-handling functions in game-gui-*
670 SDL_Event e;
671 bool quit = false;
672
[7dcd925]673 while (!quit) {
[826df16]674 while (SDL_PollEvent(&e)) {
675 if (e.type == SDL_QUIT) {
676 quit = true;
677 }
678 if (e.type == SDL_KEYDOWN) {
679 quit = true;
680 }
681 if (e.type == SDL_MOUSEBUTTONDOWN) {
682 quit = true;
683 }
[321272c]684
[e09ad38]685 /**/
[bfd620e]686 SDL_FillRect(sdlSurface, nullptr, SDL_MapRGB(sdlSurface->format, 0xFF, 0xFF, 0xFF));
[321272c]687
[bfd620e]688 SDL_UpdateWindowSurface(window);
[e09ad38]689 /**/
[bfd620e]690 }
691 }
[826df16]692 }
693
694 void cleanup() {
[84216c7]695 vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
696
[bfd620e]697 for (auto imageView : swapChainImageViews) {
698 vkDestroyImageView(device, imageView, nullptr);
699 }
700
701 vkDestroySwapchainKHR(device, swapChain, nullptr);
[909b51a]702 vkDestroyDevice(device, nullptr);
703
[80de39d]704 if (enableValidationLayers) {
705 DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
706 }
707
[b3671b5]708 vkDestroySurfaceKHR(instance, surface, nullptr);
[826df16]709 vkDestroyInstance(instance, nullptr);
710
711 // TODO: Move this into some generic method in game-gui-sdl
712 SDL_DestroyWindow(window);
713
[98f3232]714 gui->Shutdown();
715 delete gui;
[826df16]716 }
[e09ad38]717
718 static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
719 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
720 VkDebugUtilsMessageTypeFlagsEXT messageType,
721 const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
722 void* pUserData) {
723 cerr << "validation layer: " << pCallbackData->pMessage << endl;
724
725 return VK_FALSE;
726}
727
728 static vector<char> readFile(const string& filename) {
729 ifstream file(filename, ios::ate | ios::binary);
730
731 if (!file.is_open()) {
732 throw runtime_error("failed to open file!");
733 }
734
735 size_t fileSize = (size_t)file.tellg();
736 vector<char> buffer(fileSize);
737
738 file.seekg(0);
739 file.read(buffer.data(), fileSize);
740
741 file.close();
742
743 return buffer;
744 }
[826df16]745};
746
[1c6cd5e]747int main(int argc, char* argv[]) {
[826df16]748
[b6127d2]749#ifdef NDEBUG
750 cout << "DEBUGGING IS OFF" << endl;
751#else
752 cout << "DEBUGGING IS ON" << endl;
753#endif
[a8f0577]754
[bfd620e]755 glm::mat4 matrix;
756 glm::vec4 vec;
757 glm::vec4 test = matrix * vec;
[826df16]758
759 cout << "Starting Vulkan game..." << endl;
760
761 VulkanGame game;
762
763 try {
764 game.run();
765 } catch (const exception& e) {
766 cerr << e.what() << endl;
767 return EXIT_FAILURE;
768 }
[03f4c64]769
[826df16]770 cout << "Finished running the game" << endl;
[03f4c64]771
[826df16]772 return EXIT_SUCCESS;
[03f4c64]773}
Note: See TracBrowser for help on using the repository browser.