source: opengl-game/vulkan-game.cpp@ be34c9a

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

Create the render pass

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