VulkanWrapper.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. #include "core/VulkanWrapper.hpp"
  2. #include <cstring>
  3. #include "GLFW.hpp"
  4. #include "core/VulkanBase.hpp"
  5. #include "core/WindowManager.hpp"
  6. import Core.File;
  7. import Core.UniquePointer;
  8. import Core.List;
  9. import Core.Logger;
  10. import Core.Types;
  11. import Core.Math;
  12. import Core.Array;
  13. import Core.Vector;
  14. namespace Vulkan = Core::Vulkan;
  15. using Core::List;
  16. using Core::Vulkan::VertexBuffer;
  17. using Vulkan::CommandBuffer;
  18. using Vulkan::Queue;
  19. using Vulkan::SwapchainImages;
  20. using Vulkan::SwapchainResult;
  21. #define WRAPPER_DESTRUCT(Type, ...) \
  22. using Core::Vulkan::Type; \
  23. Type::~Type() { \
  24. if(device != VK_NULL_HANDLE) { \
  25. vkDestroy##Type##__VA_ARGS__(device, handle, nullptr); \
  26. } \
  27. device = VK_NULL_HANDLE; \
  28. handle = VK_NULL_HANDLE; \
  29. }
  30. WRAPPER_DESTRUCT(ImageView)
  31. WRAPPER_DESTRUCT(Framebuffer)
  32. WRAPPER_DESTRUCT(Semaphore)
  33. WRAPPER_DESTRUCT(Fence)
  34. WRAPPER_DESTRUCT(Swapchain, KHR)
  35. WRAPPER_DESTRUCT(ShaderModule)
  36. WRAPPER_DESTRUCT(PipelineLayout)
  37. WRAPPER_DESTRUCT(Pipeline)
  38. WRAPPER_DESTRUCT(CommandPool)
  39. WRAPPER_DESTRUCT(RenderPass)
  40. bool ImageView::init(VkDevice d, VkImage image, VkFormat format) {
  41. ImageView::~ImageView();
  42. VkImageViewCreateInfo info = {
  43. .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
  44. .image = image,
  45. .viewType = VK_IMAGE_VIEW_TYPE_2D,
  46. .format = format,
  47. .subresourceRange = {
  48. .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
  49. .baseMipLevel = 0,
  50. .levelCount = 1,
  51. .baseArrayLayer = 0,
  52. .layerCount = 1}};
  53. VK_CHECK_TRUE(vkCreateImageView(d, &info, nullptr, &handle));
  54. device = d;
  55. return false;
  56. }
  57. bool Framebuffer::init(
  58. const ImageView& iv, VkRenderPass rp, u32 width, u32 height) {
  59. Framebuffer::~Framebuffer();
  60. VkFramebufferCreateInfo info = {
  61. .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
  62. .renderPass = rp,
  63. .attachmentCount = 1,
  64. .pAttachments = iv,
  65. .width = width,
  66. .height = height,
  67. .layers = 1};
  68. VK_CHECK_TRUE(vkCreateFramebuffer(iv.device, &info, nullptr, &handle));
  69. device = iv.device;
  70. return false;
  71. }
  72. bool Semaphore::init(VkDevice d) {
  73. Semaphore::~Semaphore();
  74. VkSemaphoreCreateInfo info = {
  75. .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
  76. VK_CHECK_TRUE(vkCreateSemaphore(d, &info, nullptr, &handle));
  77. device = d;
  78. return false;
  79. }
  80. bool Fence::init(VkDevice d) {
  81. Fence::~Fence();
  82. VkFenceCreateInfo info = {
  83. .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
  84. .flags = VK_FENCE_CREATE_SIGNALED_BIT};
  85. VK_CHECK_TRUE(vkCreateFence(d, &info, nullptr, &handle));
  86. device = d;
  87. return false;
  88. }
  89. void Fence::reset() {
  90. VK_CHECK_VOID(vkResetFences(device, 1, &handle));
  91. }
  92. void Fence::waitFor(u64 timeout) {
  93. VK_CHECK_VOID(vkWaitForFences(device, 1, &handle, true, timeout));
  94. }
  95. static u32 getSwapImageCount(const VkSurfaceCapabilitiesKHR* caps) {
  96. u32 c = caps->minImageCount + 1;
  97. // according to VkSurfaceCapabilitiesKHR doc:
  98. // maxImageCount is 0 when there is no strict limit
  99. if(caps->maxImageCount != 0) {
  100. return Core::min(c, caps->maxImageCount);
  101. }
  102. return c;
  103. }
  104. bool Swapchain::init(Data& d) {
  105. Swapchain::~Swapchain();
  106. VkSurfaceCapabilitiesKHR caps = {};
  107. if(d.base.getSurfaceCapabilities(caps)) {
  108. return true;
  109. }
  110. VkSwapchainCreateInfoKHR ci = {
  111. .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
  112. .surface = d.base,
  113. .minImageCount = getSwapImageCount(&caps),
  114. .imageFormat = d.surfaceFormat.format,
  115. .imageColorSpace = d.surfaceFormat.colorSpace,
  116. .imageExtent = d.size,
  117. .imageArrayLayers = 1,
  118. .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
  119. .imageSharingMode = d.sharingMode,
  120. .queueFamilyIndexCount = static_cast<u32>(d.queueFamilies.getLength()),
  121. .pQueueFamilyIndices = &d.queueFamilies[0],
  122. .preTransform = caps.currentTransform,
  123. .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
  124. .presentMode = d.presentMode,
  125. .clipped = VK_TRUE,
  126. .oldSwapchain = VK_NULL_HANDLE};
  127. VK_CHECK_TRUE(vkCreateSwapchainKHR(d.base, &ci, nullptr, &handle));
  128. device = d.base;
  129. return false;
  130. }
  131. SwapchainResult Swapchain::nextImage(
  132. u32& imageIndex, Semaphore& s, u64 timeout) {
  133. VkResult r = vkAcquireNextImageKHR(
  134. device, handle, timeout, s, VK_NULL_HANDLE, &imageIndex);
  135. if(r == VK_SUBOPTIMAL_KHR) {
  136. return SwapchainResult::RECREATE;
  137. } else if(r == VK_ERROR_OUT_OF_DATE_KHR) {
  138. return SwapchainResult::ERROR_RECREATE;
  139. }
  140. VK_CHECK(SwapchainResult::ERROR, r);
  141. return SwapchainResult::SUCCESS;
  142. }
  143. bool ShaderModule::init(VkDevice d, const char* path) {
  144. ShaderModule::~ShaderModule();
  145. List<char> f;
  146. if(Core::readFile(f, path)) {
  147. return true;
  148. }
  149. size_t l = f.getLength() - 1;
  150. if((l % 4) != 0) {
  151. VK_REPORT_ERROR("Shader size is not a multiple of 4");
  152. return true;
  153. }
  154. VkShaderModuleCreateInfo info = {
  155. .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
  156. .codeSize = l,
  157. .pCode = reinterpret_cast<u32*>(static_cast<void*>(&f[0]))};
  158. VK_CHECK_TRUE(vkCreateShaderModule(d, &info, nullptr, &handle));
  159. device = d;
  160. return false;
  161. }
  162. bool PipelineLayout::init(VkDevice d) {
  163. PipelineLayout::~PipelineLayout();
  164. VkPipelineLayoutCreateInfo info = {
  165. .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
  166. VK_CHECK_TRUE(vkCreatePipelineLayout(d, &info, nullptr, &handle));
  167. device = d;
  168. return false;
  169. }
  170. bool SwapchainImages::init(const Swapchain& s, VkFormat format) {
  171. u32 c = 0;
  172. VK_CHECK_TRUE(vkGetSwapchainImagesKHR(s.device, s.handle, &c, nullptr));
  173. images.resize(c);
  174. imageViews.resize(c);
  175. renderFinishedSemaphore.resize(c);
  176. VK_CHECK_TRUE(vkGetSwapchainImagesKHR(s.device, s.handle, &c, &images[0]));
  177. for(u32 x = 0; x < c; x++) {
  178. if(imageViews[x].init(s.device, images[x], format)) {
  179. return true;
  180. } else if(renderFinishedSemaphore[x].init(s.device)) {
  181. return true;
  182. }
  183. }
  184. return false;
  185. }
  186. bool RenderPass::init(VkDevice d, VkFormat format) {
  187. RenderPass::~RenderPass();
  188. VkAttachmentDescription c = {
  189. .format = format,
  190. .samples = VK_SAMPLE_COUNT_1_BIT,
  191. .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
  192. .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
  193. .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
  194. .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
  195. .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
  196. .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR};
  197. VkAttachmentReference ca = {
  198. .attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
  199. VkSubpassDescription subpass = {
  200. .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
  201. .colorAttachmentCount = 1,
  202. .pColorAttachments = &ca};
  203. VkSubpassDependency dependency = {
  204. .srcSubpass = VK_SUBPASS_EXTERNAL,
  205. .dstSubpass = 0,
  206. .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  207. .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  208. .srcAccessMask = 0,
  209. .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  210. };
  211. VkRenderPassCreateInfo info = {
  212. .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
  213. .attachmentCount = 1,
  214. .pAttachments = &c,
  215. .subpassCount = 1,
  216. .pSubpasses = &subpass,
  217. .dependencyCount = 1,
  218. .pDependencies = &dependency};
  219. VK_CHECK_TRUE(vkCreateRenderPass(d, &info, nullptr, &handle));
  220. device = d;
  221. return false;
  222. }
  223. Pipeline::Pipeline() : viewport{.maxDepth = 1.0f}, scissor{} {
  224. }
  225. void Pipeline::updateSize(u32 width, u32 height) {
  226. viewport.width = static_cast<float>(width);
  227. viewport.height = static_cast<float>(height);
  228. scissor.extent.width = width;
  229. scissor.extent.height = height;
  230. }
  231. bool Pipeline::init(
  232. PipelineLayout& pl, RenderPass& rp,
  233. const List<VkVertexInputBindingDescription>& bd,
  234. const List<VkVertexInputAttributeDescription>& ad) {
  235. Pipeline::~Pipeline();
  236. ShaderModule vertexShaderModule;
  237. ShaderModule fragmentShaderModule;
  238. if(vertexShaderModule.init(pl.device, "shaders/vertex.spv") ||
  239. fragmentShaderModule.init(pl.device, "shaders/fragment.spv")) {
  240. return true;
  241. }
  242. VkPipelineShaderStageCreateInfo stages[2] = {
  243. {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  244. .stage = VK_SHADER_STAGE_VERTEX_BIT,
  245. .module = vertexShaderModule,
  246. .pName = "main"},
  247. {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  248. .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
  249. .module = fragmentShaderModule,
  250. .pName = "main"}};
  251. VkPipelineVertexInputStateCreateInfo vertexInputState = {
  252. .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
  253. .vertexBindingDescriptionCount = static_cast<u32>(bd.getLength()),
  254. .pVertexBindingDescriptions = &bd[0],
  255. .vertexAttributeDescriptionCount = static_cast<u32>(ad.getLength()),
  256. .pVertexAttributeDescriptions = &ad[0]};
  257. VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {
  258. .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
  259. .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
  260. .primitiveRestartEnable = false};
  261. VkPipelineViewportStateCreateInfo viewportState = {
  262. .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
  263. .viewportCount = 1,
  264. .pViewports = &viewport,
  265. .scissorCount = 1,
  266. .pScissors = &scissor};
  267. VkPipelineRasterizationStateCreateInfo rasterizationState = {
  268. .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
  269. .depthClampEnable = false,
  270. .rasterizerDiscardEnable = false,
  271. .polygonMode = VK_POLYGON_MODE_FILL,
  272. .cullMode = VK_CULL_MODE_BACK_BIT,
  273. .frontFace = VK_FRONT_FACE_CLOCKWISE,
  274. .depthBiasEnable = false,
  275. .depthBiasConstantFactor = 0.0f,
  276. .depthBiasClamp = 0.0f,
  277. .depthBiasSlopeFactor = 0.0f,
  278. .lineWidth = 1.0f};
  279. VkPipelineMultisampleStateCreateInfo multisampleState = {
  280. .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
  281. .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
  282. .sampleShadingEnable = false,
  283. .minSampleShading = 1.0f,
  284. .pSampleMask = nullptr,
  285. .alphaToCoverageEnable = false,
  286. .alphaToOneEnable = false};
  287. VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
  288. .blendEnable = false,
  289. .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
  290. .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
  291. .colorBlendOp = VK_BLEND_OP_ADD,
  292. .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
  293. .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
  294. .alphaBlendOp = VK_BLEND_OP_ADD,
  295. .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
  296. VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
  297. VkPipelineColorBlendStateCreateInfo colorBlendState = {
  298. .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
  299. .logicOpEnable = false,
  300. .logicOp = VK_LOGIC_OP_COPY,
  301. .attachmentCount = 1,
  302. .pAttachments = &colorBlendAttachmentState,
  303. .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}};
  304. Core::Array<VkDynamicState, 2> dynamicStates = {
  305. {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}};
  306. VkPipelineDynamicStateCreateInfo dynamicState = {
  307. .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
  308. .dynamicStateCount = dynamicStates.getLength(),
  309. .pDynamicStates = dynamicStates.begin()};
  310. VkGraphicsPipelineCreateInfo info = {
  311. .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
  312. .stageCount = 2,
  313. .pStages = stages,
  314. .pVertexInputState = &vertexInputState,
  315. .pInputAssemblyState = &inputAssemblyState,
  316. .pTessellationState = nullptr,
  317. .pViewportState = &viewportState,
  318. .pRasterizationState = &rasterizationState,
  319. .pMultisampleState = &multisampleState,
  320. .pDepthStencilState = nullptr,
  321. .pColorBlendState = &colorBlendState,
  322. .pDynamicState = &dynamicState,
  323. .layout = pl,
  324. .renderPass = rp,
  325. .subpass = 0,
  326. .basePipelineHandle = VK_NULL_HANDLE,
  327. .basePipelineIndex = -1};
  328. VK_CHECK_TRUE(vkCreateGraphicsPipelines(
  329. pl.device, VK_NULL_HANDLE, 1, &info, nullptr, &handle));
  330. device = pl.device;
  331. return false;
  332. }
  333. bool CommandPool::init(VkDevice d, u32 queueFamily) {
  334. CommandPool::~CommandPool();
  335. VkCommandPoolCreateInfo info = {
  336. .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
  337. .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
  338. .queueFamilyIndex = queueFamily};
  339. VK_CHECK_TRUE(vkCreateCommandPool(d, &info, nullptr, &handle));
  340. device = d;
  341. return false;
  342. }
  343. bool CommandBuffer::init(CommandPool& cp) {
  344. CommandBuffer::~CommandBuffer();
  345. VkCommandBufferAllocateInfo info = {
  346. .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
  347. .commandPool = cp,
  348. .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
  349. .commandBufferCount = 1};
  350. VK_CHECK_TRUE(vkAllocateCommandBuffers(cp.device, &info, &handle));
  351. device = cp.device;
  352. return false;
  353. }
  354. void CommandBuffer::reset() {
  355. VK_CHECK_VOID(vkResetCommandBuffer(handle, 0));
  356. }
  357. void CommandBuffer::begin() {
  358. VkCommandBufferBeginInfo info = {
  359. .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
  360. VK_CHECK_VOID(vkBeginCommandBuffer(handle, &info));
  361. }
  362. void CommandBuffer::end() {
  363. VK_CHECK_VOID(vkEndCommandBuffer(handle));
  364. }
  365. void CommandBuffer::beginRenderPass(
  366. RenderPass& rp, Framebuffer& f, const VkExtent2D& size) {
  367. VkClearValue v = {.color = {.float32 = {0.0f, 0.0f, 0.0f, 1.0f}}};
  368. VkRenderPassBeginInfo info = {
  369. .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
  370. .renderPass = rp,
  371. .framebuffer = f,
  372. .renderArea = {.offset = {0, 0}, .extent = size},
  373. .clearValueCount = 1,
  374. .pClearValues = &v};
  375. vkCmdBeginRenderPass(handle, &info, VK_SUBPASS_CONTENTS_INLINE);
  376. }
  377. void CommandBuffer::endRenderPass() {
  378. vkCmdEndRenderPass(handle);
  379. }
  380. void CommandBuffer::bindPipeline(Pipeline& p) {
  381. vkCmdBindPipeline(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, p);
  382. vkCmdSetViewport(handle, 0, 1, &p.viewport);
  383. vkCmdSetScissor(handle, 0, 1, &p.scissor);
  384. }
  385. void CommandBuffer::draw(u32 vertices) {
  386. vkCmdDraw(handle, vertices, 1, 0, 0);
  387. }
  388. bool Queue::init(VkDevice d, u32 queueFamily) {
  389. vkGetDeviceQueue(d, queueFamily, 0, &handle);
  390. return handle == VK_NULL_HANDLE;
  391. }
  392. void Queue::submit(
  393. CommandBuffer& cb, Fence& f, Semaphore& wait, Semaphore& signal,
  394. VkPipelineStageFlags flags) {
  395. VkSubmitInfo info = {
  396. .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
  397. .waitSemaphoreCount = 1,
  398. .pWaitSemaphores = wait,
  399. .pWaitDstStageMask = &flags,
  400. .commandBufferCount = 1,
  401. .pCommandBuffers = cb,
  402. .signalSemaphoreCount = 1,
  403. .pSignalSemaphores = signal};
  404. VK_CHECK_VOID(vkQueueSubmit(handle, 1, &info, f));
  405. }
  406. SwapchainResult Queue::present(Semaphore& signal, Swapchain& s, u32 index) {
  407. VkPresentInfoKHR info = {
  408. .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
  409. .waitSemaphoreCount = 1,
  410. .pWaitSemaphores = signal,
  411. .swapchainCount = 1,
  412. .pSwapchains = s,
  413. .pImageIndices = &index};
  414. VkResult r = vkQueuePresentKHR(handle, &info);
  415. if(r == VK_SUBOPTIMAL_KHR) {
  416. return SwapchainResult::RECREATE;
  417. } else if(r == VK_ERROR_OUT_OF_DATE_KHR) {
  418. return SwapchainResult::ERROR_RECREATE;
  419. }
  420. VK_CHECK(SwapchainResult::ERROR, r);
  421. return SwapchainResult::SUCCESS;
  422. }
  423. VertexBuffer::VertexBuffer() : BaseWrapper<VkBuffer>(), memory(VK_NULL_HANDLE) {
  424. }
  425. VertexBuffer::~VertexBuffer() {
  426. if(device != VK_NULL_HANDLE) {
  427. vkDestroyBuffer(device, handle, nullptr);
  428. vkFreeMemory(device, memory, nullptr);
  429. }
  430. device = VK_NULL_HANDLE;
  431. handle = VK_NULL_HANDLE;
  432. }
  433. bool VertexBuffer::init(Base& b, size_t size, const void* data) {
  434. VkBufferCreateInfo info = {
  435. .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
  436. .size = size,
  437. .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
  438. .sharingMode = VK_SHARING_MODE_EXCLUSIVE};
  439. VK_CHECK_TRUE(vkCreateBuffer(b, &info, nullptr, &handle));
  440. device = b;
  441. VkMemoryRequirements m;
  442. vkGetBufferMemoryRequirements(device, handle, &m);
  443. VkMemoryAllocateInfo aInfo = {
  444. .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
  445. .allocationSize = m.size,
  446. .memoryTypeIndex = b.findMemoryType(
  447. m.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  448. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)};
  449. VK_CHECK_TRUE(vkAllocateMemory(device, &aInfo, nullptr, &memory));
  450. VK_CHECK_TRUE(vkBindBufferMemory(device, handle, memory, 0));
  451. void* destination = nullptr;
  452. VK_CHECK_TRUE(vkMapMemory(device, memory, 0, size, 0, &destination));
  453. memcpy(destination, data, size);
  454. vkUnmapMemory(device, memory);
  455. return false;
  456. }
  457. struct VulkanDummy {
  458. Core::Vulkan::Base base{};
  459. struct BaseData {
  460. u32 graphicsFamily = 0;
  461. u32 presentFamily = 0;
  462. VkSurfaceFormatKHR surfaceFormat{};
  463. VkPresentModeKHR presentMode{};
  464. };
  465. BaseData baseData{};
  466. Queue graphicsQueue{};
  467. Queue presentQueue{};
  468. VkExtent2D swapchainSize{};
  469. Swapchain swapchain{};
  470. SwapchainImages images{};
  471. PipelineLayout pipelineLayout{};
  472. RenderPass renderPass{};
  473. Pipeline pipeline{};
  474. List<Vulkan::Framebuffer> framebuffers{};
  475. CommandPool commandPool{};
  476. size_t currentFrame = 0;
  477. struct Frame {
  478. CommandBuffer commandBuffer{};
  479. Semaphore imageAvailableSemaphore{};
  480. Fence inFlightFence{};
  481. };
  482. Core::Array<Frame, 2> frames{};
  483. struct Vertex {
  484. Core::Vector2 position;
  485. Core::Vector3 color;
  486. static auto getBindingDescription() {
  487. VkVertexInputBindingDescription d = {
  488. .binding = 0,
  489. .stride = sizeof(Vertex),
  490. .inputRate = VK_VERTEX_INPUT_RATE_VERTEX};
  491. return d;
  492. }
  493. static auto getAttributeDescriptions() {
  494. Core::Array<VkVertexInputAttributeDescription, 2> d = {
  495. {{.location = 0,
  496. .binding = 0,
  497. .format = VK_FORMAT_R32G32_SFLOAT,
  498. .offset = offsetof(Vertex, position)},
  499. {.location = 1,
  500. .binding = 0,
  501. .format = VK_FORMAT_R32G32B32_SFLOAT,
  502. .offset = offsetof(Vertex, color)}}};
  503. return d;
  504. }
  505. };
  506. VertexBuffer vertexBuffer{};
  507. static int getSurfaceFormatPoints(const VkSurfaceFormatKHR& sf) {
  508. if(sf.format == VK_FORMAT_B8G8R8A8_UNORM &&
  509. sf.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
  510. return 10;
  511. }
  512. return 1;
  513. }
  514. static int getSurfacePresentModePoints(VkPresentModeKHR m) {
  515. if(m == VK_PRESENT_MODE_MAILBOX_KHR) {
  516. return 5;
  517. } else if(m == VK_PRESENT_MODE_FIFO_KHR) {
  518. return 2;
  519. }
  520. return 0;
  521. }
  522. bool getSwapchainSize(VkExtent2D* size) {
  523. VkSurfaceCapabilitiesKHR c = {};
  524. if(base.getSurfaceCapabilities(c)) {
  525. return true;
  526. }
  527. if(c.currentExtent.width != 0xFFFF'FFFFu &&
  528. c.currentExtent.height != 0xFFFF'FFFFu) {
  529. *size = c.currentExtent;
  530. Core::logInfo("Swapchain size: #x#", size->width, size->height);
  531. return false;
  532. }
  533. int w = 0;
  534. int h = 0;
  535. glfwGetFramebufferSize(Core::Window::get(), &w, &h);
  536. if(w <= 0 || h <= 0) {
  537. Core::logError("Could not get framebuffer size");
  538. return true;
  539. }
  540. Core::logInfo("Framebuffer size: #x#", w, h);
  541. size->width = Core::clamp(
  542. static_cast<u32>(w), c.minImageExtent.width,
  543. c.maxImageExtent.width);
  544. size->height = Core::clamp(
  545. static_cast<u32>(h), c.minImageExtent.height,
  546. c.maxImageExtent.height);
  547. Core::logInfo("Swapchain size: #x#", size->width, size->height);
  548. return false;
  549. }
  550. bool initSwapchain() {
  551. Vulkan::Swapchain::Data d = {
  552. .base = base,
  553. .surfaceFormat = baseData.surfaceFormat,
  554. .presentMode = baseData.presentMode};
  555. if(getSwapchainSize(&d.size)) {
  556. Core::logError("Could not retrieve any swapchain size");
  557. return true;
  558. }
  559. swapchainSize = d.size;
  560. d.queueFamilies.add(baseData.graphicsFamily);
  561. if(baseData.graphicsFamily != baseData.presentFamily) {
  562. d.queueFamilies.add(baseData.presentFamily);
  563. d.sharingMode = VK_SHARING_MODE_CONCURRENT;
  564. } else {
  565. d.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  566. }
  567. return swapchain.init(d);
  568. }
  569. bool initDevice() {
  570. bool same = baseData.graphicsFamily == baseData.presentFamily;
  571. List<Vulkan::DeviceQueueData> data;
  572. data.add(baseData.graphicsFamily, 1.0f);
  573. if(!same) {
  574. data.add(baseData.presentFamily, 1.0f);
  575. }
  576. List<const char*> extensions;
  577. extensions.add(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
  578. if(base.initDevice(data, extensions)) {
  579. return true;
  580. } else if(graphicsQueue.init(base, baseData.graphicsFamily)) {
  581. Core::logError("Cannot get device graphics queue");
  582. return true;
  583. } else if(presentQueue.init(base, baseData.presentFamily)) {
  584. Core::logError("Cannot get device present queue");
  585. return true;
  586. }
  587. return false;
  588. }
  589. static int getDevicePoints(Vulkan::Base& b, BaseData& d) {
  590. int points = 0;
  591. VkPhysicalDeviceProperties p;
  592. b.getPhysicalDeviceProperties(p);
  593. Core::logInfo("Checking '#'", p.deviceName);
  594. switch(p.deviceType) {
  595. case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: points += 100; break;
  596. case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: points += 50; break;
  597. case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: points += 20; break;
  598. default: break;
  599. }
  600. d.graphicsFamily = b.findQueueFamily(VK_QUEUE_GRAPHICS_BIT);
  601. if(d.graphicsFamily == Vulkan::INVALID_QUEUE_FAMILY) {
  602. Core::logInfo("> ... has no graphics family");
  603. points = -1000;
  604. }
  605. d.presentFamily = b.findSurfaceQueueFamily();
  606. if(d.presentFamily == Vulkan::INVALID_QUEUE_FAMILY) {
  607. Core::logInfo("> ... has no present family");
  608. points = -1000;
  609. }
  610. if(!b.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
  611. Core::logInfo("> ... has no swapchain support");
  612. points = -1000;
  613. }
  614. if(b.findSurfaceFormat(d.surfaceFormat, getSurfaceFormatPoints)) {
  615. Core::logInfo("> ... has no matching surface format");
  616. points = -1000;
  617. } else {
  618. points += getSurfaceFormatPoints(d.surfaceFormat);
  619. }
  620. if(b.findSurfacePresentMode(
  621. d.presentMode, getSurfacePresentModePoints)) {
  622. Core::logInfo("> ... has no matching present mode");
  623. points = -1000;
  624. } else {
  625. points += getSurfacePresentModePoints(d.presentMode);
  626. }
  627. Core::logInfo("> Final points: #", points);
  628. return points;
  629. }
  630. bool initPhysicalDevice() {
  631. Core::logInfo("Searching for physical devices ...");
  632. if(base.findPhysicalDevice(baseData, getDevicePoints)) {
  633. Core::logError("No matching physical device was found");
  634. return true;
  635. }
  636. VkPhysicalDeviceProperties p;
  637. base.getPhysicalDeviceProperties(p);
  638. Core::logInfo("Best Device: #", p.deviceName);
  639. return false;
  640. }
  641. bool initSwapchainImages() {
  642. if(images.init(swapchain, baseData.surfaceFormat.format)) {
  643. Core::logError("Could not get swapchain images");
  644. return true;
  645. }
  646. Core::logInfo("Found # images", images.images.getLength());
  647. return false;
  648. }
  649. bool initPipeline() {
  650. pipeline.updateSize(swapchainSize.width, swapchainSize.height);
  651. List<VkVertexInputBindingDescription> bd;
  652. bd.add(Vertex::getBindingDescription());
  653. List<VkVertexInputAttributeDescription> ad;
  654. for(auto a : Vertex::getAttributeDescriptions()) {
  655. ad.add(a);
  656. }
  657. return pipeline.init(pipelineLayout, renderPass, bd, ad);
  658. }
  659. bool initFramebuffers() {
  660. framebuffers.resize(images.imageViews.getLength());
  661. size_t i = 0;
  662. for(Framebuffer& f : framebuffers) {
  663. if(f.init(
  664. images.imageViews[i++], renderPass, swapchainSize.width,
  665. swapchainSize.height)) {
  666. return true;
  667. }
  668. }
  669. return false;
  670. }
  671. void fillCommandBuffer(CommandBuffer& cb, u32 index) {
  672. cb.begin();
  673. cb.beginRenderPass(renderPass, framebuffers[index], swapchainSize);
  674. cb.bindPipeline(pipeline);
  675. VkDeviceSize offset = 0;
  676. vkCmdBindVertexBuffers(cb, 0, 1, vertexBuffer, &offset);
  677. cb.draw(3);
  678. cb.endRenderPass();
  679. cb.end();
  680. }
  681. bool initFrames() {
  682. for(Frame& f : frames) {
  683. if(f.commandBuffer.init(commandPool) ||
  684. f.imageAvailableSemaphore.init(base) ||
  685. f.inFlightFence.init(base)) {
  686. return true;
  687. }
  688. }
  689. return false;
  690. }
  691. bool initVertexBuffer() {
  692. List<Vertex> l;
  693. l.add(Core::Vector2{-0.5f, -0.5f}, Core::Vector3{1.0, 1.0, 1.0});
  694. l.add(Core::Vector2{0.5f, 0.0f}, Core::Vector3{0.0, 1.0, 1.0});
  695. l.add(Core::Vector2{0.0f, 0.5f}, Core::Vector3{1.0, 1.0, 0.0});
  696. return vertexBuffer.init(base, sizeof(l[0]) * l.getLength(), &l[0]);
  697. }
  698. bool init() {
  699. return base.init() || initPhysicalDevice() || initDevice() ||
  700. initSwapchain() || initSwapchainImages() ||
  701. pipelineLayout.init(base) ||
  702. renderPass.init(base, baseData.surfaceFormat.format) ||
  703. initPipeline() || initFramebuffers() ||
  704. commandPool.init(base, baseData.graphicsFamily) ||
  705. initFrames() || initVertexBuffer();
  706. }
  707. bool recreateSwapchain() {
  708. Core::logInfo("Recreate swapchain");
  709. base.waitForIdle();
  710. if(initSwapchain() || initSwapchainImages() || initFramebuffers()) {
  711. return true;
  712. }
  713. pipeline.updateSize(swapchainSize.width, swapchainSize.height);
  714. return false;
  715. }
  716. bool render() {
  717. Frame& f = frames[currentFrame];
  718. f.inFlightFence.waitFor();
  719. u32 imageIndex = 0;
  720. switch(swapchain.nextImage(imageIndex, f.imageAvailableSemaphore)) {
  721. case SwapchainResult::SUCCESS: break;
  722. case SwapchainResult::RECREATE: break;
  723. case SwapchainResult::ERROR_RECREATE: return recreateSwapchain();
  724. case SwapchainResult::ERROR: return true;
  725. }
  726. // https://docs.vulkan.org/guide/latest/swapchain_semaphore_reuse.html
  727. Semaphore& renderSemaphore = images.renderFinishedSemaphore[imageIndex];
  728. f.inFlightFence.reset();
  729. f.commandBuffer.reset();
  730. fillCommandBuffer(f.commandBuffer, imageIndex);
  731. graphicsQueue.submit(
  732. f.commandBuffer, f.inFlightFence, f.imageAvailableSemaphore,
  733. renderSemaphore, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
  734. bool recreate = false;
  735. switch(presentQueue.present(renderSemaphore, swapchain, imageIndex)) {
  736. case SwapchainResult::SUCCESS: break;
  737. case SwapchainResult::RECREATE:
  738. case SwapchainResult::ERROR_RECREATE: recreate = true;
  739. case SwapchainResult::ERROR: break;
  740. }
  741. currentFrame = (currentFrame + 1) % frames.getLength();
  742. if(recreate || Core::Window::hasSizeChanged()) {
  743. recreateSwapchain();
  744. }
  745. return false;
  746. }
  747. };
  748. static Core::UniquePointer<VulkanDummy> dummy;
  749. bool Vulkan::init() {
  750. dummy = new VulkanDummy();
  751. return dummy->init();
  752. }
  753. void Vulkan::render() {
  754. dummy->render();
  755. }
  756. void Vulkan::destroy() {
  757. dummy->base.waitForIdle();
  758. dummy = nullptr;
  759. }