VKWVulkanWindow.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. #ifndef VKW_VULKAN_WINDOW_H
  2. #define VKW_VULKAN_WINDOW_H
  3. #include "vulkan_include.h"
  4. #include <vector>
  5. #include <string>
  6. #include "Frame.h"
  7. #include "base_widget.h"
  8. #include "Adapters/VulkanWindowAdapter.h"
  9. namespace vkw
  10. {
  11. class VKWVulkanWindow : public BaseWidget
  12. {
  13. public:
  14. struct InstanceInitilizationInfo2
  15. {
  16. PFN_vkDebugReportCallbackEXT debugCallback = nullptr;
  17. std::vector<std::string> enabledLayers = { "VK_LAYER_KHRONOS_validation"};
  18. std::vector<std::string> enabledExtensions = { VK_EXT_DEBUG_REPORT_EXTENSION_NAME };
  19. #if defined VK_HEADER_VERSION_COMPLETE
  20. #define VKW_DEFAULT_VULKAN_VERSION VK_HEADER_VERSION_COMPLETE
  21. #else
  22. #define VKW_DEFAULT_VULKAN_VERSION VK_MAKE_VERSION(1, 0, 0)
  23. #endif
  24. uint32_t vulkanVersion = VKW_DEFAULT_VULKAN_VERSION;
  25. std::string applicationName = "App name";
  26. std::string engineName = "Engine Name";
  27. };
  28. struct SurfaceInitilizationInfo2
  29. {
  30. VkFormat surfaceFormat = VkFormat::VK_FORMAT_B8G8R8A8_UNORM;
  31. VkFormat depthFormat = VkFormat::VK_FORMAT_D32_SFLOAT_S8_UINT;
  32. VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
  33. uint32_t additionalImageCount = 1;// how many additional swapchain images should we create ( total = min_images + additionalImageCount
  34. };
  35. struct DeviceInitilizationInfo2
  36. {
  37. // which device ID do you want to use?
  38. // set to 0 to choose the first discrete GPU it can find.
  39. // if no discrete gpu is found, uses the first GPU found
  40. //
  41. // auto devices = window->getAvailablePhysicalDevices();
  42. // devices[0].deviceID
  43. uint32_t deviceID = 0;
  44. std::vector<std::string> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
  45. // the values enabledFeaturesXX structs can be set to true
  46. // to enable the features. you do not need to set the sNext
  47. // pointers. They will automatically be set when we create the device
  48. // if you want enable non KHR extensions, then you will have to set
  49. // the enabledFeatures12.pNext value yourself
  50. VkPhysicalDeviceFeatures2 enabledFeatures = {};
  51. VkPhysicalDeviceVulkan11Features enabledFeatures11 = {};
  52. VkPhysicalDeviceVulkan12Features enabledFeatures12 = {};
  53. VkPhysicalDeviceVulkan13Features enabledFeatures13 = {};
  54. };
  55. //=================================================================
  56. // 1. Create the window first using this function
  57. void setWindowAdapater(VulkanWindowAdapater * window);
  58. // 2. Create a vulkan instance
  59. void createVulkanInstance(InstanceInitilizationInfo2 const & I);
  60. void setVulkanInstance(VkInstance instance);
  61. // 3. create the vulkan surface
  62. bool createVulkanSurface(SurfaceInitilizationInfo2 const & I);
  63. // 5. Create the logical device
  64. void createVulkanDevice(DeviceInitilizationInfo2 const & I);
  65. void setDepthFormat(VkFormat format)
  66. {
  67. m_initInfo2.surface.depthFormat = format;
  68. }
  69. void setPresentMode(VkPresentModeKHR mode)
  70. {
  71. m_initInfo2.surface.presentMode = mode;
  72. }
  73. std::vector<VkPhysicalDeviceProperties> getAvailablePhysicalDevices() const
  74. {
  75. return getAvailablePhysicalDevices(m_instance);
  76. }
  77. static std::vector<VkPhysicalDeviceProperties> getAvailablePhysicalDevices(VkInstance instance)
  78. {
  79. std::vector<VkPhysicalDevice> physicalDevices;
  80. uint32_t physicalDeviceCount = 0;
  81. vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr);
  82. physicalDevices.resize(physicalDeviceCount);
  83. vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data());
  84. std::vector<VkPhysicalDeviceProperties> _p;
  85. for(auto & pD : physicalDevices)
  86. {
  87. VkPhysicalDeviceProperties props;
  88. vkGetPhysicalDeviceProperties(pD, &props);
  89. _p.push_back(props);
  90. }
  91. return _p;
  92. }
  93. static VkPhysicalDeviceProperties getPhysicalDeviceProperties(VkInstance instance, VkPhysicalDevice device)
  94. {
  95. VkPhysicalDeviceProperties props;
  96. vkGetPhysicalDeviceProperties(device, &props);
  97. return props;
  98. }
  99. static std::vector<VkPhysicalDevice> getPhysicalDevices(VkInstance instance)
  100. {
  101. // Querying valid physical devices on the machine
  102. uint32_t physical_device_count{0};
  103. vkEnumeratePhysicalDevices(instance, &physical_device_count, nullptr);
  104. std::vector<VkPhysicalDevice> physical_devices;
  105. physical_devices.resize(physical_device_count);
  106. vkEnumeratePhysicalDevices(instance, &physical_device_count, physical_devices.data());
  107. return physical_devices;
  108. }
  109. static std::vector<VkQueueFamilyProperties> getQueueFamilyProperties(VkPhysicalDevice physicalDevice)
  110. {
  111. uint32_t queue_family_properties_count = 0;
  112. vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queue_family_properties_count, nullptr);
  113. std::vector<VkQueueFamilyProperties> queue_family_properties(queue_family_properties_count);
  114. vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queue_family_properties_count, queue_family_properties.data());
  115. return queue_family_properties;
  116. }
  117. /**
  118. * @brief getPhysicalDevice
  119. * @param instance
  120. * @param surface
  121. * @return
  122. *
  123. * Return a physical device which is suitable to present to surface
  124. */
  125. static VkPhysicalDevice getPhysicalDevice(VkInstance instance, VkSurfaceKHR surface)
  126. {
  127. auto physicalDevices = getPhysicalDevices(instance);
  128. for(auto pd : physicalDevices)
  129. {
  130. //assert(!gpus.empty() && "No physical devices were found on the system.");
  131. auto props = getPhysicalDeviceProperties(instance, pd);
  132. // Find a discrete GPU
  133. if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
  134. {
  135. //See if it work with the surface
  136. auto queue_family_properties = getQueueFamilyProperties(pd);
  137. size_t queue_count = queue_family_properties.size();
  138. for (uint32_t queue_idx = 0; static_cast<size_t>(queue_idx) < queue_count; queue_idx++)
  139. {
  140. VkBool32 present_supported = VK_FALSE;
  141. vkGetPhysicalDeviceSurfaceSupportKHR(pd, queue_idx, surface, &present_supported);
  142. if(present_supported)
  143. return pd;
  144. }
  145. }
  146. }
  147. return VK_NULL_HANDLE;
  148. }
  149. //=================================================================
  150. //=================================================================================
  151. /**
  152. * @brief destroy
  153. *
  154. * When you are done with the window, you must call this
  155. * too release any vulkan resources associated with the
  156. * window.
  157. */
  158. void destroy();
  159. std::vector<std::string> getAvailableVulkanLayers();
  160. ~VKWVulkanWindow();
  161. void setInstance(VkInstance instance);
  162. void setPhysicalDevice(VkPhysicalDevice physicalDevice);
  163. //===================================================================
  164. // The implementation for the following functions are in
  165. // SDLVulkanWindow_USAGE.cpp
  166. //===================================================================
  167. /**
  168. * @brief acquireNextFrame
  169. * @return
  170. *
  171. * Get the next available frame. The Frame contains
  172. * information about which swapchain image index to use
  173. * a handle to a command buffer and the command pool should
  174. * you need it.
  175. *
  176. * It also contains semaphores to handle synhronization
  177. */
  178. Frame acquireNextFrame();
  179. /**
  180. * @brief submitFrame
  181. * @param C
  182. *
  183. * Submt the the frame to the GPU to process.
  184. * The command buffer C.commandBuffer will be
  185. * sent to the GPU for processing.
  186. */
  187. void submitFrame(Frame const & C);
  188. void submitFrameCommandBuffer(VkCommandBuffer cb,
  189. VkSemaphore wait,
  190. VkSemaphore signal,
  191. VkFence fence);
  192. /**
  193. * @brief presentFrame
  194. * @param F
  195. *
  196. * Present the swapchain frame which was
  197. * acquired by acquireNextFrame();
  198. */
  199. void presentFrame(const Frame &F);
  200. /**
  201. * @brief waitForPresent
  202. *
  203. * Wait until the device is idle
  204. */
  205. void waitForPresent();
  206. //SDL_Window* getSDLWindow() const
  207. //{
  208. // return m_window;
  209. //}
  210. VulkanWindowAdapater* getWindowAdapter() const
  211. {
  212. return m_window;
  213. }
  214. VkInstance getInstance() const
  215. {
  216. return m_instance;
  217. }
  218. VkExtent2D getSwapchainExtent() const
  219. {
  220. return m_swapchainSize;
  221. }
  222. VkDevice getDevice() const
  223. {
  224. return m_device;
  225. }
  226. VkPhysicalDevice getPhysicalDevice() const
  227. {
  228. return m_physicalDevice;
  229. }
  230. VkSwapchainKHR getSwapchain() const
  231. {
  232. return m_swapchain;
  233. }
  234. int32_t getGraphicsQueueIndex() const
  235. {
  236. return m_graphicsQueueIndex;
  237. }
  238. VkQueue getGraphicsQueue() const
  239. {
  240. return m_graphicsQueue;
  241. }
  242. int32_t getPresentQueueIndex() const
  243. {
  244. return m_presentQueueIndex;
  245. }
  246. VkQueue getPresentQueue() const
  247. {
  248. return m_presentQueue;
  249. }
  250. std::vector<VkImageView> getSwapchainImageViews() const
  251. {
  252. return m_swapchainImageViews;
  253. }
  254. std::vector<VkImage> getSwapchainImages() const
  255. {
  256. return m_swapchainImages;
  257. }
  258. VkFormat getSwapchainFormat() const
  259. {
  260. return m_surfaceFormat.format;
  261. }
  262. VkFormat getDepthFormat() const
  263. {
  264. return m_initInfo2.surface.depthFormat;
  265. }
  266. VkImage getDepthImage() const
  267. {
  268. return m_depthStencil;
  269. }
  270. VkImageView getDepthImageView() const
  271. {
  272. return m_depthStencilImageView;
  273. }
  274. VkRenderPass getRenderPass() const
  275. {
  276. return m_renderPass;
  277. }
  278. //===================================================================
  279. void rebuildSwapchain()
  280. {
  281. _destroySwapchain(false);
  282. _createSwapchain(m_initInfo2.surface.additionalImageCount);
  283. }
  284. static VkPhysicalDeviceFeatures2 getSupportedDeviceFeatures(VkPhysicalDevice physicalDevice);
  285. static VkPhysicalDeviceVulkan11Features getSupportedDeviceFeatures11(VkPhysicalDevice physicalDevice);
  286. static VkPhysicalDeviceVulkan12Features getSupportedDeviceFeatures12(VkPhysicalDevice physicalDevice);
  287. static VkPhysicalDeviceVulkan13Features getSupportedDeviceFeatures13(VkPhysicalDevice physicalDevice);
  288. protected:
  289. template<typename callable_t>
  290. VkPhysicalDevice chooseVulkanPhysicalDevice(callable_t && callable) const
  291. {
  292. using namespace std;
  293. vector<VkPhysicalDevice> physicalDevices;
  294. uint32_t physicalDeviceCount = 0;
  295. vkEnumeratePhysicalDevices(m_instance, &physicalDeviceCount, nullptr);
  296. physicalDevices.resize(physicalDeviceCount);
  297. vkEnumeratePhysicalDevices(m_instance, &physicalDeviceCount, physicalDevices.data());
  298. for(auto & pD : physicalDevices)
  299. {
  300. VkPhysicalDeviceProperties props;
  301. vkGetPhysicalDeviceProperties(pD, &props);
  302. if( callable(props))
  303. {
  304. return pD;
  305. break;
  306. }
  307. }
  308. return VK_NULL_HANDLE;
  309. }
  310. struct
  311. {
  312. InstanceInitilizationInfo2 instance;
  313. SurfaceInitilizationInfo2 surface;
  314. DeviceInitilizationInfo2 device;
  315. } m_initInfo2;
  316. //SDL_Window * m_window = nullptr;
  317. VulkanWindowAdapater *m_window = nullptr;
  318. VkInstance m_instance = VK_NULL_HANDLE;
  319. VkSurfaceKHR m_surface = VK_NULL_HANDLE;
  320. VkPhysicalDevice m_physicalDevice;
  321. int32_t m_graphicsQueueIndex;
  322. int32_t m_presentQueueIndex;
  323. VkDevice m_device = VK_NULL_HANDLE;
  324. VkQueue m_graphicsQueue = VK_NULL_HANDLE;
  325. VkQueue m_presentQueue = VK_NULL_HANDLE;
  326. VkSurfaceCapabilitiesKHR m_surfaceCapabilities;
  327. VkSurfaceFormatKHR m_surfaceFormat;
  328. VkExtent2D m_swapchainSize;
  329. VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
  330. std::vector<VkImage> m_swapchainImages;
  331. std::vector<VkImageView> m_swapchainImageViews;
  332. VkImage m_depthStencil = VK_NULL_HANDLE;
  333. VkImageView m_depthStencilImageView = VK_NULL_HANDLE;
  334. VkDeviceMemory m_depthStencilImageMemory = VK_NULL_HANDLE;
  335. VkRenderPass m_renderPass = VK_NULL_HANDLE;
  336. std::vector<VkFramebuffer> m_swapchainFrameBuffers;
  337. std::vector<VkCommandPool> m_commandPools;
  338. std::vector<VkFence> m_fences;
  339. std::vector<VkSemaphore> m_imageAvailableSemaphores;
  340. std::vector<VkSemaphore> m_renderCompleteSemaphores;
  341. VkDebugReportCallbackEXT m_debugCallback = VK_NULL_HANDLE;
  342. std::vector<Frame> m_frames;
  343. protected:
  344. void _selectQueueFamily();
  345. VkDevice _createDevice();
  346. void _createSwapchain(uint32_t additionalImages);
  347. void _destroySwapchain(bool destroyRenderpass);
  348. VkDebugReportCallbackEXT _createDebug(PFN_vkDebugReportCallbackEXT _callback);
  349. std::pair<VkImage, VkDeviceMemory> createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties);
  350. void _createDepthStencil();
  351. void _createRenderPass();
  352. void _createFramebuffers();
  353. void _createPerFrameObjects();
  354. };
  355. }
  356. #endif