source: opengl-game/vulkan-game.cpp@ 771b33a

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

In openglgame, port over some more of the pipeline creation code and the functionality to specify and initialize varying attributes

  • Property mode set to 100644
File size: 19.5 KB
RevLine 
[99d44b2]1#include "vulkan-game.hpp"
[850e84c]2
[6fc24c7]3#include <array>
[0df3c9a]4#include <iostream>
[c1c2021]5#include <set>
[0df3c9a]6
[5edbd58]7#include "consts.hpp"
[c559904]8#include "logger.hpp"
[5edbd58]9
[771b33a]10#include "utils.hpp"
[c1d9b2a]11#include "vulkan-utils.hpp"
12
[0df3c9a]13using namespace std;
14
[99d44b2]15VulkanGame::VulkanGame() {
[0df3c9a]16 gui = nullptr;
17 window = nullptr;
18}
19
[99d44b2]20VulkanGame::~VulkanGame() {
[0df3c9a]21}
22
[b6e60b4]23void VulkanGame::run(int width, int height, unsigned char guiFlags) {
[2e77b3f]24 cout << "DEBUGGING IS " << (ENABLE_VALIDATION_LAYERS ? "ON" : "OFF") << endl;
25
26 cout << "Vulkan Game" << endl;
27
[c559904]28 // This gets the runtime version, use SDL_VERSION() for the comppile-time version
29 // TODO: Create a game-gui function to get the gui version and retrieve it that way
30 SDL_GetVersion(&sdlVersion);
31
32 // TODO: Refactor the logger api to be more flexible,
33 // esp. since gl_log() and gl_log_err() have issues printing anything besides stirngs
34 restart_gl_log();
35 gl_log("starting SDL\n%s.%s.%s",
36 to_string(sdlVersion.major).c_str(),
37 to_string(sdlVersion.minor).c_str(),
38 to_string(sdlVersion.patch).c_str());
39
40 open_log();
41 get_log() << "starting SDL" << endl;
42 get_log() <<
43 (int)sdlVersion.major << "." <<
44 (int)sdlVersion.minor << "." <<
45 (int)sdlVersion.patch << endl;
46
[5edbd58]47 if (initWindow(width, height, guiFlags) == RTWO_ERROR) {
[0df3c9a]48 return;
49 }
[b6e60b4]50
[0df3c9a]51 initVulkan();
52 mainLoop();
53 cleanup();
[c559904]54
55 close_log();
[0df3c9a]56}
57
[c559904]58// TODO: Make some more initi functions, or call this initUI if the
59// amount of things initialized here keeps growing
[b6e60b4]60bool VulkanGame::initWindow(int width, int height, unsigned char guiFlags) {
[c559904]61 // TODO: Put all fonts, textures, and images in the assets folder
[0df3c9a]62 gui = new GameGui_SDL();
63
[b6e60b4]64 if (gui->init() == RTWO_ERROR) {
[c559904]65 // TODO: Also print these sorts of errors to the log
[0df3c9a]66 cout << "UI library could not be initialized!" << endl;
[b6e60b4]67 cout << gui->getError() << endl;
[0df3c9a]68 return RTWO_ERROR;
69 }
70
[b6e60b4]71 window = (SDL_Window*) gui->createWindow("Vulkan Game", width, height, guiFlags & GUI_FLAGS_WINDOW_FULLSCREEN);
[0df3c9a]72 if (window == nullptr) {
73 cout << "Window could not be created!" << endl;
[ed7c953]74 cout << gui->getError() << endl;
[0df3c9a]75 return RTWO_ERROR;
76 }
77
[b6e60b4]78 cout << "Target window size: (" << width << ", " << height << ")" << endl;
[a6f6833]79 cout << "Actual window size: (" << gui->getWindowWidth() << ", " << gui->getWindowHeight() << ")" << endl;
[b6e60b4]80
[c1d9b2a]81 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
82 if (renderer == nullptr) {
83 cout << "Renderer could not be created!" << endl;
84 cout << gui->getError() << endl;
85 return RTWO_ERROR;
86 }
87
[0df3c9a]88 return RTWO_SUCCESS;
89}
90
[99d44b2]91void VulkanGame::initVulkan() {
[c1d9b2a]92 const vector<const char*> validationLayers = {
93 "VK_LAYER_KHRONOS_validation"
94 };
[fe5c3ba]95 const vector<const char*> deviceExtensions = {
96 VK_KHR_SWAPCHAIN_EXTENSION_NAME
97 };
[c1d9b2a]98
99 createVulkanInstance(validationLayers);
100 setupDebugMessenger();
[90a424f]101 createVulkanSurface();
[fe5c3ba]102 pickPhysicalDevice(deviceExtensions);
[c1c2021]103 createLogicalDevice(validationLayers, deviceExtensions);
[502bd0b]104 createSwapChain();
[f94eea9]105 createImageViews();
[6fc24c7]106 createRenderPass();
[fa9fa1c]107 createCommandPool();
[7d2b0b9]108
[771b33a]109 graphicsPipelines.push_back(GraphicsPipeline_Vulkan(device, viewport, sizeof(Vertex)));
110
111 graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&Vertex::pos));
112 graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&Vertex::color));
113 graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&Vertex::texCoord));
114
[7d2b0b9]115 graphicsPipelines.back().createPipeline("shaders/scene-vert.spv", "shaders/scene-frag.spv");
116
[771b33a]117 graphicsPipelines.push_back(GraphicsPipeline_Vulkan(device, viewport, sizeof(OverlayVertex)));
118
119 graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&OverlayVertex::pos));
120 graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&OverlayVertex::texCoord));
121
[7d2b0b9]122 graphicsPipelines.back().createPipeline("shaders/overlay-vert.spv", "shaders/overlay-frag.spv");
123
124 cout << "Created " << graphicsPipelines.size() << " graphics pipelines" << endl;
[0df3c9a]125}
126
[99d44b2]127void VulkanGame::mainLoop() {
[f6521fb]128 UIEvent e;
[0df3c9a]129 bool quit = false;
130
[c1d9b2a]131 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
132
[0df3c9a]133 while (!quit) {
[27c40ce]134 gui->processEvents();
135
[f6521fb]136 while (gui->pollEvent(&e)) {
137 switch(e.type) {
138 case UI_EVENT_QUIT:
139 cout << "Quit event detected" << endl;
140 quit = true;
141 break;
142 case UI_EVENT_WINDOW:
143 cout << "Window event detected" << endl;
144 // Currently unused
145 break;
[0e09340]146 case UI_EVENT_WINDOWRESIZE:
147 cout << "Window resize event detected" << endl;
148 framebufferResized = true;
149 break;
[f6521fb]150 case UI_EVENT_KEY:
151 if (e.key.keycode == SDL_SCANCODE_ESCAPE) {
152 quit = true;
153 } else {
154 cout << "Key event detected" << endl;
155 }
156 break;
157 case UI_EVENT_MOUSEBUTTONDOWN:
158 cout << "Mouse button down event detected" << endl;
159 break;
160 case UI_EVENT_MOUSEBUTTONUP:
161 cout << "Mouse button up event detected" << endl;
162 break;
163 case UI_EVENT_MOUSEMOTION:
164 break;
[a0da009]165 case UI_EVENT_UNKNOWN:
166 cout << "Unknown event type: 0x" << hex << e.unknown.eventType << dec << endl;
167 break;
[c61323a]168 default:
169 cout << "Unhandled UI event: " << e.type << endl;
[0df3c9a]170 }
171 }
[c1d9b2a]172
[a0c5f28]173 renderUI();
174 renderScene();
[0df3c9a]175 }
[c1c2021]176
177 vkDeviceWaitIdle(device);
[0df3c9a]178}
179
[a0c5f28]180void VulkanGame::renderUI() {
181 SDL_RenderClear(renderer);
182 SDL_RenderPresent(renderer);
183}
184
185void VulkanGame::renderScene() {
186}
187
[99d44b2]188void VulkanGame::cleanup() {
[c1c2021]189 cleanupSwapChain();
190
[fa9fa1c]191 vkDestroyCommandPool(device, commandPool, nullptr);
[c1c2021]192 vkDestroyDevice(device, nullptr);
193 vkDestroySurfaceKHR(instance, surface, nullptr);
194
[c1d9b2a]195 if (ENABLE_VALIDATION_LAYERS) {
196 VulkanUtils::destroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
197 }
[c1c2021]198
[c1d9b2a]199 vkDestroyInstance(instance, nullptr);
200
201 SDL_DestroyRenderer(renderer);
202 renderer = nullptr;
203
[b6e60b4]204 gui->destroyWindow();
205 gui->shutdown();
[0df3c9a]206 delete gui;
[c1d9b2a]207}
208
209void VulkanGame::createVulkanInstance(const vector<const char*> &validationLayers) {
210 if (ENABLE_VALIDATION_LAYERS && !VulkanUtils::checkValidationLayerSupport(validationLayers)) {
211 throw runtime_error("validation layers requested, but not available!");
212 }
213
214 VkApplicationInfo appInfo = {};
215 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
216 appInfo.pApplicationName = "Vulkan Game";
217 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
218 appInfo.pEngineName = "No Engine";
219 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
220 appInfo.apiVersion = VK_API_VERSION_1_0;
221
222 VkInstanceCreateInfo createInfo = {};
223 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
224 createInfo.pApplicationInfo = &appInfo;
225
226 vector<const char*> extensions = gui->getRequiredExtensions();
227 if (ENABLE_VALIDATION_LAYERS) {
228 extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
229 }
230
231 createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
232 createInfo.ppEnabledExtensionNames = extensions.data();
233
234 cout << endl << "Extensions:" << endl;
235 for (const char* extensionName : extensions) {
236 cout << extensionName << endl;
237 }
238 cout << endl;
239
240 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
241 if (ENABLE_VALIDATION_LAYERS) {
242 createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
243 createInfo.ppEnabledLayerNames = validationLayers.data();
244
245 populateDebugMessengerCreateInfo(debugCreateInfo);
246 createInfo.pNext = &debugCreateInfo;
247 } else {
248 createInfo.enabledLayerCount = 0;
249
250 createInfo.pNext = nullptr;
251 }
252
253 if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
254 throw runtime_error("failed to create instance!");
255 }
256}
257
258void VulkanGame::setupDebugMessenger() {
259 if (!ENABLE_VALIDATION_LAYERS) return;
260
261 VkDebugUtilsMessengerCreateInfoEXT createInfo;
262 populateDebugMessengerCreateInfo(createInfo);
263
264 if (VulkanUtils::createDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
265 throw runtime_error("failed to set up debug messenger!");
266 }
267}
268
269void VulkanGame::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
270 createInfo = {};
271 createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
272 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;
273 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;
274 createInfo.pfnUserCallback = debugCallback;
275}
276
277VKAPI_ATTR VkBool32 VKAPI_CALL VulkanGame::debugCallback(
278 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
279 VkDebugUtilsMessageTypeFlagsEXT messageType,
280 const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
281 void* pUserData) {
282 cerr << "validation layer: " << pCallbackData->pMessage << endl;
283
284 return VK_FALSE;
285}
[90a424f]286
287void VulkanGame::createVulkanSurface() {
288 if (gui->createVulkanSurface(instance, &surface) == RTWO_ERROR) {
289 throw runtime_error("failed to create window surface!");
290 }
291}
292
[fe5c3ba]293void VulkanGame::pickPhysicalDevice(const vector<const char*>& deviceExtensions) {
[90a424f]294 uint32_t deviceCount = 0;
295 vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
296
297 if (deviceCount == 0) {
298 throw runtime_error("failed to find GPUs with Vulkan support!");
299 }
300
301 vector<VkPhysicalDevice> devices(deviceCount);
302 vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
303
304 cout << endl << "Graphics cards:" << endl;
305 for (const VkPhysicalDevice& device : devices) {
[fe5c3ba]306 if (isDeviceSuitable(device, deviceExtensions)) {
[90a424f]307 physicalDevice = device;
308 break;
309 }
310 }
311 cout << endl;
312
313 if (physicalDevice == VK_NULL_HANDLE) {
314 throw runtime_error("failed to find a suitable GPU!");
315 }
316}
317
[fa9fa1c]318bool VulkanGame::isDeviceSuitable(VkPhysicalDevice physicalDevice,
319 const vector<const char*>& deviceExtensions) {
[90a424f]320 VkPhysicalDeviceProperties deviceProperties;
[fa9fa1c]321 vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
[90a424f]322
323 cout << "Device: " << deviceProperties.deviceName << endl;
324
[fa9fa1c]325 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface);
326 bool extensionsSupported = VulkanUtils::checkDeviceExtensionSupport(physicalDevice, deviceExtensions);
[90a424f]327 bool swapChainAdequate = false;
328
329 if (extensionsSupported) {
[fa9fa1c]330 SwapChainSupportDetails swapChainSupport = VulkanUtils::querySwapChainSupport(physicalDevice, surface);
[90a424f]331 swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
332 }
333
334 VkPhysicalDeviceFeatures supportedFeatures;
[fa9fa1c]335 vkGetPhysicalDeviceFeatures(physicalDevice, &supportedFeatures);
[90a424f]336
337 return indices.isComplete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy;
[c1c2021]338}
339
340void VulkanGame::createLogicalDevice(
341 const vector<const char*> validationLayers,
342 const vector<const char*>& deviceExtensions) {
343 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface);
344
345 vector<VkDeviceQueueCreateInfo> queueCreateInfos;
346 set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
347
348 float queuePriority = 1.0f;
349 for (uint32_t queueFamily : uniqueQueueFamilies) {
350 VkDeviceQueueCreateInfo queueCreateInfo = {};
351 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
352 queueCreateInfo.queueFamilyIndex = queueFamily;
353 queueCreateInfo.queueCount = 1;
354 queueCreateInfo.pQueuePriorities = &queuePriority;
355
356 queueCreateInfos.push_back(queueCreateInfo);
357 }
358
359 VkPhysicalDeviceFeatures deviceFeatures = {};
360 deviceFeatures.samplerAnisotropy = VK_TRUE;
361
362 VkDeviceCreateInfo createInfo = {};
363 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
364 createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
365 createInfo.pQueueCreateInfos = queueCreateInfos.data();
366
367 createInfo.pEnabledFeatures = &deviceFeatures;
368
369 createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
370 createInfo.ppEnabledExtensionNames = deviceExtensions.data();
371
372 // These fields are ignored by up-to-date Vulkan implementations,
373 // but it's a good idea to set them for backwards compatibility
374 if (ENABLE_VALIDATION_LAYERS) {
375 createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
376 createInfo.ppEnabledLayerNames = validationLayers.data();
377 } else {
378 createInfo.enabledLayerCount = 0;
379 }
380
381 if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
382 throw runtime_error("failed to create logical device!");
383 }
384
385 vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
386 vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
[502bd0b]387}
388
389void VulkanGame::createSwapChain() {
390 SwapChainSupportDetails swapChainSupport = VulkanUtils::querySwapChainSupport(physicalDevice, surface);
391
392 VkSurfaceFormatKHR surfaceFormat = VulkanUtils::chooseSwapSurfaceFormat(swapChainSupport.formats);
393 VkPresentModeKHR presentMode = VulkanUtils::chooseSwapPresentMode(swapChainSupport.presentModes);
394 VkExtent2D extent = VulkanUtils::chooseSwapExtent(swapChainSupport.capabilities, gui->getWindowWidth(), gui->getWindowHeight());
395
396 uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
397 if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
398 imageCount = swapChainSupport.capabilities.maxImageCount;
399 }
400
401 VkSwapchainCreateInfoKHR createInfo = {};
402 createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
403 createInfo.surface = surface;
404 createInfo.minImageCount = imageCount;
405 createInfo.imageFormat = surfaceFormat.format;
406 createInfo.imageColorSpace = surfaceFormat.colorSpace;
407 createInfo.imageExtent = extent;
408 createInfo.imageArrayLayers = 1;
409 createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
410
411 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface);
412 uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };
413
414 if (indices.graphicsFamily != indices.presentFamily) {
415 createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
416 createInfo.queueFamilyIndexCount = 2;
417 createInfo.pQueueFamilyIndices = queueFamilyIndices;
[f94eea9]418 } else {
[502bd0b]419 createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
420 createInfo.queueFamilyIndexCount = 0;
421 createInfo.pQueueFamilyIndices = nullptr;
422 }
423
424 createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
425 createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
426 createInfo.presentMode = presentMode;
427 createInfo.clipped = VK_TRUE;
428 createInfo.oldSwapchain = VK_NULL_HANDLE;
429
430 if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
431 throw runtime_error("failed to create swap chain!");
432 }
433
434 vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
435 swapChainImages.resize(imageCount);
436 vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());
437
438 swapChainImageFormat = surfaceFormat.format;
[771b33a]439 viewport = { 0, 0, (int)extent.width, (int)extent.height };
[f94eea9]440}
441
442void VulkanGame::createImageViews() {
443 swapChainImageViews.resize(swapChainImages.size());
444
445 for (size_t i = 0; i < swapChainImages.size(); i++) {
446 swapChainImageViews[i] = VulkanUtils::createImageView(device, swapChainImages[i], swapChainImageFormat,
447 VK_IMAGE_ASPECT_COLOR_BIT);
448 }
449}
450
[6fc24c7]451void VulkanGame::createRenderPass() {
452 VkAttachmentDescription colorAttachment = {};
453 colorAttachment.format = swapChainImageFormat;
454 colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
455 colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
456 colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
457 colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
458 colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
459 colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
460 colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
461
462 VkAttachmentReference colorAttachmentRef = {};
463 colorAttachmentRef.attachment = 0;
464 colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
465
466 VkAttachmentDescription depthAttachment = {};
467 depthAttachment.format = findDepthFormat();
468 depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
469 depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
470 depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
471 depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
472 depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
473 depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
474 depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
475
476 VkAttachmentReference depthAttachmentRef = {};
477 depthAttachmentRef.attachment = 1;
478 depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
479
480 VkSubpassDescription subpass = {};
481 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
482 subpass.colorAttachmentCount = 1;
483 subpass.pColorAttachments = &colorAttachmentRef;
484 subpass.pDepthStencilAttachment = &depthAttachmentRef;
485
486 VkSubpassDependency dependency = {};
487 dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
488 dependency.dstSubpass = 0;
489 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
490 dependency.srcAccessMask = 0;
491 dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
492 dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
493
494 array<VkAttachmentDescription, 2> attachments = { colorAttachment, depthAttachment };
495 VkRenderPassCreateInfo renderPassInfo = {};
496 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
497 renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
498 renderPassInfo.pAttachments = attachments.data();
499 renderPassInfo.subpassCount = 1;
500 renderPassInfo.pSubpasses = &subpass;
501 renderPassInfo.dependencyCount = 1;
502 renderPassInfo.pDependencies = &dependency;
503
504 if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
505 throw runtime_error("failed to create render pass!");
506 }
507}
508
509VkFormat VulkanGame::findDepthFormat() {
510 return VulkanUtils::findSupportedFormat(
511 physicalDevice,
512 { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
513 VK_IMAGE_TILING_OPTIMAL,
514 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
515 );
516}
517
[fa9fa1c]518void VulkanGame::createCommandPool() {
519 QueueFamilyIndices queueFamilyIndices = VulkanUtils::findQueueFamilies(physicalDevice, surface);;
520
521 VkCommandPoolCreateInfo poolInfo = {};
522 poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
523 poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
524 poolInfo.flags = 0;
525
526 if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
527 throw runtime_error("failed to create graphics command pool!");
528 }
529}
530
[f94eea9]531void VulkanGame::cleanupSwapChain() {
[6fc24c7]532 vkDestroyRenderPass(device, renderPass, nullptr);
533
[f94eea9]534 for (auto imageView : swapChainImageViews) {
535 vkDestroyImageView(device, imageView, nullptr);
536 }
537
538 vkDestroySwapchainKHR(device, swapChain, nullptr);
[90a424f]539}
Note: See TracBrowser for help on using the repository browser.