Renderer.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  1. #include "Renderer.h"
  2. #include "Config.h"
  3. #include "FileSystem.h"
  4. #include "Logging.h"
  5. #include "RendererVK.h"
  6. #include "Path.h"
  7. #include "Window.h"
  8. #include "WindowingGLFW.h"
  9. #include "imgui_impl_vulkan.h"
  10. #include <vector>
  11. namespace gameplay
  12. {
  13. struct RenderFrame
  14. {
  15. VkCommandPool commandPool = VK_NULL_HANDLE;
  16. VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
  17. VkFence fence = VK_NULL_HANDLE;
  18. VkImage backbuffer = VK_NULL_HANDLE;
  19. VkImageView backbufferView = VK_NULL_HANDLE;
  20. VkFramebuffer framebuffer = VK_NULL_HANDLE;
  21. VkSemaphore imageAcquiredSemaphore = VK_NULL_HANDLE;
  22. VkSemaphore renderCompleteSemaphore = VK_NULL_HANDLE;
  23. };
  24. struct Renderer::Impl
  25. {
  26. bool validation = false;
  27. uint32_t minImageCount = 2;
  28. GLFWwindow* glfwWindow = nullptr;
  29. VkAllocationCallbacks* allocator = nullptr;
  30. VkDebugReportCallbackEXT debugReport = nullptr;
  31. VkInstance instance = VK_NULL_HANDLE;
  32. VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
  33. VkPhysicalDeviceProperties physicalDeviceProperties = {};
  34. VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties = {};
  35. VkDevice device = VK_NULL_HANDLE;
  36. std::vector<VkQueueFamilyProperties> queueFamilyProperties;
  37. struct
  38. {
  39. uint32_t present = 0;
  40. uint32_t graphics = 0;
  41. uint32_t compute = 0;
  42. uint32_t transfer = 0;
  43. } queueFamilyIndices;
  44. VkQueue queue = VK_NULL_HANDLE;
  45. int surfaceWidth = 0;
  46. int surfaceHeight = 0;
  47. VkSurfaceKHR surface = VK_NULL_HANDLE;
  48. VkSurfaceFormatKHR surfaceFormat;
  49. VkColorSpaceKHR colorSpace;
  50. VkSwapchainKHR swapchain = VK_NULL_HANDLE;
  51. VkPresentModeKHR presentMode;
  52. VkRenderPass renderPass = VK_NULL_HANDLE;
  53. VkPipeline pipeline = VK_NULL_HANDLE;
  54. bool clearEnable = true;
  55. VkClearValue clearValue = {};
  56. uint32_t frameIndex = 0;
  57. uint32_t semaphoreIndex = 0;
  58. VkFormat imageFormat;
  59. uint32_t imageCount = 0;
  60. std::vector<RenderFrame> frames;
  61. VkPipelineCache pipelineCache = VK_NULL_HANDLE;
  62. VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
  63. bool rebuildSwapchain = false;
  64. void startup_vulkan();
  65. void shutdown_vulkan();
  66. void startup_window_surface();
  67. void shutdown_window_surface();
  68. void create_or_resize_window_swapchain();
  69. void destroy_render_frame(RenderFrame* renderFrame);
  70. uint32_t get_queue_family_index(VkQueueFlagBits queueFlags);
  71. VkBool32 is_device_extension_present(VkPhysicalDevice physicalDevice, const char* extensionName);
  72. VkSurfaceFormatKHR select_surface_format(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, const VkFormat* requestFormats, int requestFormatCount, VkColorSpaceKHR requestColorSpace);
  73. VkPresentModeKHR select_present_mode(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, const VkPresentModeKHR* requestModes, int requestModeCount);
  74. uint32_t get_image_count_for_present_mode(VkPresentModeKHR present_mode);
  75. void next_frame();
  76. void present_frame();
  77. void startup_imgui();
  78. void shutdow_imgui();
  79. void render_imgui();
  80. };
  81. Renderer::Renderer()
  82. {
  83. _impl = new Renderer::Impl();
  84. auto config = App::get_app()->get_config();
  85. _impl->validation = config->set_bool("graphics.validation", false);
  86. _impl->minImageCount = (uint32_t)config->set_int("graphics.minImageCount", 2);
  87. }
  88. Renderer::~Renderer()
  89. {
  90. GP_SAFE_DELETE(_impl);
  91. }
  92. void Renderer::startup()
  93. {
  94. if (!glfwVulkanSupported())
  95. {
  96. GP_LOG_ERROR("GLFW: Vulkan Not Supported");
  97. }
  98. _impl->startup_vulkan();
  99. _impl->startup_window_surface();
  100. _impl->startup_imgui();
  101. }
  102. void Renderer::Impl::startup_vulkan()
  103. {
  104. load_vulkan_library();
  105. std::vector<const char*> instanceExtension;
  106. // get the required surface extensions from glfw
  107. uint32_t glfwExtensionCount = 0;
  108. const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
  109. for ( uint32_t i = 0; i < glfwExtensionCount; i++)
  110. {
  111. instanceExtension.push_back(glfwExtensions[i]);
  112. }
  113. // initialize the vulkan application
  114. auto fs = App::get_app()->get_file_system();
  115. std::string appName = Path(fs->get_app_executable_path()).get_stem();
  116. VkApplicationInfo appInfo = {};
  117. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  118. appInfo.pApplicationName = appName.c_str();
  119. appInfo.pEngineName = appName.c_str();
  120. appInfo.apiVersion = VK_API_VERSION_1_0;
  121. // create the vulkan instance
  122. VkInstanceCreateInfo instanceCreateInfo = {};
  123. instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  124. instanceCreateInfo.pNext = nullptr;
  125. instanceCreateInfo.pApplicationInfo = &appInfo;
  126. if (instanceExtension.size() > 0)
  127. {
  128. if (validation)
  129. {
  130. instanceExtension.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
  131. }
  132. instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtension.size();
  133. instanceCreateInfo.ppEnabledExtensionNames = instanceExtension.data();
  134. }
  135. if (validation)
  136. {
  137. instanceCreateInfo.enabledLayerCount = (uint32_t)vulkan_validation_layers.size();
  138. instanceCreateInfo.ppEnabledLayerNames = vulkan_validation_layers.data();
  139. }
  140. VK_CHECK_RESULT(vkCreateInstance(&instanceCreateInfo, allocator, &instance));
  141. // register validation debug report
  142. if (validation)
  143. {
  144. vkCreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"));
  145. vkDestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"));
  146. vkDebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(vkGetInstanceProcAddr(instance, "vkDebugReportMessageEXT"));
  147. VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {};
  148. dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
  149. dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
  150. dbgCreateInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)log_vulkan_validation_debug_report;
  151. dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
  152. VK_CHECK_RESULT(vkCreateDebugReportCallbackEXT(instance, &dbgCreateInfo, allocator, &debugReport));
  153. }
  154. // load functions (needed on some platgforms)
  155. load_vulkan_functions();
  156. // get the available gpus
  157. uint32_t gpuCount = 0;
  158. VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &gpuCount, nullptr));
  159. GP_ASSERT(gpuCount > 0);
  160. std::vector<VkPhysicalDevice> physicalDevices(gpuCount);
  161. VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &gpuCount, physicalDevices.data()));
  162. // rate the physical devices based on important properties and features
  163. std::map<int, VkPhysicalDevice> physicalDevicesRated;
  164. for (const auto& physicalDev : physicalDevices)
  165. {
  166. VkPhysicalDeviceProperties properties;
  167. vkGetPhysicalDeviceProperties(physicalDev, &properties);
  168. VkPhysicalDeviceFeatures features;
  169. vkGetPhysicalDeviceFeatures(physicalDev, &features);
  170. int score = 0;
  171. if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
  172. {
  173. score += 1000;
  174. }
  175. score += properties.limits.maxImageDimension2D;
  176. if (!features.geometryShader)
  177. {
  178. score = 0;
  179. }
  180. physicalDevicesRated[score] = physicalDev;
  181. }
  182. // take the first device from rated devices that support our queue requirements
  183. physicalDevice = physicalDevicesRated.begin()->second;
  184. // get properties various properties of the physical device
  185. vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
  186. vkGetPhysicalDeviceMemoryProperties(physicalDevice, &physicalDeviceMemoryProperties);
  187. uint32_t queueFamilyCount;
  188. vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr);
  189. queueFamilyProperties.resize(queueFamilyCount);
  190. vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilyProperties.data());
  191. // get queue create infos for queues
  192. std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
  193. // graphics queue create info
  194. const float defaultQueuePriority(0.0f);
  195. queueFamilyIndices.graphics = get_queue_family_index(VK_QUEUE_GRAPHICS_BIT);
  196. VkDeviceQueueCreateInfo queueInfo{};
  197. queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  198. queueInfo.queueFamilyIndex = queueFamilyIndices.graphics;
  199. queueInfo.queueCount = 1;
  200. queueInfo.pQueuePriorities = &defaultQueuePriority;
  201. queueCreateInfos.push_back(queueInfo);
  202. // compute queue create info (if different) and requested
  203. queueFamilyIndices.compute = get_queue_family_index(VK_QUEUE_COMPUTE_BIT);
  204. if (queueFamilyIndices.compute != queueFamilyIndices.graphics)
  205. {
  206. float queuePriority(0.0f);
  207. VkDeviceQueueCreateInfo queueInfo{};
  208. queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  209. queueInfo.queueFamilyIndex = queueFamilyIndices.compute;
  210. queueInfo.queueCount = 1;
  211. queueInfo.pQueuePriorities = &defaultQueuePriority;
  212. queueCreateInfos.push_back(queueInfo);
  213. }
  214. else
  215. {
  216. queueFamilyIndices.compute = queueFamilyIndices.graphics;
  217. }
  218. if ((queueFamilyIndices.transfer != queueFamilyIndices.graphics) && (queueFamilyIndices.transfer != queueFamilyIndices.compute))
  219. {
  220. // if compute family index differs, we need an additional queue create info for the compute queue
  221. VkDeviceQueueCreateInfo queueInfo{};
  222. queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  223. queueInfo.queueFamilyIndex = queueFamilyIndices.transfer;
  224. queueInfo.queueCount = 1;
  225. queueInfo.pQueuePriorities = &defaultQueuePriority;
  226. queueCreateInfos.push_back(queueInfo);
  227. }
  228. else
  229. {
  230. queueFamilyIndices.transfer = queueFamilyIndices.graphics;
  231. }
  232. // Create the logical device
  233. VkPhysicalDeviceFeatures deviceFeatures = {};
  234. VkDeviceCreateInfo deviceCreateInfo = {};
  235. deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  236. deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size();
  237. deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
  238. deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
  239. std::vector<const char*> deviceExtensions;
  240. deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
  241. // Add validation layers/extensions
  242. if (validation && is_device_extension_present(physicalDevice, VK_EXT_DEBUG_MARKER_EXTENSION_NAME))
  243. {
  244. deviceExtensions.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
  245. }
  246. if (deviceExtensions.size() > 0)
  247. {
  248. deviceCreateInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size();
  249. deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
  250. }
  251. else
  252. {
  253. deviceCreateInfo.enabledExtensionCount = 0;
  254. }
  255. if (validation)
  256. {
  257. deviceCreateInfo.enabledLayerCount = (uint32_t)vulkan_validation_layers.size();
  258. deviceCreateInfo.ppEnabledLayerNames = vulkan_validation_layers.data();
  259. }
  260. else
  261. {
  262. deviceCreateInfo.enabledLayerCount = 0;
  263. }
  264. // create device and get the queue
  265. VK_CHECK_RESULT(vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device));
  266. vkGetDeviceQueue(device, queueFamilyIndices.graphics, 0, &queue);
  267. // setup and descriptor pool
  268. VkDescriptorPoolSize poolSizes[] =
  269. {
  270. { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
  271. { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
  272. { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
  273. { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
  274. { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
  275. { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
  276. { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
  277. { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
  278. { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
  279. { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
  280. { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
  281. };
  282. VkDescriptorPoolCreateInfo poolInfo = {};
  283. poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  284. poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
  285. poolInfo.maxSets = 1000 * (uint32_t)GP_COUNTOF(poolSizes);
  286. poolInfo.poolSizeCount = (uint32_t)GP_COUNTOF(poolSizes);
  287. poolInfo.pPoolSizes = poolSizes;
  288. VK_CHECK_RESULT(vkCreateDescriptorPool(device, &poolInfo, allocator, &descriptorPool));
  289. }
  290. void Renderer::Impl::shutdown_vulkan()
  291. {
  292. vkDestroyDescriptorPool(device, descriptorPool, allocator);
  293. if (validation)
  294. {
  295. vkDestroyDebugReportCallbackEXT(instance, debugReport, allocator);
  296. }
  297. vkDestroyDevice(device, allocator);
  298. vkDestroyInstance(instance, allocator);
  299. }
  300. void Renderer::Impl::startup_window_surface()
  301. {
  302. glfwWindow = App::get_app()->get_main_window()->handle->glfwWindow;
  303. // create the window surface
  304. VK_CHECK_RESULT(glfwCreateWindowSurface(instance, glfwWindow, allocator, &surface));
  305. // get the framebuffer size
  306. glfwGetFramebufferSize(glfwWindow, &surfaceWidth, &surfaceHeight);
  307. // lookup device surface and swapchain extensions
  308. vkGetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR"));
  309. vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
  310. vkGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
  311. vkGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"));
  312. vkCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(vkGetInstanceProcAddr(instance, "vkCreateSwapchainKHR"));
  313. vkDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(vkGetInstanceProcAddr(instance, "vkDestroySwapchainKHR"));
  314. vkGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(vkGetInstanceProcAddr(instance, "vkGetSwapchainImagesKHR"));
  315. vkAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(vkGetInstanceProcAddr(instance, "vkAcquireNextImageKHR"));
  316. vkQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(vkGetInstanceProcAddr(instance, "vkQueuePresentKHR"));
  317. VkBool32 res;
  318. vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndices.graphics, surface, &res);
  319. if (res != VK_TRUE)
  320. {
  321. GP_LOG_ERROR("Failed vkGetPhysicalDeviceSurfaceSupportKHR");
  322. return;
  323. }
  324. // select surface format
  325. const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
  326. const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
  327. surfaceFormat = select_surface_format(physicalDevice, surface, requestSurfaceImageFormat, (uint32_t)GP_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
  328. // get the present mode and image count for the present mode
  329. VkPresentModeKHR presentModes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
  330. presentMode = select_present_mode(physicalDevice, surface, &presentModes[0], (uint32_t)GP_COUNTOF(presentModes));
  331. // create the swapchain with render frames
  332. create_or_resize_window_swapchain();
  333. }
  334. void Renderer::Impl::shutdown_window_surface()
  335. {
  336. vkDeviceWaitIdle(device);
  337. for (uint32_t i = 0; i < imageCount; i++)
  338. {
  339. destroy_render_frame(&frames[i]);
  340. }
  341. frames.clear();
  342. vkDestroyPipeline(device, pipeline, allocator);
  343. vkDestroyRenderPass(device, renderPass, allocator);
  344. vkDestroySwapchainKHR(device,swapchain, allocator);
  345. vkDestroySurfaceKHR(instance, surface, allocator);
  346. }
  347. uint32_t Renderer::Impl::get_queue_family_index(VkQueueFlagBits queueFlags)
  348. {
  349. if (queueFlags & VK_QUEUE_COMPUTE_BIT)
  350. {
  351. for (uint32_t i = 0; i < static_cast<uint32_t>(queueFamilyProperties.size()); i++)
  352. {
  353. if ((queueFamilyProperties[i].queueFlags & queueFlags) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0))
  354. {
  355. return i;
  356. break;
  357. }
  358. }
  359. }
  360. for (uint32_t i = 0; i < static_cast<uint32_t>(queueFamilyProperties.size()); i++)
  361. {
  362. if (queueFamilyProperties[i].queueFlags & queueFlags)
  363. {
  364. return i;
  365. break;
  366. }
  367. }
  368. return 0;
  369. }
  370. VkBool32 Renderer::Impl::is_device_extension_present(VkPhysicalDevice physicalDevice, const char* extensionName)
  371. {
  372. uint32_t extensionCount = 0;
  373. std::vector<VkExtensionProperties> extensions;
  374. vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, NULL);
  375. extensions.resize(extensionCount);
  376. vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &extensionCount, extensions.data());
  377. for (auto& ext : extensions)
  378. {
  379. if (!strcmp(extensionName, ext.extensionName))
  380. {
  381. return true;
  382. }
  383. }
  384. return false;
  385. }
  386. VkSurfaceFormatKHR Renderer::Impl::select_surface_format(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, const VkFormat* requestFormats, int requestFormatCount, VkColorSpaceKHR requestColorSpace)
  387. {
  388. uint32_t availSurfaceFormatCount;
  389. vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &availSurfaceFormatCount, NULL);
  390. std::vector<VkSurfaceFormatKHR> availFormats;
  391. availFormats.resize((int)availSurfaceFormatCount);
  392. vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &availSurfaceFormatCount, availFormats.data());
  393. if (availSurfaceFormatCount == 1)
  394. {
  395. if (availFormats[0].format == VK_FORMAT_UNDEFINED)
  396. {
  397. VkSurfaceFormatKHR ret;
  398. ret.format = requestFormats[0];
  399. ret.colorSpace = requestColorSpace;
  400. return ret;
  401. }
  402. else
  403. {
  404. return availFormats[0];
  405. }
  406. }
  407. else
  408. {
  409. for (int i = 0; i < requestFormatCount; i++)
  410. {
  411. for (uint32_t i = 0; i < availSurfaceFormatCount; i++)
  412. {
  413. if (availFormats[i].format == requestFormats[i] && availFormats[i].colorSpace == requestColorSpace)
  414. {
  415. return availFormats[i];
  416. }
  417. }
  418. }
  419. return availFormats[0];
  420. }
  421. }
  422. VkPresentModeKHR Renderer::Impl::select_present_mode(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, const VkPresentModeKHR* requestModes, int requestModeCount)
  423. {
  424. // request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
  425. uint32_t availModeCount = 0;
  426. vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &availModeCount, nullptr);
  427. std::vector<VkPresentModeKHR> availModes;
  428. availModes.resize((int)availModeCount);
  429. vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &availModeCount, availModes.data());
  430. for (int req = 0; req < requestModeCount; req++)
  431. {
  432. for (uint32_t avail = 0; avail < availModeCount; avail++)
  433. {
  434. if (requestModes[req] == availModes[avail])
  435. {
  436. return requestModes[req];
  437. }
  438. }
  439. }
  440. return VK_PRESENT_MODE_FIFO_KHR;
  441. }
  442. uint32_t Renderer::Impl::get_image_count_for_present_mode(VkPresentModeKHR mode)
  443. {
  444. switch(mode)
  445. {
  446. case VK_PRESENT_MODE_MAILBOX_KHR:
  447. return 3;
  448. case VK_PRESENT_MODE_FIFO_KHR:
  449. case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
  450. return 2;
  451. case VK_PRESENT_MODE_IMMEDIATE_KHR:
  452. return 1;
  453. default:
  454. return 1;
  455. }
  456. }
  457. void Renderer::Impl::create_or_resize_window_swapchain()
  458. {
  459. // preserve previous swa
  460. VkSwapchainKHR oldSwapchain = swapchain;
  461. swapchain = VK_NULL_HANDLE;
  462. VK_CHECK_RESULT(vkDeviceWaitIdle(device));
  463. // cleanup previous swapchain resources
  464. for (size_t i = 0; i <imageCount; i++)
  465. {
  466. destroy_render_frame(&frames[i]);
  467. }
  468. if (renderPass)
  469. {
  470. vkDestroyRenderPass(device, renderPass, allocator);
  471. }
  472. if (pipeline)
  473. {
  474. vkDestroyPipeline(device, pipeline, allocator);
  475. }
  476. uint32_t minImageCountForMode = get_image_count_for_present_mode(presentMode);
  477. if (minImageCount < minImageCountForMode)
  478. {
  479. minImageCount = minImageCountForMode;
  480. }
  481. // setup new swapchain
  482. VkSwapchainCreateInfoKHR info = {};
  483. info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  484. info.surface = surface;
  485. info.minImageCount = minImageCount;
  486. info.imageFormat = surfaceFormat.format;
  487. info.imageColorSpace = surfaceFormat.colorSpace;
  488. info.imageArrayLayers = 1;
  489. info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  490. info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family
  491. info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
  492. info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  493. info.presentMode = presentMode;
  494. info.clipped = VK_TRUE;
  495. info.oldSwapchain = swapchain;
  496. VkSurfaceCapabilitiesKHR surfaceCaps;
  497. VK_CHECK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfaceCaps));
  498. if (info.minImageCount < surfaceCaps.minImageCount)
  499. {
  500. info.minImageCount = surfaceCaps.minImageCount;
  501. }
  502. else if (surfaceCaps.maxImageCount != 0 && info.minImageCount > surfaceCaps.maxImageCount)
  503. {
  504. info.minImageCount = surfaceCaps.maxImageCount;
  505. }
  506. if (surfaceCaps.currentExtent.width == 0xffffffff)
  507. {
  508. info.imageExtent.width = surfaceWidth;
  509. info.imageExtent.height = surfaceHeight;
  510. }
  511. else
  512. {
  513. info.imageExtent.width = surfaceWidth = surfaceCaps.currentExtent.width;
  514. info.imageExtent.height = surfaceHeight = surfaceCaps.currentExtent.height;
  515. }
  516. VK_CHECK_RESULT(vkCreateSwapchainKHR(device, &info, allocator, &swapchain));
  517. // get the number of back buffers
  518. VK_CHECK_RESULT(vkGetSwapchainImagesKHR(device, swapchain, &imageCount, NULL));
  519. frames.resize(imageCount);
  520. // get the back buffer images and assign into the render frames
  521. std::vector<VkImage> backbuffers;
  522. backbuffers.resize(imageCount);
  523. VK_CHECK_RESULT(vkGetSwapchainImagesKHR(device, swapchain, &imageCount, backbuffers.data()));
  524. for (uint32_t i = 0; i < imageCount; i++)
  525. {
  526. frames[i].backbuffer = backbuffers[i];
  527. }
  528. // destroy any previous swapchain that may exist
  529. if (oldSwapchain)
  530. {
  531. vkDestroySwapchainKHR(device, oldSwapchain, allocator);
  532. }
  533. // create a render pass for ui
  534. {
  535. VkAttachmentDescription attachment = {};
  536. attachment.format = surfaceFormat.format;
  537. attachment.samples = VK_SAMPLE_COUNT_1_BIT;
  538. attachment.loadOp = clearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  539. attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  540. attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  541. attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  542. attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  543. attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  544. VkAttachmentReference color_attachment = {};
  545. color_attachment.attachment = 0;
  546. color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  547. VkSubpassDescription subpass = {};
  548. subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  549. subpass.colorAttachmentCount = 1;
  550. subpass.pColorAttachments = &color_attachment;
  551. VkSubpassDependency dependency = {};
  552. dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
  553. dependency.dstSubpass = 0;
  554. dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  555. dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  556. dependency.srcAccessMask = 0;
  557. dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  558. VkRenderPassCreateInfo info = {};
  559. info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  560. info.attachmentCount = 1;
  561. info.pAttachments = &attachment;
  562. info.subpassCount = 1;
  563. info.pSubpasses = &subpass;
  564. info.dependencyCount = 1;
  565. info.pDependencies = &dependency;
  566. VK_CHECK_RESULT(vkCreateRenderPass(device, &info, allocator, &renderPass));
  567. }
  568. // create the iamge view
  569. {
  570. VkImageViewCreateInfo info = {};
  571. info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  572. info.viewType = VK_IMAGE_VIEW_TYPE_2D;
  573. info.format = surfaceFormat.format;
  574. info.components.r = VK_COMPONENT_SWIZZLE_R;
  575. info.components.g = VK_COMPONENT_SWIZZLE_G;
  576. info.components.b = VK_COMPONENT_SWIZZLE_B;
  577. info.components.a = VK_COMPONENT_SWIZZLE_A;
  578. VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
  579. info.subresourceRange = image_range;
  580. for (uint32_t i = 0; i < imageCount; i++)
  581. {
  582. RenderFrame* renderFrame = &frames[i];
  583. info.image = renderFrame->backbuffer;
  584. VK_CHECK_RESULT(vkCreateImageView(device, &info, allocator, &renderFrame->backbufferView));
  585. }
  586. }
  587. // create the framebuffer
  588. {
  589. VkImageView attachment[1];
  590. VkFramebufferCreateInfo info = {};
  591. info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  592. info.renderPass = renderPass;
  593. info.attachmentCount = 1;
  594. info.pAttachments = attachment;
  595. info.width = surfaceWidth;
  596. info.height = surfaceHeight;
  597. info.layers = 1;
  598. for (uint32_t i = 0; i < imageCount; i++)
  599. {
  600. RenderFrame* renderFrame = &frames[i];
  601. attachment[0] = renderFrame->backbufferView;
  602. VK_CHECK_RESULT(vkCreateFramebuffer(device, &info, allocator, &renderFrame->framebuffer));
  603. }
  604. }
  605. // create command buffers for each render frame
  606. for (uint32_t i = 0; i < imageCount; i++)
  607. {
  608. RenderFrame* renderFrame = &frames[i];
  609. // create the command pool
  610. {
  611. VkCommandPoolCreateInfo info = {};
  612. info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  613. info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  614. info.queueFamilyIndex = queueFamilyIndices.graphics;
  615. VK_CHECK_RESULT(vkCreateCommandPool(device, &info, allocator, &renderFrame->commandPool));
  616. }
  617. // create the command buffer
  618. {
  619. VkCommandBufferAllocateInfo info = {};
  620. info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  621. info.commandPool = renderFrame->commandPool;
  622. info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  623. info.commandBufferCount = 1;
  624. VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &info, &renderFrame->commandBuffer));
  625. }
  626. // create the fence
  627. {
  628. VkFenceCreateInfo info = {};
  629. info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  630. info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  631. VK_CHECK_RESULT(vkCreateFence(device, &info, allocator, &renderFrame->fence));
  632. }
  633. // create the semaphore
  634. {
  635. VkSemaphoreCreateInfo info = {};
  636. info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  637. VK_CHECK_RESULT(vkCreateSemaphore(device, &info, allocator, &renderFrame->imageAcquiredSemaphore));
  638. VK_CHECK_RESULT(vkCreateSemaphore(device, &info, allocator, &renderFrame->renderCompleteSemaphore));
  639. }
  640. }
  641. }
  642. void Renderer::Impl::destroy_render_frame(RenderFrame* renderFrame)
  643. {
  644. vkDestroyFence(device, renderFrame->fence, allocator);
  645. vkFreeCommandBuffers(device, renderFrame->commandPool, 1, &renderFrame->commandBuffer);
  646. vkDestroyCommandPool(device, renderFrame->commandPool, allocator);
  647. renderFrame->fence = VK_NULL_HANDLE;
  648. renderFrame->commandBuffer = VK_NULL_HANDLE;
  649. renderFrame->commandPool = VK_NULL_HANDLE;
  650. vkDestroyImageView(device, renderFrame->backbufferView, allocator);
  651. vkDestroyFramebuffer(device, renderFrame->framebuffer, allocator);
  652. vkDestroySemaphore(device, renderFrame->imageAcquiredSemaphore, allocator);
  653. vkDestroySemaphore(device, renderFrame->renderCompleteSemaphore, allocator);
  654. renderFrame->imageAcquiredSemaphore = renderFrame->renderCompleteSemaphore = VK_NULL_HANDLE;
  655. }
  656. void Renderer::Impl::next_frame()
  657. {
  658. if (rebuildSwapchain)
  659. {
  660. glfwGetFramebufferSize(glfwWindow, &surfaceWidth, &surfaceWidth);
  661. if (surfaceWidth > 0 && surfaceHeight > 0)
  662. {
  663. create_or_resize_window_swapchain();
  664. frameIndex = 0;
  665. rebuildSwapchain = false;
  666. }
  667. }
  668. }
  669. void Renderer::Impl::present_frame()
  670. {
  671. if (rebuildSwapchain)
  672. {
  673. return;
  674. }
  675. VkSemaphore render_complete_semaphore = frames[semaphoreIndex].renderCompleteSemaphore;
  676. VkPresentInfoKHR info = {};
  677. info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  678. info.waitSemaphoreCount = 1;
  679. info.pWaitSemaphores = &render_complete_semaphore;
  680. info.swapchainCount = 1;
  681. info.pSwapchains = &swapchain;
  682. info.pImageIndices = &frameIndex;
  683. VkResult res = vkQueuePresentKHR(queue, &info);
  684. if (res == VK_ERROR_OUT_OF_DATE_KHR)
  685. {
  686. rebuildSwapchain = true;
  687. return;
  688. }
  689. check_vulkan_result(res);
  690. semaphoreIndex = (semaphoreIndex + 1) % imageCount;
  691. }
  692. void Renderer::Impl::startup_imgui()
  693. {
  694. ImGui_ImplVulkan_InitInfo init_info = {};
  695. init_info.Instance = instance;
  696. init_info.PhysicalDevice = physicalDevice;
  697. init_info.Device = device;
  698. init_info.QueueFamily = queueFamilyIndices.graphics;
  699. init_info.Queue = queue;
  700. init_info.PipelineCache = pipelineCache;
  701. init_info.DescriptorPool = descriptorPool;
  702. init_info.Allocator = allocator;
  703. init_info.MinImageCount = minImageCount;
  704. init_info.ImageCount = imageCount;
  705. init_info.CheckVkResultFn = check_vulkan_result;
  706. ImGui_ImplVulkan_Init(&init_info, renderPass);
  707. // upload the fonts
  708. {
  709. // Use any command queue
  710. VkCommandPool commandPool = frames[frameIndex].commandPool;
  711. VkCommandBuffer commandBuffer = frames[frameIndex].commandBuffer;
  712. VK_CHECK_RESULT(vkResetCommandPool(device, commandPool, 0));
  713. VkCommandBufferBeginInfo beginInfo = {};
  714. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  715. beginInfo.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  716. VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &beginInfo));
  717. ImGui_ImplVulkan_CreateFontsTexture(commandBuffer);
  718. VkSubmitInfo endInfo = {};
  719. endInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  720. endInfo.commandBufferCount = 1;
  721. endInfo.pCommandBuffers = &commandBuffer;
  722. VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer));
  723. VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &endInfo, VK_NULL_HANDLE));
  724. VK_CHECK_RESULT(vkDeviceWaitIdle(device));
  725. ImGui_ImplVulkan_DestroyFontUploadObjects();
  726. }
  727. }
  728. void Renderer::Impl::shutdow_imgui()
  729. {
  730. vkDeviceWaitIdle(device);
  731. ImGui_ImplVulkan_Shutdown();
  732. }
  733. void Renderer::Impl::render_imgui()
  734. {
  735. VkSemaphore imageAcquiredSemaphore = frames[semaphoreIndex].imageAcquiredSemaphore;
  736. VkSemaphore renderCompleteSemaphore = frames[semaphoreIndex].renderCompleteSemaphore;
  737. VkResult res = vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE, &frameIndex);
  738. if (res == VK_ERROR_OUT_OF_DATE_KHR)
  739. {
  740. rebuildSwapchain = true;
  741. return;
  742. }
  743. check_vulkan_result(res);
  744. RenderFrame* frame = &frames[frameIndex];
  745. VK_CHECK_RESULT(vkWaitForFences(device, 1, &frame->fence, VK_TRUE, UINT64_MAX));
  746. VK_CHECK_RESULT(vkResetFences(device, 1, &frame->fence));
  747. VK_CHECK_RESULT(vkResetCommandPool(device, frame->commandPool, 0));
  748. // begin a command buffer
  749. {
  750. VkCommandBufferBeginInfo info = {};
  751. info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  752. info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  753. VK_CHECK_RESULT(vkBeginCommandBuffer(frame->commandBuffer, &info));
  754. }
  755. // begin a render pass
  756. {
  757. VkRenderPassBeginInfo info = {};
  758. info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  759. info.renderPass = renderPass;
  760. info.framebuffer = frame->framebuffer;
  761. info.renderArea.extent.width = surfaceWidth;
  762. info.renderArea.extent.height = surfaceHeight;
  763. info.clearValueCount = 1;
  764. info.pClearValues = &clearValue;
  765. vkCmdBeginRenderPass(frame->commandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
  766. }
  767. // build commands from imgui draw data
  768. ImDrawData* drawData = ImGui::GetDrawData();
  769. ImGui_ImplVulkan_RenderDrawData(drawData, frame->commandBuffer);
  770. // end the render pass
  771. vkCmdEndRenderPass(frame->commandBuffer);
  772. {
  773. VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  774. VkSubmitInfo info = {};
  775. info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  776. info.waitSemaphoreCount = 1;
  777. info.pWaitSemaphores = &imageAcquiredSemaphore;
  778. info.pWaitDstStageMask = &wait_stage;
  779. info.commandBufferCount = 1;
  780. info.pCommandBuffers = &frame->commandBuffer;
  781. info.signalSemaphoreCount = 1;
  782. info.pSignalSemaphores = &renderCompleteSemaphore;
  783. VK_CHECK_RESULT(vkEndCommandBuffer(frame->commandBuffer));
  784. VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &info, frame->fence));
  785. }
  786. }
  787. void Renderer::shutdown()
  788. {
  789. _impl->shutdow_imgui();
  790. _impl->shutdown_window_surface();
  791. _impl->shutdown_vulkan();
  792. unload_vulkan_library();
  793. }
  794. void Renderer::next_frame()
  795. {
  796. _impl->next_frame();
  797. }
  798. void Renderer::update()
  799. {
  800. // update the scene with ecs
  801. }
  802. void Renderer::render_frame()
  803. {
  804. _impl->render_imgui();
  805. ImGuiIO& io = ImGui::GetIO();
  806. if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
  807. {
  808. ImGui::UpdatePlatformWindows();
  809. ImGui::RenderPlatformWindowsDefault();
  810. }
  811. }
  812. void Renderer::present_frame()
  813. {
  814. _impl->present_frame();
  815. }
  816. }