Changeset ce9dc9f in opengl-game
- Timestamp:
- Jan 24, 2021, 6:15:32 PM (4 years ago)
- Branches:
- feature/imgui-sdl
- Children:
- 8b823e7
- Parents:
- 3f32dfd
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
IMGUI/imgui_impl_vulkan.cpp
r3f32dfd rce9dc9f 103 103 void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator); 104 104 void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator); 105 void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); 105 106 void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator); 106 107 … … 894 895 IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE); 895 896 IM_ASSERT(info->Device != VK_NULL_HANDLE); 897 IM_ASSERT(info->Queue != VK_NULL_HANDLE); 896 898 IM_ASSERT(info->DescriptorPool != VK_NULL_HANDLE); 897 899 IM_ASSERT(info->MinImageCount >= 2); … … 1070 1072 } 1071 1073 1074 // Also destroy old swap chain and in-flight frames data, if any. 1075 void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count) 1076 { 1077 VkResult err; 1078 VkSwapchainKHR old_swapchain = wd->Swapchain; 1079 wd->Swapchain = NULL; 1080 err = vkDeviceWaitIdle(device); 1081 check_vk_result(err); 1082 1083 // We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one. 1084 // Destroy old Framebuffer 1085 for (uint32_t i = 0; i < wd->ImageCount; i++) 1086 { 1087 ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); 1088 ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator); 1089 } 1090 IM_FREE(wd->Frames); 1091 IM_FREE(wd->FrameSemaphores); 1092 wd->Frames = NULL; 1093 wd->FrameSemaphores = NULL; 1094 wd->ImageCount = 0; 1095 if (wd->RenderPass) 1096 vkDestroyRenderPass(device, wd->RenderPass, allocator); 1097 if (wd->Pipeline) 1098 vkDestroyPipeline(device, wd->Pipeline, allocator); 1099 1100 // If min image count was not specified, request different count of images dependent on selected present mode 1101 if (min_image_count == 0) 1102 min_image_count = ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(wd->PresentMode); 1103 1104 // Create Swapchain 1105 { 1106 VkSwapchainCreateInfoKHR info = {}; 1107 info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 1108 info.surface = wd->Surface; 1109 info.minImageCount = min_image_count; 1110 info.imageFormat = wd->SurfaceFormat.format; 1111 info.imageColorSpace = wd->SurfaceFormat.colorSpace; 1112 info.imageArrayLayers = 1; 1113 info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 1114 info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family 1115 info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 1116 info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 1117 info.presentMode = wd->PresentMode; 1118 info.clipped = VK_TRUE; 1119 info.oldSwapchain = old_swapchain; 1120 VkSurfaceCapabilitiesKHR cap; 1121 err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap); 1122 check_vk_result(err); 1123 if (info.minImageCount < cap.minImageCount) 1124 info.minImageCount = cap.minImageCount; 1125 else if (cap.maxImageCount != 0 && info.minImageCount > cap.maxImageCount) 1126 info.minImageCount = cap.maxImageCount; 1127 1128 if (cap.currentExtent.width == 0xffffffff) 1129 { 1130 info.imageExtent.width = wd->Width = w; 1131 info.imageExtent.height = wd->Height = h; 1132 } 1133 else 1134 { 1135 info.imageExtent.width = wd->Width = cap.currentExtent.width; 1136 info.imageExtent.height = wd->Height = cap.currentExtent.height; 1137 } 1138 err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain); 1139 check_vk_result(err); 1140 err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, NULL); 1141 check_vk_result(err); 1142 VkImage backbuffers[16] = {}; 1143 IM_ASSERT(wd->ImageCount >= min_image_count); 1144 IM_ASSERT(wd->ImageCount < IM_ARRAYSIZE(backbuffers)); 1145 err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers); 1146 check_vk_result(err); 1147 1148 IM_ASSERT(wd->Frames == NULL); 1149 wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount); 1150 wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount); 1151 memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount); 1152 memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->ImageCount); 1153 for (uint32_t i = 0; i < wd->ImageCount; i++) 1154 wd->Frames[i].Backbuffer = backbuffers[i]; 1155 } 1156 if (old_swapchain) 1157 vkDestroySwapchainKHR(device, old_swapchain, allocator); 1158 1159 // Create the Render Pass 1160 { 1161 VkAttachmentDescription attachment = {}; 1162 attachment.format = wd->SurfaceFormat.format; 1163 attachment.samples = VK_SAMPLE_COUNT_1_BIT; 1164 attachment.loadOp = wd->ClearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1165 attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 1166 attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1167 attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1168 attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 1169 attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 1170 VkAttachmentReference color_attachment = {}; 1171 color_attachment.attachment = 0; 1172 color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1173 VkSubpassDescription subpass = {}; 1174 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 1175 subpass.colorAttachmentCount = 1; 1176 subpass.pColorAttachments = &color_attachment; 1177 VkSubpassDependency dependency = {}; 1178 dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 1179 dependency.dstSubpass = 0; 1180 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1181 dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1182 dependency.srcAccessMask = 0; 1183 dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 1184 VkRenderPassCreateInfo info = {}; 1185 info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 1186 info.attachmentCount = 1; 1187 info.pAttachments = &attachment; 1188 info.subpassCount = 1; 1189 info.pSubpasses = &subpass; 1190 info.dependencyCount = 1; 1191 info.pDependencies = &dependency; 1192 err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass); 1193 check_vk_result(err); 1194 1195 // We do not create a pipeline by default as this is also used by examples' main.cpp, 1196 // but secondary viewport in multi-viewport mode may want to create one with: 1197 //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline); 1198 } 1199 1200 // Create The Image Views 1201 { 1202 VkImageViewCreateInfo info = {}; 1203 info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 1204 info.viewType = VK_IMAGE_VIEW_TYPE_2D; 1205 info.format = wd->SurfaceFormat.format; 1206 info.components.r = VK_COMPONENT_SWIZZLE_R; 1207 info.components.g = VK_COMPONENT_SWIZZLE_G; 1208 info.components.b = VK_COMPONENT_SWIZZLE_B; 1209 info.components.a = VK_COMPONENT_SWIZZLE_A; 1210 VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 1211 info.subresourceRange = image_range; 1212 for (uint32_t i = 0; i < wd->ImageCount; i++) 1213 { 1214 ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i]; 1215 info.image = fd->Backbuffer; 1216 err = vkCreateImageView(device, &info, allocator, &fd->BackbufferView); 1217 check_vk_result(err); 1218 } 1219 } 1220 1221 // Create Framebuffer 1222 { 1223 VkImageView attachment[1]; 1224 VkFramebufferCreateInfo info = {}; 1225 info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 1226 info.renderPass = wd->RenderPass; 1227 info.attachmentCount = 1; 1228 info.pAttachments = attachment; 1229 info.width = wd->Width; 1230 info.height = wd->Height; 1231 info.layers = 1; 1232 for (uint32_t i = 0; i < wd->ImageCount; i++) 1233 { 1234 ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i]; 1235 attachment[0] = fd->BackbufferView; 1236 err = vkCreateFramebuffer(device, &info, allocator, &fd->Framebuffer); 1237 check_vk_result(err); 1238 } 1239 } 1240 } 1241 1242 // Create or resize window 1243 void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count) 1244 { 1245 (void)instance; 1246 ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count); 1247 ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator); 1248 } 1249 1072 1250 void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator) 1073 1251 { -
IMGUI/imgui_impl_vulkan.h
r3f32dfd rce9dc9f 32 32 VkPhysicalDevice PhysicalDevice; 33 33 VkDevice Device; 34 uint32_t QueueFamily; 35 VkQueue Queue; 34 36 VkPipelineCache PipelineCache; 35 37 VkDescriptorPool DescriptorPool; … … 71 73 72 74 // Helpers 75 IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); 73 76 IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator); 74 77 IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space); -
sdl-game.cpp
r3f32dfd rce9dc9f 1 1 #include "sdl-game.hpp" 2 2 3 #include <array> 3 4 #include <iostream> 4 5 #include <set> 5 6 #include <stdexcept> 6 7 8 #include <stdlib.h> // abort (only used in check_vk_result) 9 10 #include <SDL2/SDL_vulkan.h> 11 7 12 #include "IMGUI/imgui_impl_sdl.h" 8 13 9 #include <stdio.h> // printf, fprintf10 #include <stdlib.h> // abort11 12 // dear imgui: standalone example application for SDL2 + Vulkan13 // If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.14 15 // Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.16 // - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.17 // You will use those if you want to use this rendering back-end in your engine/app.18 // - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by19 // the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.20 // Read comments in imgui_impl_vulkan.h.21 22 #include <SDL2/SDL_vulkan.h>23 24 14 #include "logger.hpp" 25 15 26 #include "vulkan-utils.hpp"27 28 16 using namespace std; 29 17 30 //#define IMGUI_UNLIMITED_FRAME_RATE 31 32 static VkAllocationCallbacks* g_Allocator = NULL; 33 static VkInstance g_Instance = VK_NULL_HANDLE; 34 static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; 35 static VkDevice g_Device = VK_NULL_HANDLE; 36 static VkQueue g_GraphicsQueue = VK_NULL_HANDLE; 37 static VkQueue g_PresentQueue = VK_NULL_HANDLE; 38 static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; 39 40 static ImGui_ImplVulkanH_Window g_MainWindowData; 41 static uint32_t g_MinImageCount = 2; 42 static bool g_SwapChainRebuild = false; 43 44 static void check_vk_result(VkResult err) 45 { 46 if (err == 0) 18 #define IMGUI_UNLIMITED_FRAME_RATE 19 20 static bool g_SwapChainRebuild = false; 21 22 static void check_vk_result(VkResult err) { 23 if (err == 0) { 47 24 return; 25 } 48 26 fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err); 49 if (err < 0) 27 if (err < 0) { 50 28 abort(); 51 } 52 53 // All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo. 54 // Your real engine/app may not use them. 55 56 static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, SDL_Window* window) { 57 // TODO: SetupVulkanWIndow calls vkGetPhysicalDeviceSurfaceSupportKHR to get the present queue. In vulkan-game, I do this in findQueueFamilies. 58 int width, height; 59 SDL_GetWindowSize(window, &width, &height); 60 61 wd->Surface = surface; 62 63 // Select Surface Format 64 const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; 65 const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 66 wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); 67 68 // Select Present Mode 69 #ifdef IMGUI_UNLIMITED_FRAME_RATE 70 VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; 71 #else 72 VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; 73 #endif 74 wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes)); 75 //printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode); 76 77 // Create SwapChain, RenderPass, Framebuffer, etc. 78 IM_ASSERT(g_MinImageCount >= 2); 79 80 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(g_PhysicalDevice, surface); 81 82 ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, indices.graphicsFamily.value(), 83 g_Allocator, width, height, g_MinImageCount); 84 } 85 86 static void CleanupVulkanWindow() 87 { 88 ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator); 89 } 90 91 static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) 92 { 93 VkResult err; 94 95 VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; 96 VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; 97 err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); 98 if (err == VK_ERROR_OUT_OF_DATE_KHR) 99 { 29 } 30 } 31 32 void VulkanGame::FrameRender(ImDrawData* draw_data) { 33 VkResult result = vkAcquireNextImageKHR(device, swapChain, numeric_limits<uint64_t>::max(), 34 imageAcquiredSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); 35 36 if (result == VK_ERROR_OUT_OF_DATE_KHR) { 100 37 g_SwapChainRebuild = true; 101 38 return; 102 } 103 check_vk_result(err); 104 105 ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; 106 { 107 err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking 108 check_vk_result(err); 109 110 err = vkResetFences(g_Device, 1, &fd->Fence); 111 check_vk_result(err); 112 } 113 { 114 err = vkResetCommandPool(g_Device, fd->CommandPool, 0); 115 check_vk_result(err); 116 VkCommandBufferBeginInfo info = {}; 117 info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 118 info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 119 err = vkBeginCommandBuffer(fd->CommandBuffer, &info); 120 check_vk_result(err); 121 } 122 { 123 VkRenderPassBeginInfo info = {}; 124 info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 125 info.renderPass = wd->RenderPass; 126 info.framebuffer = fd->Framebuffer; 127 info.renderArea.extent.width = wd->Width; 128 info.renderArea.extent.height = wd->Height; 129 info.clearValueCount = 1; 130 info.pClearValues = &wd->ClearValue; 131 vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); 132 } 39 } else if (result != VK_SUCCESS) { 40 throw runtime_error("failed to acquire swap chain image!"); 41 } 42 43 if (vkWaitForFences(device, 1, &inFlightFences[imageIndex], VK_TRUE, numeric_limits<uint64_t>::max()) != VK_SUCCESS) { 44 throw runtime_error("failed waiting for fence!"); 45 } 46 if (vkResetFences(device, 1, &inFlightFences[imageIndex]) != VK_SUCCESS) { 47 throw runtime_error("failed to reset fence!"); 48 } 49 50 // START OF NEW CODE 51 // I don't have analogous code in vulkan-game right now because I record command buffers once 52 // before the render loop ever starts. I should change this 53 54 result = vkResetCommandPool(device, commandPools[imageIndex], 0); 55 check_vk_result(result); 56 VkCommandBufferBeginInfo info = {}; 57 info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 58 info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 59 result = vkBeginCommandBuffer(commandBuffers[imageIndex], &info); 60 check_vk_result(result); 61 62 VkRenderPassBeginInfo renderPassInfo = {}; 63 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 64 renderPassInfo.renderPass = renderPass; 65 renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex]; 66 renderPassInfo.renderArea.extent = swapChainExtent; 67 68 array<VkClearValue, 2> clearValues = {}; 69 clearValues[0].color = { { 0.45f, 0.55f, 0.60f, 1.00f } }; 70 clearValues[1].depthStencil = { 1.0f, 0 }; 71 72 renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size()); 73 renderPassInfo.pClearValues = clearValues.data(); 74 75 vkCmdBeginRenderPass(commandBuffers[imageIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); 133 76 134 77 // Record dear imgui primitives into command buffer 135 ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);78 ImGui_ImplVulkan_RenderDrawData(draw_data, commandBuffers[imageIndex]); 136 79 137 80 // Submit command buffer 138 vkCmdEndRenderPass(fd->CommandBuffer); 139 { 140 VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 141 VkSubmitInfo info = {}; 142 info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 143 info.waitSemaphoreCount = 1; 144 info.pWaitSemaphores = &image_acquired_semaphore; 145 info.pWaitDstStageMask = &wait_stage; 146 info.commandBufferCount = 1; 147 info.pCommandBuffers = &fd->CommandBuffer; 148 info.signalSemaphoreCount = 1; 149 info.pSignalSemaphores = &render_complete_semaphore; 150 151 err = vkEndCommandBuffer(fd->CommandBuffer); 152 check_vk_result(err); 153 err = vkQueueSubmit(g_GraphicsQueue, 1, &info, fd->Fence); 154 check_vk_result(err); 155 } 156 } 157 158 static void FramePresent(ImGui_ImplVulkanH_Window* wd) 159 { 81 vkCmdEndRenderPass(commandBuffers[imageIndex]); 82 83 if (vkEndCommandBuffer(commandBuffers[imageIndex]) != VK_SUCCESS) { 84 throw runtime_error("failed to record command buffer!"); 85 } 86 87 // END OF NEW CODE 88 89 VkSemaphore waitSemaphores[] = { imageAcquiredSemaphores[currentFrame] }; 90 VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 91 VkSemaphore signalSemaphores[] = { renderCompleteSemaphores[currentFrame] }; 92 93 VkSubmitInfo submitInfo = {}; 94 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 95 submitInfo.waitSemaphoreCount = 1; 96 submitInfo.pWaitSemaphores = waitSemaphores; 97 submitInfo.pWaitDstStageMask = &wait_stage; 98 submitInfo.commandBufferCount = 1; 99 submitInfo.pCommandBuffers = &commandBuffers[imageIndex]; 100 submitInfo.signalSemaphoreCount = 1; 101 submitInfo.pSignalSemaphores = signalSemaphores; 102 103 if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[imageIndex]) != VK_SUCCESS) { 104 throw runtime_error("failed to submit draw command buffer!"); 105 } 106 } 107 108 void VulkanGame::FramePresent() { 160 109 if (g_SwapChainRebuild) 161 110 return; 162 VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; 163 VkPresentInfoKHR info = {}; 164 info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 165 info.waitSemaphoreCount = 1; 166 info.pWaitSemaphores = &render_complete_semaphore; 167 info.swapchainCount = 1; 168 info.pSwapchains = &wd->Swapchain; 169 info.pImageIndices = &wd->FrameIndex; 170 VkResult err = vkQueuePresentKHR(g_PresentQueue, &info); 171 if (err == VK_ERROR_OUT_OF_DATE_KHR) 172 { 111 112 VkSemaphore signalSemaphores[] = { renderCompleteSemaphores[currentFrame] }; 113 114 VkPresentInfoKHR presentInfo = {}; 115 presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 116 presentInfo.waitSemaphoreCount = 1; 117 presentInfo.pWaitSemaphores = signalSemaphores; 118 presentInfo.swapchainCount = 1; 119 presentInfo.pSwapchains = &swapChain; 120 presentInfo.pImageIndices = &imageIndex; 121 presentInfo.pResults = nullptr; 122 123 VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo); 124 125 // In vulkan-game, I also handle VK_SUBOPTIMAL_KHR and framebufferResized. g_SwapChainRebuild is kind of similar 126 // to framebufferResized, but not quite the same 127 if (result == VK_ERROR_OUT_OF_DATE_KHR) { 173 128 g_SwapChainRebuild = true; 174 129 return; 175 } 176 check_vk_result(err); 177 wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores 130 } else if (result != VK_SUCCESS) { 131 throw runtime_error("failed to present swap chain image!"); 132 } 133 134 currentFrame = (currentFrame + 1) % swapChainImageCount; 178 135 } 179 136 … … 190 147 } 191 148 192 VulkanGame::VulkanGame(int maxFramesInFlight) : MAX_FRAMES_IN_FLIGHT(maxFramesInFlight) { 149 VulkanGame::VulkanGame() { 150 // TODO: Double-check whether initialization should happen in the header, where the variables are declared, or here 151 // Also, decide whether to use this-> for all instance variables, or only when necessary 152 153 this->debugMessenger = VK_NULL_HANDLE; 154 193 155 this->gui = nullptr; 194 156 this->window = nullptr; 157 158 this->swapChainPresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; 159 this->swapChainMinImageCount = 0; 195 160 } 196 161 … … 208 173 209 174 initVulkan(); 210 211 VkResult err;212 213 // Create Framebuffers214 ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;215 SetupVulkanWindow(wd, surface, window);216 175 217 176 // Create Descriptor Pool … … 237 196 pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); 238 197 pool_info.pPoolSizes = pool_sizes; 239 err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &descriptorPool); 240 check_vk_result(err); 241 } 198 check_vk_result(vkCreateDescriptorPool(device, &pool_info, nullptr, &descriptorPool)); 199 } 200 201 // TODO: Do this in one place and save it instead of redoing it every time I need a queue family index 202 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface); 242 203 243 204 // Setup Dear ImGui context 244 205 IMGUI_CHECKVERSION(); 245 206 ImGui::CreateContext(); 246 ImGuiIO& io = ImGui::GetIO(); (void)io;207 ImGuiIO& io = ImGui::GetIO(); 247 208 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls 248 209 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls … … 255 216 ImGui_ImplSDL2_InitForVulkan(window); 256 217 ImGui_ImplVulkan_InitInfo init_info = {}; 257 init_info.Instance = g_Instance; 258 init_info.PhysicalDevice = g_PhysicalDevice; 259 init_info.Device = g_Device; 260 init_info.PipelineCache = g_PipelineCache; 218 init_info.Instance = instance; 219 init_info.PhysicalDevice = physicalDevice; 220 init_info.Device = device; 221 init_info.QueueFamily = indices.graphicsFamily.value(); 222 init_info.Queue = graphicsQueue; 261 223 init_info.DescriptorPool = descriptorPool; 262 init_info.Allocator = g_Allocator;263 init_info.MinImageCount = g_MinImageCount;264 init_info.ImageCount = wd->ImageCount;224 init_info.Allocator = nullptr; 225 init_info.MinImageCount = swapChainMinImageCount; 226 init_info.ImageCount = swapChainImageCount; 265 227 init_info.CheckVkResultFn = check_vk_result; 266 ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);228 ImGui_ImplVulkan_Init(&init_info, renderPass); 267 229 268 230 // Load Fonts … … 279 241 //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); 280 242 //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); 281 // IM_ASSERT(font != NULL);243 //assert(font != NULL); 282 244 283 245 // Upload Fonts 284 246 { 285 // Use any command queue 286 VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool; 287 VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer; 288 289 err = vkResetCommandPool(g_Device, command_pool, 0); 290 check_vk_result(err); 291 VkCommandBufferBeginInfo begin_info = {}; 292 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 293 begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 294 err = vkBeginCommandBuffer(command_buffer, &begin_info); 295 check_vk_result(err); 296 297 ImGui_ImplVulkan_CreateFontsTexture(command_buffer); 298 299 VkSubmitInfo end_info = {}; 300 end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 301 end_info.commandBufferCount = 1; 302 end_info.pCommandBuffers = &command_buffer; 303 err = vkEndCommandBuffer(command_buffer); 304 check_vk_result(err); 305 err = vkQueueSubmit(graphicsQueue, 1, &end_info, VK_NULL_HANDLE); 306 check_vk_result(err); 307 308 err = vkDeviceWaitIdle(g_Device); 309 check_vk_result(err); 247 VkCommandBuffer commandBuffer = VulkanUtils::beginSingleTimeCommands(device, resourceCommandPool); 248 249 ImGui_ImplVulkan_CreateFontsTexture(commandBuffer); 250 251 VulkanUtils::endSingleTimeCommands(device, resourceCommandPool, commandBuffer, graphicsQueue); 252 310 253 ImGui_ImplVulkan_DestroyFontUploadObjects(); 311 254 } … … 314 257 bool show_demo_window = true; 315 258 bool show_another_window = false; 316 ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);317 259 318 260 // Main loop … … 337 279 int width, height; 338 280 SDL_GetWindowSize(window, &width, &height); 339 if (width > 0 && height > 0) 340 {341 ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);342 343 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(g_PhysicalDevice, surface);344 345 ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData,346 indices.graphicsFamily.value(), g_Allocator, width, height, g_MinImageCount); 347 g_MainWindowData.FrameIndex = 0;281 if (width > 0 && height > 0) { 282 // TODO: This should be used if the min image count changes, presumably because a new surface was created 283 // with a different image count or something like that. Maybe I want to add code to query for a new min image count 284 // during swapchain recreation to take advantage of this 285 ImGui_ImplVulkan_SetMinImageCount(swapChainMinImageCount); 286 287 recreateSwapChain(); 288 289 imageIndex = 0; 348 290 g_SwapChainRebuild = false; 349 291 } … … 361 303 // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. 362 304 { 363 static float f = 0.0f;364 305 static int counter = 0; 365 306 … … 369 310 ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state 370 311 ImGui::Checkbox("Another Window", &show_another_window); 371 372 ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f373 ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color374 312 375 313 if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) … … 396 334 ImDrawData* draw_data = ImGui::GetDrawData(); 397 335 const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); 398 if (!is_minimized) 399 { 400 memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); 401 FrameRender(wd, draw_data); 402 FramePresent(wd); 403 } 404 } 405 406 // Cleanup 407 err = vkDeviceWaitIdle(g_Device); 408 check_vk_result(err); 409 ImGui_ImplVulkan_Shutdown(); 410 ImGui_ImplSDL2_Shutdown(); 411 ImGui::DestroyContext(); 412 413 CleanupVulkanWindow(); 336 if (!is_minimized) { 337 FrameRender(draw_data); 338 FramePresent(); 339 } 340 } 341 414 342 cleanup(); 415 343 … … 481 409 pickPhysicalDevice(deviceExtensions); 482 410 createLogicalDevice(validationLayers, deviceExtensions); 411 chooseSwapChainProperties(); 412 createSwapChain(); 413 createImageViews(); 414 createRenderPass(); 415 createResourceCommandPool(); 416 417 createCommandPools(); 418 419 VulkanUtils::createDepthImage(device, physicalDevice, resourceCommandPool, findDepthFormat(), swapChainExtent, 420 depthImage, graphicsQueue); 421 422 createFramebuffers(); 423 424 // TODO: Initialize pipelines here 425 426 createCommandBuffers(); 427 428 createSyncObjects(); 483 429 } 484 430 485 431 void VulkanGame::cleanup() { 486 vkDestroyDescriptorPool(g_Device, descriptorPool, g_Allocator); 432 // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals) 433 //vkQueueWaitIdle(g_Queue); 434 if (vkDeviceWaitIdle(device) != VK_SUCCESS) { 435 throw runtime_error("failed to wait for device!"); 436 } 437 438 ImGui_ImplVulkan_Shutdown(); 439 ImGui_ImplSDL2_Shutdown(); 440 ImGui::DestroyContext(); 441 442 cleanupSwapChain(); 443 444 // this would actually be destroyed in the pipeline class 445 vkDestroyDescriptorPool(device, descriptorPool, nullptr); 446 447 vkDestroyCommandPool(device, resourceCommandPool, nullptr); 448 449 vkDestroyDevice(device, nullptr); 450 vkDestroySurfaceKHR(instance, surface, nullptr); 487 451 488 452 if (ENABLE_VALIDATION_LAYERS) { 489 VulkanUtils::destroyDebugUtilsMessengerEXT(g_Instance, debugMessenger, nullptr); 490 } 491 492 vkDestroyDevice(g_Device, g_Allocator); 493 vkDestroyInstance(g_Instance, g_Allocator); 453 VulkanUtils::destroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); 454 } 455 456 vkDestroyInstance(instance, nullptr); 494 457 495 458 gui->destroyWindow(); … … 536 499 populateDebugMessengerCreateInfo(debugCreateInfo); 537 500 createInfo.pNext = &debugCreateInfo; 538 } else { 501 } 502 else { 539 503 createInfo.enabledLayerCount = 0; 540 504 … … 542 506 } 543 507 544 if (vkCreateInstance(&createInfo, nullptr, & g_Instance) != VK_SUCCESS) {508 if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { 545 509 throw runtime_error("failed to create instance!"); 546 510 } … … 555 519 populateDebugMessengerCreateInfo(createInfo); 556 520 557 if (VulkanUtils::createDebugUtilsMessengerEXT( g_Instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {521 if (VulkanUtils::createDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { 558 522 throw runtime_error("failed to set up debug messenger!"); 559 523 } … … 569 533 570 534 void VulkanGame::createVulkanSurface() { 571 if (gui->createVulkanSurface( g_Instance, &surface) == RTWO_ERROR) {535 if (gui->createVulkanSurface(instance, &surface) == RTWO_ERROR) { 572 536 throw runtime_error("failed to create window surface!"); 573 537 } … … 577 541 uint32_t deviceCount = 0; 578 542 // TODO: Check VkResult 579 vkEnumeratePhysicalDevices( g_Instance, &deviceCount, nullptr);543 vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); 580 544 581 545 if (deviceCount == 0) { … … 585 549 vector<VkPhysicalDevice> devices(deviceCount); 586 550 // TODO: Check VkResult 587 vkEnumeratePhysicalDevices( g_Instance, &deviceCount, devices.data());551 vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); 588 552 589 553 cout << endl << "Graphics cards:" << endl; 590 554 for (const VkPhysicalDevice& device : devices) { 591 555 if (isDeviceSuitable(device, deviceExtensions)) { 592 g_PhysicalDevice = device;556 physicalDevice = device; 593 557 break; 594 558 } … … 596 560 cout << endl; 597 561 598 if ( g_PhysicalDevice == VK_NULL_HANDLE) {562 if (physicalDevice == VK_NULL_HANDLE) { 599 563 throw runtime_error("failed to find a suitable GPU!"); 600 564 } … … 612 576 613 577 if (extensionsSupported) { 614 SwapChainSupportDetails swapChainSupport = VulkanUtils::querySwapChainSupport(physicalDevice, surface); 615 swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); 578 vector<VkSurfaceFormatKHR> formats = VulkanUtils::querySwapChainFormats(physicalDevice, surface); 579 vector<VkPresentModeKHR> presentModes = VulkanUtils::querySwapChainPresentModes(physicalDevice, surface); 580 581 swapChainAdequate = !formats.empty() && !presentModes.empty(); 616 582 } 617 583 … … 623 589 624 590 void VulkanGame::createLogicalDevice(const vector<const char*>& validationLayers, 625 626 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies( g_PhysicalDevice, surface);591 const vector<const char*>& deviceExtensions) { 592 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface); 627 593 628 594 if (!indices.isComplete()) { … … 666 632 createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); 667 633 createInfo.ppEnabledLayerNames = validationLayers.data(); 668 } else { 634 } 635 else { 669 636 createInfo.enabledLayerCount = 0; 670 637 } 671 638 672 if (vkCreateDevice( g_PhysicalDevice, &createInfo, nullptr, &g_Device) != VK_SUCCESS) {639 if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { 673 640 throw runtime_error("failed to create logical device!"); 674 641 } 675 642 676 vkGetDeviceQueue(g_Device, indices.graphicsFamily.value(), 0, &graphicsQueue); 677 vkGetDeviceQueue(g_Device, indices.presentFamily.value(), 0, &presentQueue); 678 679 g_GraphicsQueue = graphicsQueue; 680 g_PresentQueue = presentQueue; 643 vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); 644 vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue); 645 } 646 647 void VulkanGame::chooseSwapChainProperties() { 648 vector<VkSurfaceFormatKHR> availableFormats = VulkanUtils::querySwapChainFormats(physicalDevice, surface); 649 vector<VkPresentModeKHR> availablePresentModes = VulkanUtils::querySwapChainPresentModes(physicalDevice, surface); 650 651 // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation 652 // Assuming that the default behavior is without setting this bit, there is no need for separate Swapchain image and image view format 653 // Additionally several new color spaces were introduced with Vulkan Spec v1.0.40, 654 // hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used. 655 swapChainSurfaceFormat = VulkanUtils::chooseSwapSurfaceFormat(availableFormats, 656 { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }, 657 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR); 658 659 #ifdef IMGUI_UNLIMITED_FRAME_RATE 660 vector<VkPresentModeKHR> presentModes{ 661 VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR 662 }; 663 #else 664 vector<VkPresentModeKHR> presentModes{ VK_PRESENT_MODE_FIFO_KHR }; 665 #endif 666 667 swapChainPresentMode = VulkanUtils::chooseSwapPresentMode(availablePresentModes, presentModes); 668 669 cout << "[vulkan] Selected PresentMode = " << swapChainPresentMode << endl; 670 671 VkSurfaceCapabilitiesKHR capabilities = VulkanUtils::querySwapChainCapabilities(physicalDevice, surface); 672 673 // If min image count was not specified, request different count of images dependent on selected present mode 674 if (swapChainMinImageCount == 0) { 675 if (swapChainPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { 676 swapChainMinImageCount = 3; 677 } 678 else if (swapChainPresentMode == VK_PRESENT_MODE_FIFO_KHR || swapChainPresentMode == VK_PRESENT_MODE_FIFO_RELAXED_KHR) { 679 swapChainMinImageCount = 2; 680 } 681 else if (swapChainPresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) { 682 swapChainMinImageCount = 1; 683 } 684 else { 685 throw runtime_error("unexpected present mode!"); 686 } 687 } 688 689 if (swapChainMinImageCount < capabilities.minImageCount) { 690 swapChainMinImageCount = capabilities.minImageCount; 691 } 692 else if (capabilities.maxImageCount != 0 && swapChainMinImageCount > capabilities.maxImageCount) { 693 swapChainMinImageCount = capabilities.maxImageCount; 694 } 695 } 696 697 void VulkanGame::createSwapChain() { 698 VkSurfaceCapabilitiesKHR capabilities = VulkanUtils::querySwapChainCapabilities(physicalDevice, surface); 699 700 swapChainExtent = VulkanUtils::chooseSwapExtent(capabilities, gui->getWindowWidth(), gui->getWindowHeight()); 701 702 VkSwapchainCreateInfoKHR createInfo = {}; 703 createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 704 createInfo.surface = surface; 705 createInfo.minImageCount = swapChainMinImageCount; 706 createInfo.imageFormat = swapChainSurfaceFormat.format; 707 createInfo.imageColorSpace = swapChainSurfaceFormat.colorSpace; 708 createInfo.imageExtent = swapChainExtent; 709 createInfo.imageArrayLayers = 1; 710 createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 711 712 // TODO: Maybe save this result so I don't have to recalculate it every time 713 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface); 714 uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() }; 715 716 if (indices.graphicsFamily != indices.presentFamily) { 717 createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; 718 createInfo.queueFamilyIndexCount = 2; 719 createInfo.pQueueFamilyIndices = queueFamilyIndices; 720 } 721 else { 722 createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 723 createInfo.queueFamilyIndexCount = 0; 724 createInfo.pQueueFamilyIndices = nullptr; 725 } 726 727 createInfo.preTransform = capabilities.currentTransform; 728 createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 729 createInfo.presentMode = swapChainPresentMode; 730 createInfo.clipped = VK_TRUE; 731 createInfo.oldSwapchain = VK_NULL_HANDLE; 732 733 if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) { 734 throw runtime_error("failed to create swap chain!"); 735 } 736 737 if (vkGetSwapchainImagesKHR(device, swapChain, &swapChainImageCount, nullptr) != VK_SUCCESS) { 738 throw runtime_error("failed to get swap chain image count!"); 739 } 740 741 swapChainImages.resize(swapChainImageCount); 742 if (vkGetSwapchainImagesKHR(device, swapChain, &swapChainImageCount, swapChainImages.data()) != VK_SUCCESS) { 743 throw runtime_error("failed to get swap chain images!"); 744 } 745 } 746 747 void VulkanGame::createImageViews() { 748 swapChainImageViews.resize(swapChainImageCount); 749 750 for (uint32_t i = 0; i < swapChainImageViews.size(); i++) { 751 swapChainImageViews[i] = VulkanUtils::createImageView(device, swapChainImages[i], swapChainSurfaceFormat.format, 752 VK_IMAGE_ASPECT_COLOR_BIT); 753 } 754 } 755 756 void VulkanGame::createRenderPass() { 757 VkAttachmentDescription colorAttachment = {}; 758 colorAttachment.format = swapChainSurfaceFormat.format; 759 colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; 760 colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Set to VK_ATTACHMENT_LOAD_OP_DONT_CARE to disable clearing 761 colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 762 colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 763 colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 764 colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 765 colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 766 767 VkAttachmentReference colorAttachmentRef = {}; 768 colorAttachmentRef.attachment = 0; 769 colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 770 771 VkAttachmentDescription depthAttachment = {}; 772 depthAttachment.format = findDepthFormat(); 773 depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; 774 depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 775 depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 776 depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 777 depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 778 depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 779 depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 780 781 VkAttachmentReference depthAttachmentRef = {}; 782 depthAttachmentRef.attachment = 1; 783 depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 784 785 VkSubpassDescription subpass = {}; 786 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 787 subpass.colorAttachmentCount = 1; 788 subpass.pColorAttachments = &colorAttachmentRef; 789 //subpass.pDepthStencilAttachment = &depthAttachmentRef; 790 791 VkSubpassDependency dependency = {}; 792 dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 793 dependency.dstSubpass = 0; 794 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 795 dependency.srcAccessMask = 0; 796 dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 797 dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 798 799 array<VkAttachmentDescription, 2> attachments = { colorAttachment, depthAttachment }; 800 VkRenderPassCreateInfo renderPassInfo = {}; 801 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 802 renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size()); 803 renderPassInfo.pAttachments = attachments.data(); 804 renderPassInfo.subpassCount = 1; 805 renderPassInfo.pSubpasses = &subpass; 806 renderPassInfo.dependencyCount = 1; 807 renderPassInfo.pDependencies = &dependency; 808 809 if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { 810 throw runtime_error("failed to create render pass!"); 811 } 812 813 // We do not create a pipeline by default as this is also used by examples' main.cpp, 814 // but secondary viewport in multi-viewport mode may want to create one with: 815 //ImGui_ImplVulkan_CreatePipeline(device, g_Allocator, VK_NULL_HANDLE, g_MainWindowData.RenderPass, VK_SAMPLE_COUNT_1_BIT, &g_MainWindowData.Pipeline); 816 } 817 818 VkFormat VulkanGame::findDepthFormat() { 819 return VulkanUtils::findSupportedFormat( 820 physicalDevice, 821 { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT }, 822 VK_IMAGE_TILING_OPTIMAL, 823 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT 824 ); 825 } 826 827 void VulkanGame::createResourceCommandPool() { 828 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface); 829 830 VkCommandPoolCreateInfo poolInfo = {}; 831 poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 832 poolInfo.queueFamilyIndex = indices.graphicsFamily.value(); 833 poolInfo.flags = 0; 834 835 if (vkCreateCommandPool(device, &poolInfo, nullptr, &resourceCommandPool) != VK_SUCCESS) { 836 throw runtime_error("failed to create resource command pool!"); 837 } 838 } 839 840 void VulkanGame::createCommandPools() { 841 commandPools.resize(swapChainImageCount); 842 843 QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface); 844 845 for (size_t i = 0; i < swapChainImageCount; i++) { 846 VkCommandPoolCreateInfo poolInfo = {}; 847 poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 848 poolInfo.queueFamilyIndex = indices.graphicsFamily.value(); 849 poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; 850 if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPools[i]) != VK_SUCCESS) { 851 throw runtime_error("failed to create graphics command pool!"); 852 } 853 } 854 } 855 856 void VulkanGame::createFramebuffers() { 857 swapChainFramebuffers.resize(swapChainImageCount); 858 859 VkFramebufferCreateInfo framebufferInfo = {}; 860 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 861 framebufferInfo.renderPass = renderPass; 862 framebufferInfo.width = swapChainExtent.width; 863 framebufferInfo.height = swapChainExtent.height; 864 framebufferInfo.layers = 1; 865 866 for (size_t i = 0; i < swapChainImageCount; i++) { 867 array<VkImageView, 2> attachments = { 868 swapChainImageViews[i], 869 depthImage.imageView 870 }; 871 872 framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size()); 873 framebufferInfo.pAttachments = attachments.data(); 874 875 if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) { 876 throw runtime_error("failed to create framebuffer!"); 877 } 878 } 879 } 880 881 void VulkanGame::createCommandBuffers() { 882 commandBuffers.resize(swapChainImageCount); 883 884 for (size_t i = 0; i < swapChainImageCount; i++) { 885 VkCommandBufferAllocateInfo allocInfo = {}; 886 allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 887 allocInfo.commandPool = commandPools[i]; 888 allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 889 allocInfo.commandBufferCount = 1; 890 891 if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffers[i]) != VK_SUCCESS) { 892 throw runtime_error("failed to allocate command buffers!"); 893 } 894 } 895 } 896 897 void VulkanGame::createSyncObjects() { 898 imageAcquiredSemaphores.resize(swapChainImageCount); 899 renderCompleteSemaphores.resize(swapChainImageCount); 900 inFlightFences.resize(swapChainImageCount); 901 902 VkSemaphoreCreateInfo semaphoreInfo = {}; 903 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 904 905 VkFenceCreateInfo fenceInfo = {}; 906 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 907 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; 908 909 for (size_t i = 0; i < swapChainImageCount; i++) { 910 if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAcquiredSemaphores[i]) != VK_SUCCESS) { 911 throw runtime_error("failed to create image acquired sempahore for a frame!"); 912 } 913 914 if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderCompleteSemaphores[i]) != VK_SUCCESS) { 915 throw runtime_error("failed to create render complete sempahore for a frame!"); 916 } 917 918 if (vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) { 919 throw runtime_error("failed to create fence for a frame!"); 920 } 921 } 922 } 923 924 void VulkanGame::recreateSwapChain() { 925 if (vkDeviceWaitIdle(device) != VK_SUCCESS) { 926 throw runtime_error("failed to wait for device!"); 927 } 928 929 cleanupSwapChain(); 930 931 createSwapChain(); 932 createImageViews(); 933 createRenderPass(); 934 935 createCommandPools(); 936 937 // The depth buffer does need to be recreated with the swap chain since its dimensions depend on the window size 938 // and resizing the window is a common reason to recreate the swapchain 939 VulkanUtils::createDepthImage(device, physicalDevice, resourceCommandPool, findDepthFormat(), swapChainExtent, 940 depthImage, graphicsQueue); 941 942 createFramebuffers(); 943 944 // TODO: Update pipelines here 945 946 createCommandBuffers(); 947 948 createSyncObjects(); 949 } 950 951 void VulkanGame::cleanupSwapChain() { 952 VulkanUtils::destroyVulkanImage(device, depthImage); 953 954 for (VkFramebuffer framebuffer : swapChainFramebuffers) { 955 vkDestroyFramebuffer(device, framebuffer, nullptr); 956 } 957 958 for (uint32_t i = 0; i < swapChainImageCount; i++) { 959 vkFreeCommandBuffers(device, commandPools[i], 1, &commandBuffers[i]); 960 vkDestroyCommandPool(device, commandPools[i], nullptr); 961 } 962 963 for (uint32_t i = 0; i < swapChainImageCount; i++) { 964 vkDestroySemaphore(device, imageAcquiredSemaphores[i], nullptr); 965 vkDestroySemaphore(device, renderCompleteSemaphores[i], nullptr); 966 vkDestroyFence(device, inFlightFences[i], nullptr); 967 } 968 969 vkDestroyRenderPass(device, renderPass, nullptr); 970 971 for (VkImageView imageView : swapChainImageViews) { 972 vkDestroyImageView(device, imageView, nullptr); 973 } 974 975 vkDestroySwapchainKHR(device, swapChain, nullptr); 681 976 } 682 977 683 978 /********************************************** END OF NEW CODE **********************************************/ 684 685 /********************************************** START TEMP HELPER GUNVTIONS **********************************/686 687 // Forward Declarations688 void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd,689 const VkAllocationCallbacks* allocator);690 void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd,691 const VkAllocationCallbacks* allocator);692 void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device,693 ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);694 695 // Create or resize window696 void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device,697 ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width,698 int height, uint32_t min_image_count) {699 (void)instance;700 ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count);701 ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);702 }703 704 // Also destroy old swap chain and in-flight frames data, if any.705 void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device,706 ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count) {707 VkResult err;708 VkSwapchainKHR old_swapchain = wd->Swapchain;709 wd->Swapchain = NULL;710 err = vkDeviceWaitIdle(device);711 check_vk_result(err);712 713 // We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.714 // Destroy old Framebuffer715 for (uint32_t i = 0; i < wd->ImageCount; i++) {716 ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);717 ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);718 }719 IM_FREE(wd->Frames);720 IM_FREE(wd->FrameSemaphores);721 wd->Frames = NULL;722 wd->FrameSemaphores = NULL;723 wd->ImageCount = 0;724 if (wd->RenderPass) {725 vkDestroyRenderPass(device, wd->RenderPass, allocator);726 }727 if (wd->Pipeline) {728 vkDestroyPipeline(device, wd->Pipeline, allocator);729 }730 731 // If min image count was not specified, request different count of images dependent on selected present mode732 if (min_image_count == 0) {733 min_image_count = ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(wd->PresentMode);734 }735 736 // Create Swapchain737 {738 VkSwapchainCreateInfoKHR info = {};739 info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;740 info.surface = wd->Surface;741 info.minImageCount = min_image_count;742 info.imageFormat = wd->SurfaceFormat.format;743 info.imageColorSpace = wd->SurfaceFormat.colorSpace;744 info.imageArrayLayers = 1;745 info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;746 info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family747 info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;748 info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;749 info.presentMode = wd->PresentMode;750 info.clipped = VK_TRUE;751 info.oldSwapchain = old_swapchain;752 VkSurfaceCapabilitiesKHR cap;753 err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);754 check_vk_result(err);755 if (info.minImageCount < cap.minImageCount) {756 info.minImageCount = cap.minImageCount;757 } else if (cap.maxImageCount != 0 && info.minImageCount > cap.maxImageCount) {758 info.minImageCount = cap.maxImageCount;759 }760 761 if (cap.currentExtent.width == 0xffffffff) {762 info.imageExtent.width = wd->Width = w;763 info.imageExtent.height = wd->Height = h;764 } else {765 info.imageExtent.width = wd->Width = cap.currentExtent.width;766 info.imageExtent.height = wd->Height = cap.currentExtent.height;767 }768 err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain);769 check_vk_result(err);770 err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, NULL);771 check_vk_result(err);772 VkImage backbuffers[16] = {};773 IM_ASSERT(wd->ImageCount >= min_image_count);774 IM_ASSERT(wd->ImageCount < IM_ARRAYSIZE(backbuffers));775 err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);776 check_vk_result(err);777 778 IM_ASSERT(wd->Frames == NULL);779 wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount);780 wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount);781 memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);782 memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->ImageCount);783 for (uint32_t i = 0; i < wd->ImageCount; i++) {784 wd->Frames[i].Backbuffer = backbuffers[i];785 }786 }787 if (old_swapchain) {788 vkDestroySwapchainKHR(device, old_swapchain, allocator);789 }790 791 // Create the Render Pass792 {793 VkAttachmentDescription attachment = {};794 attachment.format = wd->SurfaceFormat.format;795 attachment.samples = VK_SAMPLE_COUNT_1_BIT;796 attachment.loadOp = wd->ClearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;797 attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;798 attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;799 attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;800 attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;801 attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;802 VkAttachmentReference color_attachment = {};803 color_attachment.attachment = 0;804 color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;805 VkSubpassDescription subpass = {};806 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;807 subpass.colorAttachmentCount = 1;808 subpass.pColorAttachments = &color_attachment;809 VkSubpassDependency dependency = {};810 dependency.srcSubpass = VK_SUBPASS_EXTERNAL;811 dependency.dstSubpass = 0;812 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;813 dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;814 dependency.srcAccessMask = 0;815 dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;816 VkRenderPassCreateInfo info = {};817 info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;818 info.attachmentCount = 1;819 info.pAttachments = &attachment;820 info.subpassCount = 1;821 info.pSubpasses = &subpass;822 info.dependencyCount = 1;823 info.pDependencies = &dependency;824 err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass);825 check_vk_result(err);826 827 // We do not create a pipeline by default as this is also used by examples' main.cpp,828 // but secondary viewport in multi-viewport mode may want to create one with:829 //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline);830 }831 832 // Create The Image Views833 {834 VkImageViewCreateInfo info = {};835 info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;836 info.viewType = VK_IMAGE_VIEW_TYPE_2D;837 info.format = wd->SurfaceFormat.format;838 info.components.r = VK_COMPONENT_SWIZZLE_R;839 info.components.g = VK_COMPONENT_SWIZZLE_G;840 info.components.b = VK_COMPONENT_SWIZZLE_B;841 info.components.a = VK_COMPONENT_SWIZZLE_A;842 VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };843 info.subresourceRange = image_range;844 for (uint32_t i = 0; i < wd->ImageCount; i++) {845 ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];846 info.image = fd->Backbuffer;847 err = vkCreateImageView(device, &info, allocator, &fd->BackbufferView);848 check_vk_result(err);849 }850 }851 852 // Create Framebuffer853 {854 VkImageView attachment[1];855 VkFramebufferCreateInfo info = {};856 info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;857 info.renderPass = wd->RenderPass;858 info.attachmentCount = 1;859 info.pAttachments = attachment;860 info.width = wd->Width;861 info.height = wd->Height;862 info.layers = 1;863 for (uint32_t i = 0; i < wd->ImageCount; i++) {864 ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];865 attachment[0] = fd->BackbufferView;866 err = vkCreateFramebuffer(device, &info, allocator, &fd->Framebuffer);867 check_vk_result(err);868 }869 }870 }871 872 /*********************************************** END TEMP HELPER GUNVTIONS ***********************************/ -
sdl-game.hpp
r3f32dfd rce9dc9f 3 3 4 4 #include <vector> 5 6 5 #include <vulkan/vulkan.h> 7 6 8 7 #include <SDL2/SDL.h> 9 10 8 #include "IMGUI/imgui_impl_vulkan.h" 11 9 12 10 #include "consts.hpp" 11 #include "vulkan-utils.hpp" 13 12 14 13 #include "game-gui-sdl.hpp" … … 26 25 class VulkanGame { 27 26 public: 28 VulkanGame( int maxFramesInFlight);27 VulkanGame(); 29 28 ~VulkanGame(); 30 29 31 void run(int width, int height, unsigned char guiFlags); // Mostly example code30 void run(int width, int height, unsigned char guiFlags); 32 31 33 32 private: … … 38 37 void* pUserData); 39 38 40 // TODO: Make these consts static41 // Also, maybe move them into consts.hpp42 43 const int MAX_FRAMES_IN_FLIGHT; // Unused right now44 45 39 // TODO: Good place to start using smart pointers 46 40 GameGui* gui; … … 49 43 SDL_Window* window; 50 44 45 VkInstance instance; 51 46 VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; 52 47 VkSurfaceKHR surface; // TODO: Change the variable name to vulkanSurface 48 VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; 49 VkDevice device; 53 50 54 51 VkQueue graphicsQueue; 55 52 VkQueue presentQueue; 56 53 54 // TODO: Maybe make a swapchain struct for convenience 55 VkSurfaceFormatKHR swapChainSurfaceFormat; 56 VkPresentModeKHR swapChainPresentMode; 57 VkExtent2D swapChainExtent; 58 uint32_t swapChainMinImageCount; 59 uint32_t swapChainImageCount; 60 61 VkSwapchainKHR swapChain; 62 vector<VkImage> swapChainImages; 63 vector<VkImageView> swapChainImageViews; 64 vector<VkFramebuffer> swapChainFramebuffers; 65 66 VkRenderPass renderPass; 67 68 VkCommandPool resourceCommandPool; 69 70 vector<VkCommandPool> commandPools; 71 vector<VkCommandBuffer> commandBuffers; 72 73 VulkanImage depthImage; 74 75 // These are per frame 76 vector<VkSemaphore> imageAcquiredSemaphores; 77 vector<VkSemaphore> renderCompleteSemaphores; 78 79 // These are per swap chain image 80 vector<VkFence> inFlightFences; 81 82 uint32_t imageIndex; 83 uint32_t currentFrame; 84 57 85 // My code, but not complete. Skips creating the SDL renderer, probably because it doesn't use hardware acceleration. 58 86 // I should try to get uncapped framerate and compare performance w/ and w/out an SDL renderer … … 65 93 void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo); 66 94 void createVulkanSurface(); 67 void pickPhysicalDevice(const vector<const char*>& deviceExtensions); // Double-check, but it should be a copy of my code. Still uses g_Instance and g_Physical device though95 void pickPhysicalDevice(const vector<const char*>& deviceExtensions); 68 96 bool isDeviceSuitable(VkPhysicalDevice physicalDevice, const vector<const char*>& deviceExtensions); 69 97 void createLogicalDevice(const vector<const char*>& validationLayers, 70 const vector<const char*>& deviceExtensions); // Only creates the graphics queue. Later, checks that this queue also supports presenting, but this codebase does not seem to support a separate present queue 98 const vector<const char*>& deviceExtensions); 99 void chooseSwapChainProperties(); 100 void createSwapChain(); 101 void createImageViews(); 102 void createRenderPass(); 103 VkFormat findDepthFormat(); // TODO: Declare/define (in the cpp file) this function in some util functions section 104 void createResourceCommandPool(); 105 void createCommandPools(); 106 void createFramebuffers(); 107 void createCommandBuffers(); 108 void createSyncObjects(); 109 110 void recreateSwapChain(); 111 112 void cleanupSwapChain(); 71 113 72 114 // Pipeline variables. Hopefully, I can eventually use the GraphicsPipeline_Vulkan class for the imgui pipeline 73 115 VkDescriptorPool descriptorPool; 74 116 117 // Helper methods from imgui_impl_vulkan that were moved into VulkanGame to give them access to class instance variables 118 public: 119 void FrameRender(ImDrawData* draw_data); 120 void FramePresent(); 121 75 122 }; 76 123 77 // These functions are helper functions that were used in the ImGui Vulkan+SDL example78 79 void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device,80 ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h,81 uint32_t min_image_count);82 83 void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device,84 ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);85 86 // End helper functions87 88 124 #endif // _SDL_GAME_H -
vulkan-game.cpp
r3f32dfd rce9dc9f 293 293 check_vk_result(err); 294 294 295 err = vkDeviceWaitIdle(this->device); 296 check_vk_result(err); 295 if (vkDeviceWaitIdle(this->device) != VK_SUCCESS) { 296 throw runtime_error("failed to wait for device!"); 297 } 298 297 299 ImGui_ImplVulkan_DestroyFontUploadObjects(); 298 300 … … 1193 1195 1194 1196 void VulkanGame::cleanup() { 1195 // TODO: Should probably check the returned result 1196 vkDeviceWaitIdle(device); 1197 if (vkDeviceWaitIdle(device) != VK_SUCCESS) { 1198 throw runtime_error("failed to wait for device!"); 1199 } 1197 1200 1198 1201 ImGui_ImplVulkan_Shutdown(); … … 2120 2123 } 2121 2124 2122 vkDeviceWaitIdle(device); 2125 if (vkDeviceWaitIdle(device) != VK_SUCCESS) { 2126 throw runtime_error("failed to wait for device!"); 2127 } 2123 2128 2124 2129 cleanupSwapChain();
Note:
See TracChangeset
for help on using the changeset viewer.