21 log(
"Creating Swapchain");
22 VkSurfaceCapabilitiesKHR capabilities;
23 if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_r_context.physicalDevice, m_r_context.surface, &capabilities) != VK_SUCCESS) {
28 vkGetPhysicalDeviceSurfaceFormatsKHR(m_r_context.physicalDevice, m_r_context.surface, &formatCount,
nullptr);
29 if (formatCount == 0) {
32 std::vector<VkSurfaceFormatKHR> formats(formatCount);
33 vkGetPhysicalDeviceSurfaceFormatsKHR(m_r_context.physicalDevice, m_r_context.surface, &formatCount, formats.data());
35 uint32_t presentModeCount;
36 vkGetPhysicalDeviceSurfacePresentModesKHR(m_r_context.physicalDevice, m_r_context.surface, &presentModeCount,
nullptr);
37 if (presentModeCount == 0) {
41 std::vector<VkPresentModeKHR> presentModes(presentModeCount);
42 vkGetPhysicalDeviceSurfacePresentModesKHR(m_r_context.physicalDevice, m_r_context.surface, &presentModeCount, presentModes.data());
48 VkFormatProperties formatProps;
49 vkGetPhysicalDeviceFormatProperties(m_r_context.physicalDevice, surfaceFormat.format, &formatProps);
51 uint32_t imageCount = capabilities.minImageCount + 1;
52 if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) {
53 imageCount = capabilities.maxImageCount;
56 m_r_context.MAX_FRAMES_IN_FLIGHT = imageCount;
57 VkSwapchainKHR oldSwapchain = m_r_context.swapchain;
59 VkSwapchainCreateInfoKHR createInfo = {};
60 createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
61 createInfo.surface = m_r_context.surface;
62 createInfo.minImageCount = imageCount;
63 createInfo.imageFormat = surfaceFormat.format;
64 createInfo.imageColorSpace = surfaceFormat.colorSpace;
65 createInfo.imageExtent = extent;
66 createInfo.imageArrayLayers = 1;
67 createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
69 uint32_t queueFamilyIndices[] = {m_r_context.graphicsQueueFamily, m_r_context.presentQueueFamily};
70 if (m_r_context.graphicsQueueFamily != m_r_context.presentQueueFamily) {
71 createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
72 createInfo.queueFamilyIndexCount = 2;
73 createInfo.pQueueFamilyIndices = queueFamilyIndices;
75 createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
76 createInfo.queueFamilyIndexCount = 0;
77 createInfo.pQueueFamilyIndices =
nullptr;
80 createInfo.preTransform = capabilities.currentTransform;
81 createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
82 createInfo.presentMode = presentMode;
83 createInfo.clipped = VK_TRUE;
84 createInfo.oldSwapchain = oldSwapchain;
86 VkSwapchainKHR newSwapchain;
87 if (vkCreateSwapchainKHR(m_r_context.device, &createInfo,
nullptr, &newSwapchain) != VK_SUCCESS)
92 if (oldSwapchain != VK_NULL_HANDLE)
94 vkDestroySwapchainKHR(m_r_context.device, oldSwapchain,
nullptr);
97 m_r_context.swapchain = newSwapchain;
98 vkGetSwapchainImagesKHR(m_r_context.device, m_r_context.swapchain, &imageCount,
nullptr);
99 m_r_context.swapchainImages.resize(imageCount);
100 vkGetSwapchainImagesKHR(m_r_context.device, m_r_context.swapchain, &imageCount, m_r_context.swapchainImages.data());
102 m_r_context.swapchainImageFormat = surfaceFormat.format;
103 m_r_context.swapchainExtent = extent;
105 for (
auto &view : m_r_context.swapchainImageViews)
107 if (view != VK_NULL_HANDLE)
108 vkDestroyImageView(m_r_context.device, view,
nullptr);
110 m_r_context.swapchainImageViews.clear();
114 if (m_r_context.commandPools.empty()) {
118 VkCommandBuffer cmd = m_r_context.beginSingleTimeCommands();
120 for (
auto& image : m_r_context.swapchainImages) {
121 VkImageMemoryBarrier barrier{};
122 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
123 barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
124 barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
125 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
126 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
127 barrier.image = image;
128 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
129 barrier.subresourceRange.levelCount = 1;
130 barrier.subresourceRange.layerCount = 1;
132 vkCmdPipelineBarrier(
134 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
135 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
143 m_r_context.endSingleTimeCommands(cmd);
147 if (m_r_context.depthImage != VK_NULL_HANDLE) {
148 vmaDestroyImage(m_r_context.allocator, m_r_context.depthImage, m_r_context.depthAllocation);
149 m_r_context.depthImage = VK_NULL_HANDLE;
150 m_r_context.depthAllocation = VK_NULL_HANDLE;
152 if (m_r_context.depthImageView != VK_NULL_HANDLE) {
153 vkDestroyImageView(m_r_context.device, m_r_context.depthImageView,
nullptr);
154 m_r_context.depthImageView = VK_NULL_HANDLE;
157 log(
"Creating depth resources...");
161 VkImageCreateInfo imageInfo{};
162 imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
163 imageInfo.imageType = VK_IMAGE_TYPE_2D;
164 imageInfo.extent = {std::max(m_r_context.swapchainExtent.width, m_r_context.currentRenderResolution.x), std::max(m_r_context.swapchainExtent.height, m_r_context.currentRenderResolution.y), 1};
165 imageInfo.mipLevels = 1;
166 imageInfo.arrayLayers = 1;
167 imageInfo.format = depthFormat;
168 imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
169 imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
170 imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
171 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
172 imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
174 VmaAllocationCreateInfo allocInfo{};
175 allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
177 if (vmaCreateImage(m_r_context.allocator, &imageInfo, &allocInfo,
178 &m_r_context.depthImage, &m_r_context.depthAllocation,
nullptr) != VK_SUCCESS) {
182 VkImageViewCreateInfo viewInfo{};
183 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
184 viewInfo.image = m_r_context.depthImage;
185 viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
186 viewInfo.format = depthFormat;
187 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
188 viewInfo.subresourceRange.baseMipLevel = 0;
189 viewInfo.subresourceRange.levelCount = 1;
190 viewInfo.subresourceRange.baseArrayLayer = 0;
191 viewInfo.subresourceRange.layerCount = 1;
193 if (vkCreateImageView(m_r_context.device, &viewInfo,
nullptr, &m_r_context.depthImageView) != VK_SUCCESS) {
197 m_r_context.depthFormat = depthFormat;
282 if (!m_r_context.imageAvailableSemaphores.empty())
return;
284 log(
"Creating synchronization objects...");
286 m_r_context.imageAvailableSemaphores.resize(m_r_context.MAX_FRAMES_IN_FLIGHT);
287 m_r_context.renderFinishedSemaphores.resize(m_r_context.MAX_FRAMES_IN_FLIGHT);
288 m_r_context.inFlightFences.resize(m_r_context.MAX_FRAMES_IN_FLIGHT);
290 VkSemaphoreCreateInfo semaphoreInfo = {};
291 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
293 VkFenceCreateInfo fenceInfo = {};
294 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
295 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
299 for (
size_t i = 0; i < m_r_context.MAX_FRAMES_IN_FLIGHT; i++) {
300 result = vkCreateSemaphore(m_r_context.device, &semaphoreInfo,
nullptr, &m_r_context.imageAvailableSemaphores[i]);
301 if (result != VK_SUCCESS) {
302 throw_error(
"Failed to create image available semaphore");
305 result = vkCreateSemaphore(m_r_context.device, &semaphoreInfo,
nullptr, &m_r_context.renderFinishedSemaphores[i]);
306 if (result != VK_SUCCESS) {
307 throw_error(
"Failed to create render finished semaphore");
310 result = vkCreateFence(m_r_context.device, &fenceInfo,
nullptr, &m_r_context.inFlightFences[i]);
311 if (result != VK_SUCCESS) {
315 assert(m_r_context.inFlightFences[i] != VK_NULL_HANDLE);
317 log(
"Created sync objects: fence=%p", (
void*)m_r_context.inFlightFences[i]);
320 if (m_r_context.depthImageView) {
323 log(LogLevel::WARNING,
324 "Deferring low-res resource creation - depth image not ready");
329 if (m_r_context.currentRenderResolution.x == 0 || m_r_context.currentRenderResolution.y == 0) {
330 log(LogLevel::ERROR,
"Invalid render resolution for low-res resources");
336 VkImageCreateInfo imageInfo{};
337 imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
338 imageInfo.imageType = VK_IMAGE_TYPE_2D;
339 imageInfo.extent = {m_r_context.currentRenderResolution.x, m_r_context.currentRenderResolution.y, 1};
340 imageInfo.mipLevels = 1;
341 imageInfo.arrayLayers = 1;
342 imageInfo.format = m_r_context.swapchainImageFormat;
343 imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
344 imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
345 imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
346 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
348 VmaAllocationCreateInfo allocInfo{};
349 allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
351 if (vmaCreateImage(m_r_context.allocator, &imageInfo, &allocInfo,
352 &m_r_context.lowResColorImage, &m_r_context.lowResColorAlloc,
nullptr) != VK_SUCCESS) {
353 log(LogLevel::ERROR,
"Failed to create low-res color image");
357 VkImageViewCreateInfo viewInfo{};
358 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
359 viewInfo.image = m_r_context.lowResColorImage;
360 viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
361 viewInfo.format = m_r_context.swapchainImageFormat;
362 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
363 viewInfo.subresourceRange.levelCount = 1;
364 viewInfo.subresourceRange.layerCount = 1;
366 if (vkCreateImageView(m_r_context.device, &viewInfo,
nullptr, &m_r_context.lowResColorView) != VK_SUCCESS) {
367 log(LogLevel::ERROR,
"Failed to create low-res color image view");
368 vmaDestroyImage(m_r_context.allocator, m_r_context.lowResColorImage, m_r_context.lowResColorAlloc);
369 m_r_context.lowResColorImage = VK_NULL_HANDLE;
370 m_r_context.lowResColorAlloc = VK_NULL_HANDLE;
374 if (vmaCreateImage(m_r_context.allocator, &imageInfo, &allocInfo,
375 &m_r_context.uiImage, &m_r_context.uiAlloc,
nullptr) != VK_SUCCESS) {
376 log(LogLevel::ERROR,
"Failed to create ui image");
380 VkImageViewCreateInfo uiViewInfo = viewInfo;
381 uiViewInfo.image = m_r_context.uiImage;
383 if (vkCreateImageView(m_r_context.device, &uiViewInfo,
nullptr, &m_r_context.uiView) != VK_SUCCESS) {
384 log(LogLevel::ERROR,
"Failed to create ui image view");
385 vmaDestroyImage(m_r_context.allocator, m_r_context.uiImage, m_r_context.uiAlloc);
386 m_r_context.uiImage = VK_NULL_HANDLE;
387 m_r_context.uiAlloc = VK_NULL_HANDLE;
391 VkImageCreateInfo accumInfo = imageInfo;
392 accumInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
393 if(vmaCreateImage(m_r_context.allocator, &accumInfo, &allocInfo, &m_r_context.accumImage, &m_r_context.accumAlloc,
nullptr) != VK_SUCCESS) {
394 log(LogLevel::ERROR,
"Failed to create accum image");
395 vmaDestroyImage(m_r_context.allocator, m_r_context.accumImage, m_r_context.accumAlloc);
396 m_r_context.accumImage = VK_NULL_HANDLE;
397 m_r_context.accumAlloc = VK_NULL_HANDLE;
401 VkImageViewCreateInfo accumViewInfo = viewInfo;
402 accumViewInfo.image = m_r_context.accumImage;
403 accumViewInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
404 if(vkCreateImageView(m_r_context.device, &accumViewInfo,
nullptr, &m_r_context.accumView) != VK_SUCCESS) {
405 log(LogLevel::ERROR,
"Failed to create accum image view");
406 vmaDestroyImage(m_r_context.allocator, m_r_context.accumImage, m_r_context.accumAlloc);
407 m_r_context.accumImage = VK_NULL_HANDLE;
408 m_r_context.accumAlloc = VK_NULL_HANDLE;
412 VkImageCreateInfo revealInfo = imageInfo;
413 revealInfo.format = VK_FORMAT_R8_UNORM;
414 if(vmaCreateImage(m_r_context.allocator, &revealInfo, &allocInfo, &m_r_context.revealImage, &m_r_context.revealAlloc,
nullptr) != VK_SUCCESS) {
415 log(LogLevel::ERROR,
"Failed to create reveal image");
416 vmaDestroyImage(m_r_context.allocator, m_r_context.revealImage, m_r_context.revealAlloc);
417 m_r_context.revealImage = VK_NULL_HANDLE;
418 m_r_context.revealAlloc = VK_NULL_HANDLE;
422 VkImageViewCreateInfo revealViewInfo = viewInfo;
423 revealViewInfo.image = m_r_context.revealImage;
424 revealViewInfo.format = VK_FORMAT_R8_UNORM;
425 if(vkCreateImageView(m_r_context.device, &revealViewInfo,
nullptr, &m_r_context.revealView) != VK_SUCCESS) {
426 log(LogLevel::ERROR,
"Failed to create reveal image view");
427 vmaDestroyImage(m_r_context.allocator, m_r_context.revealImage, m_r_context.revealAlloc);
428 m_r_context.revealImage = VK_NULL_HANDLE;
429 m_r_context.revealAlloc = VK_NULL_HANDLE;
434 VkImageCreateInfo compositeInfo = imageInfo;
435 compositeInfo.mipLevels = 3;
436 compositeInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
437 if(vmaCreateImage(m_r_context.allocator, &compositeInfo, &allocInfo, &m_r_context.compositeImage, &m_r_context.compositeAlloc,
nullptr) != VK_SUCCESS) {
438 log(LogLevel::ERROR,
"Failed to create composite image");
442 VkImageViewCreateInfo compositeViewInfo = viewInfo;
443 compositeViewInfo.image = m_r_context.compositeImage;
444 compositeViewInfo.subresourceRange.levelCount = 3;
445 if(vkCreateImageView(m_r_context.device, &compositeViewInfo,
nullptr, &m_r_context.compositeView) != VK_SUCCESS) {
446 log(LogLevel::ERROR,
"Failed to create composite image view");
450 VkImageCreateInfo gameViewInfo = imageInfo;
451 gameViewInfo.format = m_r_context.swapchainImageFormat;
452 gameViewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
453 vmaCreateImage(m_r_context.allocator, &gameViewInfo, &allocInfo, &m_r_context.gameViewImage, &m_r_context.gameViewAlloc,
nullptr);
455 VkImageViewCreateInfo gameViewViewInfo = viewInfo;
456 gameViewViewInfo.image = m_r_context.gameViewImage;
457 gameViewViewInfo.format = m_r_context.swapchainImageFormat;
458 vkCreateImageView(m_r_context.device, &gameViewViewInfo,
nullptr, &m_r_context.gameViewView);
460 m_r_context.lowResColorFormat = m_r_context.swapchainImageFormat;
465 if (m_r_context.compositeView != VK_NULL_HANDLE) {
466 vkDestroyImageView(m_r_context.device, m_r_context.compositeView,
nullptr);
467 m_r_context.compositeView = VK_NULL_HANDLE;
469 if (m_r_context.compositeImage != VK_NULL_HANDLE && m_r_context.compositeAlloc != VK_NULL_HANDLE) {
470 vmaDestroyImage(m_r_context.allocator, m_r_context.compositeImage, m_r_context.compositeAlloc);
471 m_r_context.compositeImage = VK_NULL_HANDLE;
472 m_r_context.compositeAlloc = VK_NULL_HANDLE;
474if (m_r_context.lowResColorView != VK_NULL_HANDLE) {
475 vkDestroyImageView(m_r_context.device, m_r_context.lowResColorView,
nullptr);
476 m_r_context.lowResColorView = VK_NULL_HANDLE;
479 if (m_r_context.lowResColorImage != VK_NULL_HANDLE && m_r_context.lowResColorAlloc != VK_NULL_HANDLE) {
480 vmaDestroyImage(m_r_context.allocator, m_r_context.lowResColorImage, m_r_context.lowResColorAlloc);
481 m_r_context.lowResColorImage = VK_NULL_HANDLE;
482 m_r_context.lowResColorAlloc = VK_NULL_HANDLE;
485 if (m_r_context.uiView != VK_NULL_HANDLE) {
486 vkDestroyImageView(m_r_context.device, m_r_context.uiView,
nullptr);
487 m_r_context.uiView = VK_NULL_HANDLE;
490 if (m_r_context.uiImage != VK_NULL_HANDLE && m_r_context.uiAlloc != VK_NULL_HANDLE) {
491 vmaDestroyImage(m_r_context.allocator, m_r_context.uiImage, m_r_context.uiAlloc);
492 m_r_context.uiImage = VK_NULL_HANDLE;
493 m_r_context.uiAlloc = VK_NULL_HANDLE;
496 if(m_r_context.accumView != VK_NULL_HANDLE) {
497 vkDestroyImageView(m_r_context.device, m_r_context.accumView,
nullptr);
498 m_r_context.accumView = VK_NULL_HANDLE;
500 if(m_r_context.accumImage != VK_NULL_HANDLE && m_r_context.accumAlloc != VK_NULL_HANDLE) {
501 vmaDestroyImage(m_r_context.allocator, m_r_context.accumImage, m_r_context.accumAlloc);
502 m_r_context.accumImage = VK_NULL_HANDLE;
503 m_r_context.accumAlloc = VK_NULL_HANDLE;
506 if(m_r_context.revealView != VK_NULL_HANDLE) {
507 vkDestroyImageView(m_r_context.device, m_r_context.revealView,
nullptr);
508 m_r_context.revealView = VK_NULL_HANDLE;
510 if(m_r_context.revealImage != VK_NULL_HANDLE && m_r_context.revealAlloc != VK_NULL_HANDLE) {
511 vmaDestroyImage(m_r_context.allocator, m_r_context.revealImage, m_r_context.revealAlloc);
512 m_r_context.revealImage = VK_NULL_HANDLE;
513 m_r_context.revealAlloc = VK_NULL_HANDLE;
516 if(m_r_context.gameViewView != VK_NULL_HANDLE) {
517 vkDestroyImageView(m_r_context.device, m_r_context.gameViewView,
nullptr);
518 m_r_context.gameViewView = VK_NULL_HANDLE;
520 if(m_r_context.gameViewImage != VK_NULL_HANDLE && m_r_context.gameViewAlloc != VK_NULL_HANDLE) {
521 vmaDestroyImage(m_r_context.allocator, m_r_context.gameViewImage, m_r_context.gameViewAlloc);
522 m_r_context.gameViewImage = VK_NULL_HANDLE;
523 m_r_context.gameViewAlloc = VK_NULL_HANDLE;
Struct holding all vulkan data, like device, surface, swapchain, images, views, and more.