Graphics.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. #include "Graphics.h"
  2. #include "Buffer.h"
  3. #include "SDL_vulkan.h"
  4. #include "window/Window.h"
  5. #include "common/Exception.h"
  6. #include "Shader.h"
  7. #include <vector>
  8. #include <cstring>
  9. #include <set>
  10. #include <fstream>
  11. #include <iostream>
  12. namespace love {
  13. namespace graphics {
  14. namespace vulkan {
  15. const std::vector<const char*> validationLayers = {
  16. "VK_LAYER_KHRONOS_validation"
  17. };
  18. const std::vector<const char*> deviceExtensions = {
  19. VK_KHR_SWAPCHAIN_EXTENSION_NAME
  20. };
  21. #ifdef NDEBUG
  22. const bool enableValidationLayers = false;
  23. #else
  24. const bool enableValidationLayers = true;
  25. #endif
  26. const int MAX_FRAMES_IN_FLIGHT = 2;
  27. static std::vector<char> readFile(const std::string& filename) {
  28. std::ifstream file(filename, std::ios::ate | std::ios::binary);
  29. if (!file.is_open()) {
  30. throw std::runtime_error("failed to open file!");
  31. }
  32. size_t fileSize = (size_t)file.tellg();
  33. std::vector<char> buffer(fileSize);
  34. file.seekg(0);
  35. file.read(buffer.data(), fileSize);
  36. file.close();
  37. return buffer;
  38. }
  39. const char* Graphics::getName() const {
  40. return "love.graphics.vulkan";
  41. }
  42. Graphics::Graphics() {
  43. }
  44. void Graphics::initVulkan() {
  45. if (!init) {
  46. init = true;
  47. createVulkanInstance();
  48. createSurface();
  49. pickPhysicalDevice();
  50. createLogicalDevice();
  51. initVMA();
  52. createSwapChain();
  53. createImageViews();
  54. createRenderPass();
  55. createDefaultShaders();
  56. createDescriptorSetLayout();
  57. createGraphicsPipeline();
  58. createFramebuffers();
  59. createCommandPool();
  60. createCommandBuffers();
  61. createUniformBuffers();
  62. createDescriptorPool();
  63. createDescriptorSets();
  64. createSyncObjects();
  65. startRecordingGraphicsCommands();
  66. }
  67. }
  68. Graphics::~Graphics() {
  69. cleanup();
  70. }
  71. // START OVERRIDEN FUNCTIONS
  72. love::graphics::Buffer* Graphics::newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void* data, size_t size, size_t arraylength) {
  73. std::cout << "newBuffer ";
  74. return nullptr;
  75. }
  76. void Graphics::startRecordingGraphicsCommands() {
  77. vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
  78. while (true) {
  79. VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
  80. if (result == VK_ERROR_OUT_OF_DATE_KHR) {
  81. recreateSwapChain();
  82. continue;
  83. }
  84. else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
  85. throw love::Exception("failed to acquire swap chain image");
  86. }
  87. break;
  88. }
  89. VkCommandBufferBeginInfo beginInfo{};
  90. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  91. beginInfo.flags = 0;
  92. beginInfo.pInheritanceInfo = nullptr;
  93. std::cout << "beginCommandBuffer(imageIndex=" << imageIndex << ") ";
  94. if (vkBeginCommandBuffer(commandBuffers.at(imageIndex), &beginInfo) != VK_SUCCESS) {
  95. throw love::Exception("failed to begin recording command buffer");
  96. }
  97. VkRenderPassBeginInfo renderPassInfo{};
  98. renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  99. renderPassInfo.renderPass = renderPass;
  100. renderPassInfo.framebuffer = swapChainFramBuffers.at(imageIndex);
  101. renderPassInfo.renderArea.offset = { 0, 0 };
  102. renderPassInfo.renderArea.extent = swapChainExtent;
  103. renderPassInfo.clearValueCount = 1;
  104. renderPassInfo.pClearValues = &clearColor;
  105. const auto& commandBuffer = commandBuffers.at(imageIndex);
  106. vkCmdBeginRenderPass(commandBuffers.at(imageIndex), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
  107. vkCmdBindPipeline(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
  108. }
  109. void Graphics::endRecordingGraphicsCommands() {
  110. const auto& commandBuffer = commandBuffers.at(imageIndex);
  111. std::cout << "endCommandBuffer(imageIndex=" << imageIndex << ") ";
  112. vkCmdEndRenderPass(commandBuffers.at(imageIndex));
  113. if (vkEndCommandBuffer(commandBuffers.at(imageIndex)) != VK_SUCCESS) {
  114. throw love::Exception("failed to record command buffer");
  115. }
  116. }
  117. void Graphics::present(void* screenshotCallbackdata) {
  118. flushBatchedDraws();
  119. endRecordingGraphicsCommands();
  120. prepareDraw(currentFrame);
  121. if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
  122. vkWaitForFences(device, 1, &imagesInFlight.at(imageIndex), VK_TRUE, UINT64_MAX);
  123. }
  124. imagesInFlight[imageIndex] = inFlightFences[currentFrame];
  125. VkSubmitInfo submitInfo{};
  126. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  127. VkSemaphore waitSemaphores[] = { imageAvailableSemaphores.at(currentFrame) };
  128. VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
  129. submitInfo.waitSemaphoreCount = 1;
  130. submitInfo.pWaitSemaphores = waitSemaphores;
  131. submitInfo.pWaitDstStageMask = waitStages;
  132. submitInfo.commandBufferCount = 1;
  133. submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
  134. VkSemaphore signalSemaphores[] = { renderFinishedSemaphores.at(currentFrame) };
  135. submitInfo.signalSemaphoreCount = 1;
  136. submitInfo.pSignalSemaphores = signalSemaphores;
  137. vkResetFences(device, 1, &inFlightFences[currentFrame]);
  138. if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences.at(currentFrame)) != VK_SUCCESS) {
  139. throw love::Exception("failed to submit draw command buffer");
  140. }
  141. VkPresentInfoKHR presentInfo{};
  142. presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  143. presentInfo.waitSemaphoreCount = 1;
  144. presentInfo.pWaitSemaphores = signalSemaphores;
  145. VkSwapchainKHR swapChains[] = { swapChain };
  146. presentInfo.swapchainCount = 1;
  147. presentInfo.pSwapchains = swapChains;
  148. presentInfo.pImageIndices = &imageIndex;
  149. VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo);
  150. if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
  151. framebufferResized = false;
  152. recreateSwapChain();
  153. }
  154. else if (result != VK_SUCCESS) {
  155. throw love::Exception("failed to present swap chain image");
  156. }
  157. currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
  158. std::cout << "present" << std::endl;
  159. startRecordingGraphicsCommands();
  160. }
  161. void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) {
  162. std::cout << "setViewPortSize ";
  163. recreateSwapChain();
  164. }
  165. bool Graphics::setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) {
  166. std::cout << "setMode ";
  167. initCapabilities();
  168. created = true;
  169. if (batchedDrawState.vb[0] == nullptr)
  170. {
  171. // Initial sizes that should be good enough for most cases. It will
  172. // resize to fit if needed, later.
  173. batchedDrawState.vb[0] = new StreamBuffer(vmaAllocator, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
  174. batchedDrawState.vb[1] = new StreamBuffer(vmaAllocator, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
  175. batchedDrawState.indexBuffer = new StreamBuffer(vmaAllocator, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
  176. }
  177. return true;
  178. }
  179. void Graphics::initCapabilities() {
  180. std::cout << "initCapabilities ";
  181. VkPhysicalDeviceProperties properties;
  182. vkGetPhysicalDeviceProperties(physicalDevice, &properties);
  183. // todo
  184. capabilities.features[FEATURE_MULTI_RENDER_TARGET_FORMATS] = false;
  185. capabilities.features[FEATURE_CLAMP_ZERO] = false;
  186. capabilities.features[FEATURE_CLAMP_ONE] = false;
  187. capabilities.features[FEATURE_BLEND_MINMAX] = false;
  188. capabilities.features[FEATURE_LIGHTEN] = false;
  189. capabilities.features[FEATURE_FULL_NPOT] = false;
  190. capabilities.features[FEATURE_PIXEL_SHADER_HIGHP] = false;
  191. capabilities.features[FEATURE_SHADER_DERIVATIVES] = false;
  192. capabilities.features[FEATURE_GLSL3] = false;
  193. capabilities.features[FEATURE_GLSL4] = false;
  194. capabilities.features[FEATURE_INSTANCING] = false;
  195. capabilities.features[FEATURE_TEXEL_BUFFER] = false;
  196. capabilities.features[FEATURE_INDEX_BUFFER_32BIT] = true;
  197. capabilities.features[FEATURE_COPY_BUFFER] = false;
  198. capabilities.features[FEATURE_COPY_BUFFER_TO_TEXTURE] = false;
  199. capabilities.features[FEATURE_COPY_TEXTURE_TO_BUFFER] = false;
  200. capabilities.features[FEATURE_COPY_RENDER_TARGET_TO_BUFFER] = false;
  201. static_assert(FEATURE_MAX_ENUM == 17, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
  202. capabilities.limits[LIMIT_POINT_SIZE] = properties.limits.pointSizeRange[1];
  203. capabilities.limits[LIMIT_TEXTURE_SIZE] = properties.limits.maxImageDimension2D;
  204. capabilities.limits[LIMIT_TEXTURE_LAYERS] = properties.limits.maxImageArrayLayers;
  205. capabilities.limits[LIMIT_VOLUME_TEXTURE_SIZE] = properties.limits.maxImageDimension3D;
  206. capabilities.limits[LIMIT_CUBE_TEXTURE_SIZE] = properties.limits.maxImageDimensionCube;
  207. capabilities.limits[LIMIT_TEXEL_BUFFER_SIZE] = properties.limits.maxTexelBufferElements; // ?
  208. capabilities.limits[LIMIT_SHADER_STORAGE_BUFFER_SIZE] = properties.limits.maxStorageBufferRange; // ?
  209. capabilities.limits[LIMIT_THREADGROUPS_X] = 0; // todo
  210. capabilities.limits[LIMIT_THREADGROUPS_Y] = 0; // todo
  211. capabilities.limits[LIMIT_THREADGROUPS_Z] = 0; // todo
  212. capabilities.limits[LIMIT_RENDER_TARGETS] = 1; // todo
  213. capabilities.limits[LIMIT_TEXTURE_MSAA] = 1; // todo
  214. capabilities.limits[LIMIT_ANISOTROPY] = 1.0f; // todo
  215. static_assert(LIMIT_MAX_ENUM == 13, "Graphics::initCapabilities must be updated when adding a new system limit!");
  216. capabilities.textureTypes[TEXTURE_2D] = true;
  217. capabilities.textureTypes[TEXTURE_VOLUME] = false;
  218. capabilities.textureTypes[TEXTURE_2D_ARRAY] = false;
  219. capabilities.textureTypes[TEXTURE_CUBE] = false;
  220. }
  221. void Graphics::unSetMode() {
  222. created = false;
  223. std::cout << "unSetMode ";
  224. }
  225. void Graphics::draw(const DrawIndexedCommand& cmd) {
  226. std::cout << "drawIndexed ";
  227. std::vector<VkBuffer> buffers;
  228. std::vector<VkDeviceSize> offsets;
  229. buffers.push_back((VkBuffer)cmd.buffers->info[0].buffer->getHandle());
  230. offsets.push_back((VkDeviceSize) 0);
  231. vkCmdBindDescriptorSets(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.at(currentFrame), 0, nullptr);
  232. vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, 1, buffers.data(), offsets.data());
  233. vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer) cmd.indexBuffer->getHandle(), 0, VK_INDEX_TYPE_UINT16);
  234. vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.indexCount), 1, 0, 0, 0);
  235. }
  236. graphics::StreamBuffer* Graphics::newStreamBuffer(BufferUsage type, size_t size) {
  237. std::cout << "newStreamBuffer ";
  238. return new StreamBuffer(vmaAllocator, type, size);
  239. }
  240. // END IMPLEMENTATION OVERRIDDEN FUNCTIONS
  241. void Graphics::prepareDraw(uint32_t currentImage) {
  242. auto& buffer = uniformBuffers.at(currentImage);
  243. Shader::UniformBufferObject ubo{};
  244. ubo.windowWidth = static_cast<float>(swapChainExtent.width);
  245. ubo.windowHeight = static_cast<float>(swapChainExtent.height);
  246. auto mappedInfo = buffer->map(0);
  247. memcpy(mappedInfo.data, &ubo, sizeof(ubo));
  248. buffer->unmap(0);
  249. }
  250. void Graphics::createVulkanInstance() {
  251. if (enableValidationLayers && !checkValidationSupport()) {
  252. throw love::Exception("validation layers requested, but not available");
  253. }
  254. VkApplicationInfo appInfo{};
  255. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  256. appInfo.pApplicationName = "LOVE";
  257. appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); //todo, get this version from somewhere else?
  258. appInfo.pEngineName = "LOVE Engine";
  259. appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); //todo, same as above
  260. appInfo.apiVersion = VK_API_VERSION_1_0;
  261. VkInstanceCreateInfo createInfo{};
  262. createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  263. createInfo.pApplicationInfo = &appInfo;
  264. createInfo.pNext = nullptr;
  265. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  266. const void* handle = window->getHandle();
  267. unsigned int count;
  268. if (SDL_Vulkan_GetInstanceExtensions((SDL_Window*)handle, &count, nullptr) != SDL_TRUE) {
  269. throw love::Exception("couldn't retrieve sdl vulkan extensions");
  270. }
  271. std::vector<const char*> extensions = {}; // can add more here
  272. size_t addition_extension_count = extensions.size();
  273. extensions.resize(addition_extension_count + count);
  274. if (SDL_Vulkan_GetInstanceExtensions((SDL_Window*)handle, &count, extensions.data() + addition_extension_count) != SDL_TRUE) {
  275. throw love::Exception("couldn't retrieve sdl vulkan extensions");
  276. }
  277. createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
  278. createInfo.ppEnabledExtensionNames = extensions.data();
  279. if (enableValidationLayers) {
  280. createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  281. createInfo.ppEnabledLayerNames = validationLayers.data();
  282. }
  283. else {
  284. createInfo.enabledLayerCount = 0;
  285. createInfo.ppEnabledLayerNames = nullptr;
  286. }
  287. if (vkCreateInstance(
  288. &createInfo,
  289. nullptr,
  290. &instance) != VK_SUCCESS) {
  291. throw love::Exception("couldn't create vulkan instance");
  292. }
  293. }
  294. bool Graphics::checkValidationSupport() {
  295. uint32_t layerCount;
  296. vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
  297. std::vector<VkLayerProperties> availableLayers(layerCount);
  298. vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
  299. for (const char* layerName : validationLayers) {
  300. bool layerFound = false;
  301. for (const auto& layerProperties : availableLayers) {
  302. if (strcmp(layerName, layerProperties.layerName) == 0) {
  303. layerFound = true;
  304. break;
  305. }
  306. }
  307. if (!layerFound) {
  308. return false;
  309. }
  310. }
  311. return true;
  312. }
  313. void Graphics::pickPhysicalDevice() {
  314. uint32_t deviceCount = 0;
  315. vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
  316. if (deviceCount == 0) {
  317. throw love::Exception("failed to find GPUs with Vulkan support");
  318. }
  319. std::vector<VkPhysicalDevice> devices(deviceCount);
  320. vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
  321. std::multimap<int, VkPhysicalDevice> candidates;
  322. for (const auto& device : devices) {
  323. int score = rateDeviceSuitability(device);
  324. candidates.insert(std::make_pair(score, device));
  325. }
  326. if (candidates.rbegin()->first > 0) {
  327. physicalDevice = candidates.rbegin()->second;
  328. }
  329. else {
  330. throw love::Exception("failed to find a suitable gpu");
  331. }
  332. }
  333. bool Graphics::checkDeviceExtensionSupport(VkPhysicalDevice device) {
  334. uint32_t extensionCount;
  335. vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
  336. std::vector<VkExtensionProperties> availableExtensions(extensionCount);
  337. vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
  338. std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
  339. for (const auto& extension : availableExtensions) {
  340. requiredExtensions.erase(extension.extensionName);
  341. }
  342. return requiredExtensions.empty();
  343. }
  344. int Graphics::rateDeviceSuitability(VkPhysicalDevice device) {
  345. VkPhysicalDeviceProperties deviceProperties;
  346. VkPhysicalDeviceFeatures deviceFeatures;
  347. vkGetPhysicalDeviceProperties(device, &deviceProperties);
  348. vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
  349. int score = 1;
  350. // optional
  351. if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
  352. score += 1000;
  353. }
  354. // definitely needed
  355. QueueFamilyIndices indices = findQueueFamilies(device);
  356. if (!indices.isComplete()) {
  357. score = 0;
  358. }
  359. bool extensionsSupported = checkDeviceExtensionSupport(device);
  360. if (!extensionsSupported) {
  361. score = 0;
  362. }
  363. if (extensionsSupported) {
  364. auto swapChainSupport = querySwapChainSupport(device);
  365. bool swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
  366. if (!swapChainAdequate) {
  367. score = 0;
  368. }
  369. }
  370. return score;
  371. }
  372. Graphics::QueueFamilyIndices Graphics::findQueueFamilies(VkPhysicalDevice device) {
  373. QueueFamilyIndices indices;
  374. uint32_t queueFamilyCount = 0;
  375. vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
  376. std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
  377. vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
  378. int i = 0;
  379. for (const auto& queueFamily : queueFamilies) {
  380. if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  381. indices.graphicsFamily = i;
  382. }
  383. VkBool32 presentSupport = false;
  384. vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
  385. if (presentSupport) {
  386. indices.presentFamily = i;
  387. }
  388. if (indices.isComplete()) {
  389. break;
  390. }
  391. i++;
  392. }
  393. return indices;
  394. }
  395. void Graphics::createLogicalDevice() {
  396. QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  397. std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
  398. std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
  399. float queuePriority = 1.0f;
  400. for (uint32_t queueFamily : uniqueQueueFamilies) {
  401. VkDeviceQueueCreateInfo queueCreateInfo{};
  402. queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  403. queueCreateInfo.queueFamilyIndex = queueFamily;
  404. queueCreateInfo.queueCount = 1;
  405. queueCreateInfo.pQueuePriorities = &queuePriority;
  406. queueCreateInfos.push_back(queueCreateInfo);
  407. }
  408. VkPhysicalDeviceFeatures deviceFeatures{};
  409. VkDeviceCreateInfo createInfo{};
  410. createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  411. createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
  412. createInfo.pQueueCreateInfos = queueCreateInfos.data();
  413. createInfo.pEnabledFeatures = &deviceFeatures;
  414. createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
  415. createInfo.ppEnabledExtensionNames = deviceExtensions.data();
  416. // can this be removed?
  417. if (enableValidationLayers) {
  418. createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  419. createInfo.ppEnabledLayerNames = validationLayers.data();
  420. }
  421. else {
  422. createInfo.enabledLayerCount = 0;
  423. }
  424. if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
  425. throw love::Exception("failed to create logical device");
  426. }
  427. vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
  428. vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
  429. }
  430. void Graphics::initVMA() {
  431. VmaVulkanFunctions vulkanFunctions = {};
  432. vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
  433. vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
  434. VmaAllocatorCreateInfo allocatorCreateInfo = {};
  435. allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
  436. allocatorCreateInfo.physicalDevice = physicalDevice;
  437. allocatorCreateInfo.device = device;
  438. allocatorCreateInfo.instance = instance;
  439. allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
  440. vmaCreateAllocator(&allocatorCreateInfo, &vmaAllocator);
  441. }
  442. void Graphics::createSurface() {
  443. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  444. const void* handle = window->getHandle();
  445. if (SDL_Vulkan_CreateSurface((SDL_Window*)handle, instance, &surface) != SDL_TRUE) {
  446. throw love::Exception("failed to create window surface");
  447. }
  448. }
  449. Graphics::SwapChainSupportDetails Graphics::querySwapChainSupport(VkPhysicalDevice device) {
  450. SwapChainSupportDetails details;
  451. vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
  452. uint32_t formatCount;
  453. vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
  454. if (formatCount != 0) {
  455. details.formats.resize(formatCount);
  456. vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
  457. }
  458. uint32_t presentModeCount;
  459. vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
  460. if (presentModeCount != 0) {
  461. details.presentModes.resize(presentModeCount);
  462. vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
  463. }
  464. return details;
  465. }
  466. void Graphics::createSwapChain() {
  467. SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);
  468. VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
  469. VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
  470. VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
  471. uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
  472. if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
  473. imageCount = swapChainSupport.capabilities.maxImageCount;
  474. }
  475. VkSwapchainCreateInfoKHR createInfo{};
  476. createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  477. createInfo.surface = surface;
  478. createInfo.minImageCount = imageCount;
  479. createInfo.imageFormat = surfaceFormat.format;
  480. createInfo.imageColorSpace = surfaceFormat.colorSpace;
  481. createInfo.imageExtent = extent;
  482. createInfo.imageArrayLayers = 1;
  483. createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  484. QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  485. uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };
  486. if (indices.graphicsFamily != indices.presentFamily) {
  487. createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  488. createInfo.queueFamilyIndexCount = 2;
  489. createInfo.pQueueFamilyIndices = queueFamilyIndices;
  490. }
  491. else {
  492. createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  493. createInfo.queueFamilyIndexCount = 0;
  494. createInfo.pQueueFamilyIndices = nullptr;
  495. }
  496. createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
  497. createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  498. createInfo.presentMode = presentMode;
  499. createInfo.clipped = VK_TRUE;
  500. createInfo.oldSwapchain = VK_NULL_HANDLE;
  501. if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
  502. throw love::Exception("failed to create swap chain");
  503. }
  504. vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
  505. swapChainImages.resize(imageCount);
  506. vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());
  507. swapChainImageFormat = surfaceFormat.format;
  508. swapChainExtent = extent;
  509. }
  510. VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
  511. for (const auto& availableFormat : availableFormats) {
  512. if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
  513. return availableFormat;
  514. }
  515. }
  516. return availableFormats[0];
  517. }
  518. VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) {
  519. // needed ?
  520. for (const auto& availablePresentMode : availablePresentModes) {
  521. if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
  522. return availablePresentMode;
  523. }
  524. }
  525. return VK_PRESENT_MODE_FIFO_KHR;
  526. }
  527. VkExtent2D Graphics::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) {
  528. if (capabilities.currentExtent.width != UINT32_MAX) {
  529. return capabilities.currentExtent;
  530. }
  531. else {
  532. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  533. const void* handle = window->getHandle();
  534. int width, height;
  535. // is this the equivalent of glfwGetFramebufferSize ?
  536. SDL_Vulkan_GetDrawableSize((SDL_Window*)handle, &width, &height);
  537. VkExtent2D actualExtent = {
  538. static_cast<uint32_t>(width),
  539. static_cast<uint32_t>(height)
  540. };
  541. actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
  542. actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
  543. return actualExtent;
  544. }
  545. }
  546. void Graphics::createImageViews() {
  547. swapChainImageViews.resize(swapChainImages.size());
  548. for (size_t i = 0; i < swapChainImages.size(); i++) {
  549. VkImageViewCreateInfo createInfo{};
  550. createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  551. createInfo.image = swapChainImages.at(i);
  552. createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  553. createInfo.format = swapChainImageFormat;
  554. createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  555. createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  556. createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  557. createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  558. createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  559. createInfo.subresourceRange.baseMipLevel = 0;
  560. createInfo.subresourceRange.levelCount = 1;
  561. createInfo.subresourceRange.baseArrayLayer = 0;
  562. createInfo.subresourceRange.layerCount = 1;
  563. if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews.at(i)) != VK_SUCCESS) {
  564. throw love::Exception("failed to create image views");
  565. }
  566. }
  567. }
  568. void Graphics::createRenderPass() {
  569. VkAttachmentDescription colorAttachment{};
  570. colorAttachment.format = swapChainImageFormat;
  571. colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
  572. colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  573. colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  574. colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  575. colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  576. colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  577. colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  578. VkAttachmentReference colorAttachmentRef{};
  579. colorAttachmentRef.attachment = 0;
  580. colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  581. VkSubpassDescription subpass{};
  582. subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  583. subpass.colorAttachmentCount = 1;
  584. subpass.pColorAttachments = &colorAttachmentRef;
  585. VkSubpassDependency dependency{};
  586. dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
  587. dependency.dstSubpass = 0;
  588. dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  589. dependency.srcAccessMask = 0;
  590. dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  591. dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  592. VkRenderPassCreateInfo renderPassInfo{};
  593. renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  594. renderPassInfo.attachmentCount = 1;
  595. renderPassInfo.pAttachments = &colorAttachment;
  596. renderPassInfo.subpassCount = 1;
  597. renderPassInfo.pSubpasses = &subpass;
  598. renderPassInfo.dependencyCount = 1;
  599. renderPassInfo.pDependencies = &dependency;
  600. if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
  601. throw love::Exception("failed to create render pass");
  602. }
  603. }
  604. static VkShaderModule createShaderModule(VkDevice device, const std::vector<char>& code) {
  605. VkShaderModuleCreateInfo createInfo{};
  606. createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  607. createInfo.codeSize = code.size();
  608. createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
  609. VkShaderModule shaderModule;
  610. if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
  611. throw love::Exception("failed to create shader module");
  612. }
  613. return shaderModule;
  614. }
  615. void Graphics::createDefaultShaders() {
  616. for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++) {
  617. auto stype = (Shader::StandardShader)i;
  618. if (!Shader::standardShaders[i]) {
  619. std::vector<std::string> stages;
  620. stages.push_back(Shader::getDefaultCode(stype, SHADERSTAGE_VERTEX));
  621. stages.push_back(Shader::getDefaultCode(stype, SHADERSTAGE_PIXEL));
  622. Shader::standardShaders[i] = newShader(stages, true);
  623. }
  624. }
  625. }
  626. void Graphics::createDescriptorSetLayout() {
  627. VkDescriptorSetLayoutBinding uboLayoutBinding{};
  628. uboLayoutBinding.binding = 0;
  629. uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  630. uboLayoutBinding.descriptorCount = 1;
  631. uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
  632. VkDescriptorSetLayoutCreateInfo layoutInfo{};
  633. layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  634. layoutInfo.bindingCount = 1;
  635. layoutInfo.pBindings = &uboLayoutBinding;
  636. if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
  637. throw love::Exception("failed to create descriptor set layout");
  638. }
  639. }
  640. void Graphics::createUniformBuffers() {
  641. VkDeviceSize bufferSize = sizeof(Shader::UniformBufferObject);
  642. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
  643. uniformBuffers.push_back(std::make_unique<StreamBuffer>(vmaAllocator, BUFFERUSAGE_UNIFORM, bufferSize));
  644. }
  645. }
  646. void Graphics::createDescriptorPool() {
  647. VkDescriptorPoolSize poolSize{};
  648. poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  649. poolSize.descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
  650. VkDescriptorPoolCreateInfo poolInfo{};
  651. poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  652. poolInfo.poolSizeCount = 1;
  653. poolInfo.pPoolSizes = &poolSize;
  654. poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
  655. if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
  656. throw love::Exception("failed to create descriptor pool");
  657. }
  658. }
  659. void Graphics::createDescriptorSets() {
  660. std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout);
  661. VkDescriptorSetAllocateInfo allocInfo{};
  662. allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  663. allocInfo.descriptorPool = descriptorPool;
  664. allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
  665. allocInfo.pSetLayouts = layouts.data();
  666. descriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
  667. if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
  668. throw love::Exception("failed to allocate descriptor sets");
  669. }
  670. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
  671. VkDescriptorBufferInfo bufferInfo{};
  672. bufferInfo.buffer = (VkBuffer) uniformBuffers.at(i)->getHandle();
  673. bufferInfo.offset = 0;
  674. bufferInfo.range = sizeof(Shader::UniformBufferObject);
  675. VkWriteDescriptorSet descriptorWrite{};
  676. descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  677. descriptorWrite.dstSet = descriptorSets[i];
  678. descriptorWrite.dstBinding = 0;
  679. descriptorWrite.dstArrayElement = 0;
  680. descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  681. descriptorWrite.descriptorCount = 1;
  682. descriptorWrite.pBufferInfo = &bufferInfo;
  683. vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
  684. }
  685. }
  686. void Graphics::createGraphicsPipeline() {
  687. auto shader = reinterpret_cast<love::graphics::vulkan::Shader*>(love::graphics::vulkan::Shader::standardShaders[Shader::STANDARD_DEFAULT]);
  688. auto shaderStages = shader->getShaderStages();
  689. VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
  690. vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  691. VkVertexInputBindingDescription vertexBindingDescription;
  692. vertexBindingDescription.binding = 0;
  693. vertexBindingDescription.stride = 2 * sizeof(float); // just position for now
  694. vertexBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
  695. // todo later
  696. VkVertexInputAttributeDescription positionInputAttributeDescription;
  697. positionInputAttributeDescription.binding = 0;
  698. positionInputAttributeDescription.location = 0;
  699. positionInputAttributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
  700. positionInputAttributeDescription.offset = 0;
  701. vertexInputInfo.vertexBindingDescriptionCount = 1;
  702. vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDescription;
  703. vertexInputInfo.vertexAttributeDescriptionCount = 1;
  704. vertexInputInfo.pVertexAttributeDescriptions = &positionInputAttributeDescription;
  705. VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
  706. inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  707. inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  708. inputAssembly.primitiveRestartEnable = VK_FALSE;
  709. VkViewport viewport{};
  710. viewport.x = 0.0f;
  711. viewport.y = 0.0f;
  712. viewport.width = (float)swapChainExtent.width;
  713. viewport.height = (float)swapChainExtent.height;
  714. viewport.minDepth = 0.0f;
  715. viewport.maxDepth = 1.0f;
  716. VkRect2D scissor{};
  717. scissor.offset = { 0, 0 };
  718. scissor.extent = swapChainExtent;
  719. VkPipelineViewportStateCreateInfo viewportState{};
  720. viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  721. viewportState.viewportCount = 1;
  722. viewportState.pViewports = &viewport;
  723. viewportState.scissorCount = 1;
  724. viewportState.pScissors = &scissor;
  725. VkPipelineRasterizationStateCreateInfo rasterizer{};
  726. rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  727. rasterizer.depthClampEnable = VK_FALSE;
  728. rasterizer.rasterizerDiscardEnable = VK_FALSE;
  729. rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
  730. rasterizer.lineWidth = 1.0f;
  731. rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT;
  732. rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
  733. rasterizer.depthBiasEnable = VK_FALSE;
  734. rasterizer.depthBiasConstantFactor = 0.0f;
  735. rasterizer.depthBiasClamp = 0.0f;
  736. rasterizer.depthBiasSlopeFactor = 0.0f;
  737. VkPipelineMultisampleStateCreateInfo multisampling{};
  738. multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  739. multisampling.sampleShadingEnable = VK_FALSE;
  740. multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  741. multisampling.minSampleShading = 1.0f; // Optional
  742. multisampling.pSampleMask = nullptr; // Optional
  743. multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
  744. multisampling.alphaToOneEnable = VK_FALSE; // Optional
  745. VkPipelineColorBlendAttachmentState colorBlendAttachment{};
  746. colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
  747. colorBlendAttachment.blendEnable = VK_FALSE;
  748. VkPipelineColorBlendStateCreateInfo colorBlending{};
  749. colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  750. colorBlending.logicOpEnable = VK_FALSE;
  751. colorBlending.logicOp = VK_LOGIC_OP_COPY;
  752. colorBlending.attachmentCount = 1;
  753. colorBlending.pAttachments = &colorBlendAttachment;
  754. colorBlending.blendConstants[0] = 0.0f;
  755. colorBlending.blendConstants[1] = 0.0f;
  756. colorBlending.blendConstants[2] = 0.0f;
  757. colorBlending.blendConstants[3] = 0.0f;
  758. VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
  759. pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  760. pipelineLayoutInfo.setLayoutCount = 1;
  761. pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
  762. pipelineLayoutInfo.pushConstantRangeCount = 0;
  763. if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
  764. throw love::Exception("failed to create pipeline layout");
  765. }
  766. VkGraphicsPipelineCreateInfo pipelineInfo{};
  767. pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  768. pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
  769. pipelineInfo.pStages = shaderStages.data();
  770. pipelineInfo.pVertexInputState = &vertexInputInfo;
  771. pipelineInfo.pInputAssemblyState = &inputAssembly;
  772. pipelineInfo.pViewportState = &viewportState;
  773. pipelineInfo.pRasterizationState = &rasterizer;
  774. pipelineInfo.pMultisampleState = &multisampling;
  775. pipelineInfo.pDepthStencilState = nullptr;
  776. pipelineInfo.pColorBlendState = &colorBlending;
  777. pipelineInfo.pDynamicState = nullptr;
  778. pipelineInfo.layout = pipelineLayout;
  779. pipelineInfo.renderPass = renderPass;
  780. pipelineInfo.subpass = 0;
  781. pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
  782. pipelineInfo.basePipelineIndex = -1;
  783. if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
  784. throw love::Exception("failed to create graphics pipeline");
  785. }
  786. }
  787. void Graphics::createFramebuffers() {
  788. swapChainFramBuffers.resize(swapChainImageViews.size());
  789. for (size_t i = 0; i < swapChainImageViews.size(); i++) {
  790. VkImageView attachments[] = {
  791. swapChainImageViews.at(i)
  792. };
  793. VkFramebufferCreateInfo framebufferInfo{};
  794. framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  795. framebufferInfo.renderPass = renderPass;
  796. framebufferInfo.attachmentCount = 1;
  797. framebufferInfo.pAttachments = attachments;
  798. framebufferInfo.width = swapChainExtent.width;
  799. framebufferInfo.height = swapChainExtent.height;
  800. framebufferInfo.layers = 1;
  801. if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramBuffers.at(i)) != VK_SUCCESS) {
  802. throw love::Exception("failed to create framebuffers");
  803. }
  804. }
  805. }
  806. void Graphics::createCommandPool() {
  807. QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);
  808. VkCommandPoolCreateInfo poolInfo{};
  809. poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  810. poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
  811. poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  812. if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
  813. throw love::Exception("failed to create command pool");
  814. }
  815. }
  816. void Graphics::createCommandBuffers() {
  817. commandBuffers.resize(swapChainFramBuffers.size());
  818. VkCommandBufferAllocateInfo allocInfo{};
  819. allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  820. allocInfo.commandPool = commandPool;
  821. allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  822. allocInfo.commandBufferCount = (uint32_t)commandBuffers.size();
  823. if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
  824. throw love::Exception("failed to allocate command buffers");
  825. }
  826. }
  827. void Graphics::createSyncObjects() {
  828. imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  829. renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  830. inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
  831. imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE);
  832. VkSemaphoreCreateInfo semaphoreInfo{};
  833. semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  834. VkFenceCreateInfo fenceInfo{};
  835. fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  836. fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  837. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
  838. if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores.at(i)) != VK_SUCCESS ||
  839. vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores.at(i)) != VK_SUCCESS ||
  840. vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences.at(i)) != VK_SUCCESS) {
  841. throw love::Exception("failed to create synchronization objects for a frame!");
  842. }
  843. }
  844. }
  845. void Graphics::cleanup() {
  846. vkDeviceWaitIdle(device);
  847. cleanupSwapChain();
  848. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
  849. vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
  850. vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
  851. vkDestroyFence(device, inFlightFences[i], nullptr);
  852. }
  853. vkDestroyDescriptorPool(device, descriptorPool, nullptr);
  854. vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
  855. vkDestroyCommandPool(device, commandPool, nullptr);
  856. vkDestroyDevice(device, nullptr);
  857. vkDestroySurfaceKHR(instance, surface, nullptr);
  858. vkDestroyInstance(instance, nullptr);
  859. }
  860. void Graphics::cleanupSwapChain() {
  861. for (size_t i = 0; i < swapChainFramBuffers.size(); i++) {
  862. vkDestroyFramebuffer(device, swapChainFramBuffers[i], nullptr);
  863. }
  864. vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
  865. vkDestroyPipeline(device, graphicsPipeline, nullptr);
  866. vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
  867. vkDestroyRenderPass(device, renderPass, nullptr);
  868. for (size_t i = 0; i < swapChainImageViews.size(); i++) {
  869. vkDestroyImageView(device, swapChainImageViews[i], nullptr);
  870. }
  871. vkDestroySwapchainKHR(device, swapChain, nullptr);
  872. uniformBuffers.clear();
  873. }
  874. void Graphics::recreateSwapChain() {
  875. vkDeviceWaitIdle(device);
  876. cleanupSwapChain();
  877. createSwapChain();
  878. createImageViews();
  879. createRenderPass();
  880. createGraphicsPipeline();
  881. createFramebuffers();
  882. createUniformBuffers();
  883. createDescriptorPool();
  884. createDescriptorSets();
  885. createCommandBuffers();
  886. startRecordingGraphicsCommands();
  887. }
  888. love::graphics::Graphics* createInstance() {
  889. love::graphics::Graphics* instance = nullptr;
  890. try {
  891. instance = new Graphics();
  892. }
  893. catch (love::Exception& e) {
  894. printf("Cannot create Vulkan renderer: %s\n", e.what());
  895. }
  896. return instance;
  897. }
  898. }
  899. }
  900. }