Graphics.cpp 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528
  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 "graphics/Texture.h"
  8. #include "Vulkan.h"
  9. #include "common/version.h"
  10. #include <vector>
  11. #include <cstring>
  12. #include <set>
  13. #include <fstream>
  14. #include <iostream>
  15. #include <array>
  16. namespace love {
  17. namespace graphics {
  18. namespace vulkan {
  19. static VkIndexType getVulkanIndexBufferType(IndexDataType type) {
  20. switch (type) {
  21. case INDEX_UINT16: return VK_INDEX_TYPE_UINT16;
  22. case INDEX_UINT32: return VK_INDEX_TYPE_UINT32;
  23. default:
  24. throw love::Exception("unknown Index Data type");
  25. }
  26. }
  27. const std::vector<const char*> validationLayers = {
  28. "VK_LAYER_KHRONOS_validation"
  29. };
  30. const std::vector<const char*> deviceExtensions = {
  31. VK_KHR_SWAPCHAIN_EXTENSION_NAME
  32. };
  33. #ifdef NDEBUG
  34. const bool enableValidationLayers = false;
  35. #else
  36. const bool enableValidationLayers = true;
  37. #endif
  38. const int MAX_FRAMES_IN_FLIGHT = 2;
  39. const char* Graphics::getName() const {
  40. return "love.graphics.vulkan";
  41. }
  42. Graphics::Graphics() {
  43. }
  44. Graphics::~Graphics() {
  45. // FIXME: most resources that are allocated dynamically need proper cleanup.
  46. batchedDrawState.vb[0] = nullptr;
  47. batchedDrawState.vb[1] = nullptr;
  48. batchedDrawState.indexBuffer = nullptr;
  49. }
  50. // START OVERRIDEN FUNCTIONS
  51. 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) {
  52. std::cout << "newBuffer ";
  53. return new Buffer(vmaAllocator, this, settings, format, data, size, arraylength);
  54. }
  55. void Graphics::startRecordingGraphicsCommands() {
  56. vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
  57. while (true) {
  58. VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
  59. if (result == VK_ERROR_OUT_OF_DATE_KHR) {
  60. recreateSwapChain();
  61. continue;
  62. }
  63. else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
  64. throw love::Exception("failed to acquire swap chain image");
  65. }
  66. break;
  67. }
  68. VkCommandBufferBeginInfo beginInfo{};
  69. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  70. beginInfo.flags = 0;
  71. beginInfo.pInheritanceInfo = nullptr;
  72. std::cout << "beginCommandBuffer(imageIndex=" << imageIndex << ") ";
  73. if (vkBeginCommandBuffer(commandBuffers.at(imageIndex), &beginInfo) != VK_SUCCESS) {
  74. throw love::Exception("failed to begin recording command buffer");
  75. }
  76. VkRenderPassBeginInfo renderPassInfo{};
  77. renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  78. renderPassInfo.renderPass = renderPass;
  79. renderPassInfo.framebuffer = swapChainFramBuffers.at(imageIndex);
  80. renderPassInfo.renderArea.offset = { 0, 0 };
  81. renderPassInfo.renderArea.extent = swapChainExtent;
  82. renderPassInfo.clearValueCount = 1;
  83. renderPassInfo.pClearValues = &clearColor;
  84. const auto& commandBuffer = commandBuffers.at(imageIndex);
  85. vkCmdBeginRenderPass(commandBuffers.at(imageIndex), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
  86. currentGraphicsPipeline = VK_NULL_HANDLE;
  87. }
  88. void Graphics::endRecordingGraphicsCommands() {
  89. const auto& commandBuffer = commandBuffers.at(imageIndex);
  90. std::cout << "endCommandBuffer(imageIndex=" << imageIndex << ") ";
  91. vkCmdEndRenderPass(commandBuffers.at(imageIndex));
  92. if (vkEndCommandBuffer(commandBuffers.at(imageIndex)) != VK_SUCCESS) {
  93. throw love::Exception("failed to record command buffer");
  94. }
  95. }
  96. void Graphics::present(void* screenshotCallbackdata) {
  97. flushBatchedDraws();
  98. endRecordingGraphicsCommands();
  99. if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
  100. vkWaitForFences(device, 1, &imagesInFlight.at(imageIndex), VK_TRUE, UINT64_MAX);
  101. }
  102. imagesInFlight[imageIndex] = inFlightFences[currentFrame];
  103. VkSubmitInfo submitInfo{};
  104. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  105. VkSemaphore waitSemaphores[] = { imageAvailableSemaphores.at(currentFrame) };
  106. VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
  107. submitInfo.waitSemaphoreCount = 1;
  108. submitInfo.pWaitSemaphores = waitSemaphores;
  109. submitInfo.pWaitDstStageMask = waitStages;
  110. submitInfo.commandBufferCount = 1;
  111. submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
  112. VkSemaphore signalSemaphores[] = { renderFinishedSemaphores.at(currentFrame) };
  113. submitInfo.signalSemaphoreCount = 1;
  114. submitInfo.pSignalSemaphores = signalSemaphores;
  115. vkResetFences(device, 1, &inFlightFences[currentFrame]);
  116. if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences.at(currentFrame)) != VK_SUCCESS) {
  117. throw love::Exception("failed to submit draw command buffer");
  118. }
  119. VkPresentInfoKHR presentInfo{};
  120. presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  121. presentInfo.waitSemaphoreCount = 1;
  122. presentInfo.pWaitSemaphores = signalSemaphores;
  123. VkSwapchainKHR swapChains[] = { swapChain };
  124. presentInfo.swapchainCount = 1;
  125. presentInfo.pSwapchains = swapChains;
  126. presentInfo.pImageIndices = &imageIndex;
  127. VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo);
  128. if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
  129. framebufferResized = false;
  130. recreateSwapChain();
  131. }
  132. else if (result != VK_SUCCESS) {
  133. throw love::Exception("failed to present swap chain image");
  134. }
  135. std::cout << "present" << std::endl;
  136. currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
  137. updatedBatchedDrawBuffers();
  138. startRecordingGraphicsCommands();
  139. }
  140. void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) {
  141. std::cout << "setViewPortSize ";
  142. this->width = width;
  143. this->height = height;
  144. this->pixelWidth = pixelwidth;
  145. this->pixelHeight = pixelheight;
  146. resetProjection();
  147. recreateSwapChain();
  148. }
  149. bool Graphics::setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) {
  150. std::cout << "setMode ";
  151. createVulkanInstance();
  152. createSurface();
  153. pickPhysicalDevice();
  154. createLogicalDevice();
  155. initVMA();
  156. initCapabilities();
  157. createSwapChain();
  158. createImageViews();
  159. createRenderPass();
  160. createDefaultShaders();
  161. createDescriptorSetLayout();
  162. createFramebuffers();
  163. createCommandPool();
  164. createCommandBuffers();
  165. createDefaultTexture();
  166. createQuadIndexBuffer();
  167. createDescriptorPool();
  168. createSyncObjects();
  169. startRecordingGraphicsCommands();
  170. currentFrame = 0;
  171. created = true;
  172. float whiteColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  173. batchedDrawBuffers.clear();
  174. batchedDrawBuffers.reserve(MAX_FRAMES_IN_FLIGHT);
  175. for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
  176. batchedDrawBuffers.emplace_back();
  177. // Initial sizes that should be good enough for most cases. It will
  178. // resize to fit if needed, later.
  179. batchedDrawBuffers[i].vertexBuffer1 = new StreamBuffer(vmaAllocator, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
  180. batchedDrawBuffers[i].vertexBuffer2 = new StreamBuffer(vmaAllocator, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
  181. batchedDrawBuffers[i].indexBuffer = new StreamBuffer(vmaAllocator, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
  182. // sometimes the VertexColor is not set, so we manually adjust it to white color
  183. batchedDrawBuffers[i].constantColorBuffer = new StreamBuffer(vmaAllocator, BUFFERUSAGE_VERTEX, sizeof(whiteColor));
  184. auto mapInfo = batchedDrawBuffers[i].constantColorBuffer->map(sizeof(whiteColor));
  185. memcpy(mapInfo.data, whiteColor, sizeof(whiteColor));
  186. batchedDrawBuffers[i].constantColorBuffer->unmap(sizeof(whiteColor));
  187. batchedDrawBuffers[i].constantColorBuffer->markUsed(sizeof(whiteColor));
  188. }
  189. updatedBatchedDrawBuffers();
  190. return true;
  191. }
  192. void Graphics::initCapabilities() {
  193. std::cout << "initCapabilities ";
  194. // todo
  195. capabilities.features[FEATURE_MULTI_RENDER_TARGET_FORMATS] = false;
  196. capabilities.features[FEATURE_CLAMP_ZERO] = false;
  197. capabilities.features[FEATURE_CLAMP_ONE] = false;
  198. capabilities.features[FEATURE_BLEND_MINMAX] = false;
  199. capabilities.features[FEATURE_LIGHTEN] = false;
  200. capabilities.features[FEATURE_FULL_NPOT] = false;
  201. capabilities.features[FEATURE_PIXEL_SHADER_HIGHP] = false;
  202. capabilities.features[FEATURE_SHADER_DERIVATIVES] = false;
  203. capabilities.features[FEATURE_GLSL3] = false;
  204. capabilities.features[FEATURE_GLSL4] = false;
  205. capabilities.features[FEATURE_INSTANCING] = false;
  206. capabilities.features[FEATURE_TEXEL_BUFFER] = false;
  207. capabilities.features[FEATURE_INDEX_BUFFER_32BIT] = true;
  208. capabilities.features[FEATURE_COPY_BUFFER] = false;
  209. capabilities.features[FEATURE_COPY_BUFFER_TO_TEXTURE] = false;
  210. capabilities.features[FEATURE_COPY_TEXTURE_TO_BUFFER] = false;
  211. capabilities.features[FEATURE_COPY_RENDER_TARGET_TO_BUFFER] = false;
  212. static_assert(FEATURE_MAX_ENUM == 17, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
  213. VkPhysicalDeviceProperties properties;
  214. vkGetPhysicalDeviceProperties(physicalDevice, &properties);
  215. capabilities.limits[LIMIT_POINT_SIZE] = properties.limits.pointSizeRange[1];
  216. capabilities.limits[LIMIT_TEXTURE_SIZE] = properties.limits.maxImageDimension2D;
  217. capabilities.limits[LIMIT_TEXTURE_LAYERS] = properties.limits.maxImageArrayLayers;
  218. capabilities.limits[LIMIT_VOLUME_TEXTURE_SIZE] = properties.limits.maxImageDimension3D;
  219. capabilities.limits[LIMIT_CUBE_TEXTURE_SIZE] = properties.limits.maxImageDimensionCube;
  220. capabilities.limits[LIMIT_TEXEL_BUFFER_SIZE] = properties.limits.maxTexelBufferElements; // ?
  221. capabilities.limits[LIMIT_SHADER_STORAGE_BUFFER_SIZE] = properties.limits.maxStorageBufferRange; // ?
  222. capabilities.limits[LIMIT_THREADGROUPS_X] = 0; // todo
  223. capabilities.limits[LIMIT_THREADGROUPS_Y] = 0; // todo
  224. capabilities.limits[LIMIT_THREADGROUPS_Z] = 0; // todo
  225. capabilities.limits[LIMIT_RENDER_TARGETS] = 1; // todo
  226. capabilities.limits[LIMIT_TEXTURE_MSAA] = 1; // todo
  227. capabilities.limits[LIMIT_ANISOTROPY] = 1.0f; // todo
  228. static_assert(LIMIT_MAX_ENUM == 13, "Graphics::initCapabilities must be updated when adding a new system limit!");
  229. capabilities.textureTypes[TEXTURE_2D] = true;
  230. capabilities.textureTypes[TEXTURE_VOLUME] = false;
  231. capabilities.textureTypes[TEXTURE_2D_ARRAY] = false;
  232. capabilities.textureTypes[TEXTURE_CUBE] = false;
  233. }
  234. void Graphics::unSetMode() {
  235. std::cout << "unSetMode ";
  236. created = false;
  237. cleanup();
  238. }
  239. void Graphics::draw(const DrawIndexedCommand& cmd) {
  240. std::cout << "drawIndexed ";
  241. std::vector<VkBuffer> buffers;
  242. std::vector<VkDeviceSize> offsets;
  243. bool useConstantColorBuffer;
  244. GraphicsPipelineConfiguration configuration;
  245. createVulkanVertexFormat(*cmd.attributes, useConstantColorBuffer, configuration);
  246. for (uint32_t i = 0; i < 2; i++) {
  247. if (cmd.buffers->useBits & (1u << i)) {
  248. buffers.push_back((VkBuffer)cmd.buffers->info[i].buffer->getHandle());
  249. offsets.push_back((VkDeviceSize)cmd.buffers->info[i].offset);
  250. }
  251. else {
  252. buffers.push_back(VK_NULL_HANDLE);
  253. offsets.push_back(0);
  254. }
  255. }
  256. if (useConstantColorBuffer) {
  257. buffers.push_back((VkBuffer)batchedDrawBuffers[currentFrame].constantColorBuffer->getHandle());
  258. offsets.push_back((VkDeviceSize)0);
  259. }
  260. if (cmd.texture == nullptr) {
  261. setTexture(standardTexture);
  262. }
  263. else {
  264. setTexture(cmd.texture);
  265. }
  266. ensureGraphicsPipelineConfiguration(configuration);
  267. vkCmdBindDescriptorSets(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, getDescriptorSet(currentFrame), 0, nullptr);
  268. vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, buffers.size(), buffers.data(), offsets.data());
  269. vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)cmd.indexBuffer->getHandle(), 0, getVulkanIndexBufferType(cmd.indexType));
  270. vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.indexCount), 1, 0, 0, 0);
  271. }
  272. PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const {
  273. std::cout << "getSizedFormat ";
  274. switch (format) {
  275. PIXELFORMAT_NORMAL:
  276. if (isGammaCorrect()) {
  277. return PIXELFORMAT_RGBA8_UNORM_sRGB;
  278. }
  279. else {
  280. return PIXELFORMAT_RGBA8_UNORM;
  281. }
  282. case PIXELFORMAT_HDR:
  283. return PIXELFORMAT_RGBA16_FLOAT;
  284. default:
  285. return format;
  286. }
  287. }
  288. bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) {
  289. std::cout << "isPixelFormatSupported ";
  290. switch (format) {
  291. case PIXELFORMAT_LA8_UNORM:
  292. return false;
  293. default:
  294. return true;
  295. }
  296. }
  297. void Graphics::drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) {
  298. std::cout << "drawQuads ";
  299. const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX;
  300. const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4;
  301. std::vector<VkBuffer> bufferVector;
  302. std::vector<VkDeviceSize> offsets;
  303. bool useConstantColorBuffer;
  304. GraphicsPipelineConfiguration configuration;
  305. createVulkanVertexFormat(attributes, useConstantColorBuffer, configuration);
  306. for (uint32_t i = 0; i < 2; i++) {
  307. if (buffers.useBits & (1u << i)) {
  308. bufferVector.push_back((VkBuffer)buffers.info[i].buffer->getHandle());
  309. offsets.push_back((VkDeviceSize)buffers.info[i].offset);
  310. }
  311. else {
  312. if (useConstantColorBuffer) {
  313. bufferVector.push_back(VK_NULL_HANDLE);
  314. offsets.push_back(0);
  315. }
  316. }
  317. }
  318. if (useConstantColorBuffer) {
  319. bufferVector.push_back((VkBuffer)batchedDrawBuffers[currentFrame].constantColorBuffer->getHandle());
  320. offsets.push_back((VkDeviceSize)0);
  321. }
  322. if (texture == nullptr) {
  323. setTexture(standardTexture);
  324. }
  325. else {
  326. setTexture(texture);
  327. }
  328. ensureGraphicsPipelineConfiguration(configuration);
  329. vkCmdBindDescriptorSets(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, getDescriptorSet(currentFrame), 0, nullptr);
  330. vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)quadIndexBuffer->getHandle(), 0, getVulkanIndexBufferType(INDEX_UINT16));
  331. vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, bufferVector.size(), bufferVector.data(), offsets.data());
  332. vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(count * 6), 1, 0, 0, 0);
  333. int baseVertex = start * 4;
  334. for (int quadindex = 0; quadindex < count; quadindex += MAX_QUADS_PER_DRAW) {
  335. int quadcount = std::min(MAX_QUADS_PER_DRAW, count - quadindex);
  336. // vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(quadcount * 6), 1, 0, baseVertex, 0);
  337. baseVertex += quadcount * 4;
  338. }
  339. }
  340. graphics::StreamBuffer* Graphics::newStreamBuffer(BufferUsage type, size_t size) {
  341. std::cout << "newStreamBuffer ";
  342. return new StreamBuffer(vmaAllocator, type, size);
  343. }
  344. Matrix4 Graphics::computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const {
  345. uint32 flags = DEVICE_PROJECTION_DEFAULT;
  346. return calculateDeviceProjection(projection, 0);
  347. }
  348. // END IMPLEMENTATION OVERRIDDEN FUNCTIONS
  349. void Graphics::updatedBatchedDrawBuffers() {
  350. batchedDrawState.vb[0] = batchedDrawBuffers[currentFrame].vertexBuffer1;
  351. batchedDrawState.vb[0]->nextFrame();
  352. batchedDrawState.vb[1] = batchedDrawBuffers[currentFrame].vertexBuffer2;
  353. batchedDrawState.vb[1]->nextFrame();
  354. batchedDrawState.indexBuffer = batchedDrawBuffers[currentFrame].indexBuffer;
  355. batchedDrawState.indexBuffer->nextFrame();
  356. }
  357. VkDescriptorSet* Graphics::getDescriptorSet(int currentFrame) {
  358. DecriptorSetConfiguration config;
  359. config.texture = currentTexture;
  360. config.buffer = getUniformBuffer();
  361. for (auto i = 0; i < descriptorSetsMap.size(); i++) {
  362. if (descriptorSetsMap[i].first == config) {
  363. return &descriptorSetsMap[i].second[currentFrame];
  364. }
  365. }
  366. auto descriptorSets = createDescriptorSets(config);
  367. descriptorSetsMap.push_back(std::make_pair(config, descriptorSets));
  368. return &descriptorSetsMap.back().second[currentFrame];
  369. }
  370. graphics::StreamBuffer* Graphics::getUniformBuffer() {
  371. auto data = getCurrentBuiltinUniformData();
  372. for (auto it : uniformBufferMap) {
  373. if (it.first == data) {
  374. return it.second;
  375. }
  376. }
  377. auto buffer = createUniformBufferFromData(data);
  378. uniformBufferMap.push_back(std::make_pair(data, buffer));
  379. return buffer;
  380. }
  381. VkCommandBuffer Graphics::beginSingleTimeCommands() {
  382. VkCommandBufferAllocateInfo allocInfo{};
  383. allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  384. allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  385. allocInfo.commandPool = commandPool;
  386. allocInfo.commandBufferCount = 1;
  387. VkCommandBuffer commandBuffer;
  388. vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
  389. VkCommandBufferBeginInfo beginInfo{};
  390. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  391. beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  392. vkBeginCommandBuffer(commandBuffer, &beginInfo);
  393. return commandBuffer;
  394. }
  395. void Graphics::endSingleTimeCommands(VkCommandBuffer commandBuffer) {
  396. vkEndCommandBuffer(commandBuffer);
  397. VkSubmitInfo submitInfo{};
  398. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  399. submitInfo.commandBufferCount = 1;
  400. submitInfo.pCommandBuffers = &commandBuffer;
  401. vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
  402. vkQueueWaitIdle(graphicsQueue);
  403. vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
  404. }
  405. graphics::Shader::BuiltinUniformData Graphics::getCurrentBuiltinUniformData() {
  406. love::graphics::Shader::BuiltinUniformData data;
  407. data.transformMatrix = getTransform();
  408. data.projectionMatrix = getDeviceProjection();
  409. // The normal matrix is the transpose of the inverse of the rotation portion
  410. // (top-left 3x3) of the transform matrix.
  411. {
  412. Matrix3 normalmatrix = Matrix3(data.transformMatrix).transposedInverse();
  413. const float* e = normalmatrix.getElements();
  414. for (int i = 0; i < 3; i++)
  415. {
  416. data.normalMatrix[i].x = e[i * 3 + 0];
  417. data.normalMatrix[i].y = e[i * 3 + 1];
  418. data.normalMatrix[i].z = e[i * 3 + 2];
  419. data.normalMatrix[i].w = 0.0f;
  420. }
  421. }
  422. // Store DPI scale in an unused component of another vector.
  423. data.normalMatrix[0].w = (float)getCurrentDPIScale();
  424. // Same with point size.
  425. data.normalMatrix[1].w = getPointSize();
  426. data.screenSizeParams.x = swapChainExtent.width;
  427. data.screenSizeParams.y = swapChainExtent.height;
  428. data.screenSizeParams.z = 1.0f;
  429. data.screenSizeParams.w = 0.0f;
  430. data.constantColor = getColor();
  431. gammaCorrectColor(data.constantColor);
  432. return data;
  433. }
  434. graphics::StreamBuffer* Graphics::createUniformBufferFromData(graphics::Shader::BuiltinUniformData data) {
  435. auto buffer = newStreamBuffer(BUFFERUSAGE_UNIFORM, sizeof(data));
  436. auto mappedInfo = buffer->map(0);
  437. memcpy(mappedInfo.data, &data, sizeof(data));
  438. buffer->unmap(0);
  439. return buffer;
  440. }
  441. void Graphics::createVulkanInstance() {
  442. if (enableValidationLayers && !checkValidationSupport()) {
  443. throw love::Exception("validation layers requested, but not available");
  444. }
  445. VkApplicationInfo appInfo{};
  446. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  447. appInfo.pApplicationName = "LOVE";
  448. appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); //todo, get this version from somewhere else?
  449. appInfo.pEngineName = "LOVE Engine";
  450. appInfo.engineVersion = VK_MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
  451. appInfo.apiVersion = VK_API_VERSION_1_0;
  452. VkInstanceCreateInfo createInfo{};
  453. createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  454. createInfo.pApplicationInfo = &appInfo;
  455. createInfo.pNext = nullptr;
  456. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  457. const void* handle = window->getHandle();
  458. unsigned int count;
  459. if (SDL_Vulkan_GetInstanceExtensions((SDL_Window*)handle, &count, nullptr) != SDL_TRUE) {
  460. throw love::Exception("couldn't retrieve sdl vulkan extensions");
  461. }
  462. std::vector<const char*> extensions = {}; // can add more here
  463. size_t addition_extension_count = extensions.size();
  464. extensions.resize(addition_extension_count + count);
  465. if (SDL_Vulkan_GetInstanceExtensions((SDL_Window*)handle, &count, extensions.data() + addition_extension_count) != SDL_TRUE) {
  466. throw love::Exception("couldn't retrieve sdl vulkan extensions");
  467. }
  468. createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
  469. createInfo.ppEnabledExtensionNames = extensions.data();
  470. if (enableValidationLayers) {
  471. createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  472. createInfo.ppEnabledLayerNames = validationLayers.data();
  473. }
  474. else {
  475. createInfo.enabledLayerCount = 0;
  476. createInfo.ppEnabledLayerNames = nullptr;
  477. }
  478. if (vkCreateInstance(
  479. &createInfo,
  480. nullptr,
  481. &instance) != VK_SUCCESS) {
  482. throw love::Exception("couldn't create vulkan instance");
  483. }
  484. }
  485. bool Graphics::checkValidationSupport() {
  486. uint32_t layerCount;
  487. vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
  488. std::vector<VkLayerProperties> availableLayers(layerCount);
  489. vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
  490. for (const char* layerName : validationLayers) {
  491. bool layerFound = false;
  492. for (const auto& layerProperties : availableLayers) {
  493. if (strcmp(layerName, layerProperties.layerName) == 0) {
  494. layerFound = true;
  495. break;
  496. }
  497. }
  498. if (!layerFound) {
  499. return false;
  500. }
  501. }
  502. return true;
  503. }
  504. void Graphics::pickPhysicalDevice() {
  505. uint32_t deviceCount = 0;
  506. vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
  507. if (deviceCount == 0) {
  508. throw love::Exception("failed to find GPUs with Vulkan support");
  509. }
  510. std::vector<VkPhysicalDevice> devices(deviceCount);
  511. vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
  512. std::multimap<int, VkPhysicalDevice> candidates;
  513. for (const auto& device : devices) {
  514. int score = rateDeviceSuitability(device);
  515. candidates.insert(std::make_pair(score, device));
  516. }
  517. if (candidates.rbegin()->first > 0) {
  518. physicalDevice = candidates.rbegin()->second;
  519. }
  520. else {
  521. throw love::Exception("failed to find a suitable gpu");
  522. }
  523. }
  524. bool Graphics::checkDeviceExtensionSupport(VkPhysicalDevice device) {
  525. uint32_t extensionCount;
  526. vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
  527. std::vector<VkExtensionProperties> availableExtensions(extensionCount);
  528. vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
  529. std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
  530. for (const auto& extension : availableExtensions) {
  531. requiredExtensions.erase(extension.extensionName);
  532. }
  533. return requiredExtensions.empty();
  534. }
  535. // if the score is nonzero then the device is suitable.
  536. // A higher rating means generally better performance
  537. // if the score is 0 the device is unsuitable
  538. int Graphics::rateDeviceSuitability(VkPhysicalDevice device) {
  539. VkPhysicalDeviceProperties deviceProperties;
  540. VkPhysicalDeviceFeatures deviceFeatures;
  541. vkGetPhysicalDeviceProperties(device, &deviceProperties);
  542. vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
  543. int score = 1;
  544. // optional
  545. if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
  546. score += 1000;
  547. }
  548. // definitely needed
  549. QueueFamilyIndices indices = findQueueFamilies(device);
  550. if (!indices.isComplete()) {
  551. score = 0;
  552. }
  553. bool extensionsSupported = checkDeviceExtensionSupport(device);
  554. if (!extensionsSupported) {
  555. score = 0;
  556. }
  557. if (extensionsSupported) {
  558. auto swapChainSupport = querySwapChainSupport(device);
  559. bool swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
  560. if (!swapChainAdequate) {
  561. score = 0;
  562. }
  563. }
  564. if (!deviceFeatures.samplerAnisotropy) {
  565. score = 0;
  566. }
  567. return score;
  568. }
  569. Graphics::QueueFamilyIndices Graphics::findQueueFamilies(VkPhysicalDevice device) {
  570. QueueFamilyIndices indices;
  571. uint32_t queueFamilyCount = 0;
  572. vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
  573. std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
  574. vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
  575. int i = 0;
  576. for (const auto& queueFamily : queueFamilies) {
  577. if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  578. indices.graphicsFamily = i;
  579. }
  580. VkBool32 presentSupport = false;
  581. vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
  582. if (presentSupport) {
  583. indices.presentFamily = i;
  584. }
  585. if (indices.isComplete()) {
  586. break;
  587. }
  588. i++;
  589. }
  590. return indices;
  591. }
  592. void Graphics::createLogicalDevice() {
  593. QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  594. std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
  595. std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
  596. float queuePriority = 1.0f;
  597. for (uint32_t queueFamily : uniqueQueueFamilies) {
  598. VkDeviceQueueCreateInfo queueCreateInfo{};
  599. queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  600. queueCreateInfo.queueFamilyIndex = queueFamily;
  601. queueCreateInfo.queueCount = 1;
  602. queueCreateInfo.pQueuePriorities = &queuePriority;
  603. queueCreateInfos.push_back(queueCreateInfo);
  604. }
  605. VkPhysicalDeviceFeatures deviceFeatures{};
  606. deviceFeatures.samplerAnisotropy = VK_TRUE;
  607. VkPhysicalDeviceFeatures2 deviceFeatures2{};
  608. deviceFeatures2.features.robustBufferAccess = VK_TRUE;
  609. deviceFeatures2.pNext = nullptr;
  610. VkDeviceCreateInfo createInfo{};
  611. createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  612. createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
  613. createInfo.pQueueCreateInfos = queueCreateInfos.data();
  614. createInfo.pEnabledFeatures = &deviceFeatures;
  615. createInfo.pNext = &deviceFeatures2;
  616. createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
  617. createInfo.ppEnabledExtensionNames = deviceExtensions.data();
  618. // can this be removed?
  619. if (enableValidationLayers) {
  620. createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  621. createInfo.ppEnabledLayerNames = validationLayers.data();
  622. }
  623. else {
  624. createInfo.enabledLayerCount = 0;
  625. }
  626. if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
  627. throw love::Exception("failed to create logical device");
  628. }
  629. vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
  630. vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
  631. }
  632. void Graphics::initVMA() {
  633. VmaVulkanFunctions vulkanFunctions = {};
  634. vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
  635. vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
  636. VmaAllocatorCreateInfo allocatorCreateInfo = {};
  637. allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
  638. allocatorCreateInfo.physicalDevice = physicalDevice;
  639. allocatorCreateInfo.device = device;
  640. allocatorCreateInfo.instance = instance;
  641. allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
  642. vmaCreateAllocator(&allocatorCreateInfo, &vmaAllocator);
  643. }
  644. void Graphics::createSurface() {
  645. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  646. const void* handle = window->getHandle();
  647. if (SDL_Vulkan_CreateSurface((SDL_Window*)handle, instance, &surface) != SDL_TRUE) {
  648. throw love::Exception("failed to create window surface");
  649. }
  650. }
  651. Graphics::SwapChainSupportDetails Graphics::querySwapChainSupport(VkPhysicalDevice device) {
  652. SwapChainSupportDetails details;
  653. vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
  654. uint32_t formatCount;
  655. vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
  656. if (formatCount != 0) {
  657. details.formats.resize(formatCount);
  658. vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
  659. }
  660. uint32_t presentModeCount;
  661. vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
  662. if (presentModeCount != 0) {
  663. details.presentModes.resize(presentModeCount);
  664. vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
  665. }
  666. return details;
  667. }
  668. void Graphics::createSwapChain() {
  669. SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);
  670. VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
  671. VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
  672. VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
  673. uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
  674. if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
  675. imageCount = swapChainSupport.capabilities.maxImageCount;
  676. }
  677. VkSwapchainCreateInfoKHR createInfo{};
  678. createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  679. createInfo.surface = surface;
  680. createInfo.minImageCount = imageCount;
  681. createInfo.imageFormat = surfaceFormat.format;
  682. createInfo.imageColorSpace = surfaceFormat.colorSpace;
  683. createInfo.imageExtent = extent;
  684. createInfo.imageArrayLayers = 1;
  685. createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  686. QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  687. uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };
  688. if (indices.graphicsFamily != indices.presentFamily) {
  689. createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  690. createInfo.queueFamilyIndexCount = 2;
  691. createInfo.pQueueFamilyIndices = queueFamilyIndices;
  692. }
  693. else {
  694. createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  695. createInfo.queueFamilyIndexCount = 0;
  696. createInfo.pQueueFamilyIndices = nullptr;
  697. }
  698. createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
  699. createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  700. createInfo.presentMode = presentMode;
  701. createInfo.clipped = VK_TRUE;
  702. createInfo.oldSwapchain = VK_NULL_HANDLE;
  703. if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
  704. throw love::Exception("failed to create swap chain");
  705. }
  706. vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
  707. swapChainImages.resize(imageCount);
  708. vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());
  709. swapChainImageFormat = surfaceFormat.format;
  710. swapChainExtent = extent;
  711. }
  712. VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
  713. for (const auto& availableFormat : availableFormats) {
  714. if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
  715. return availableFormat;
  716. }
  717. }
  718. return availableFormats[0];
  719. }
  720. VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) {
  721. // needed ?
  722. for (const auto& availablePresentMode : availablePresentModes) {
  723. if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
  724. return availablePresentMode;
  725. }
  726. }
  727. return VK_PRESENT_MODE_FIFO_KHR;
  728. }
  729. VkExtent2D Graphics::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) {
  730. if (capabilities.currentExtent.width != UINT32_MAX) {
  731. return capabilities.currentExtent;
  732. }
  733. else {
  734. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  735. const void* handle = window->getHandle();
  736. int width, height;
  737. // is this the equivalent of glfwGetFramebufferSize ?
  738. SDL_Vulkan_GetDrawableSize((SDL_Window*)handle, &width, &height);
  739. VkExtent2D actualExtent = {
  740. static_cast<uint32_t>(width),
  741. static_cast<uint32_t>(height)
  742. };
  743. actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
  744. actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
  745. return actualExtent;
  746. }
  747. }
  748. void Graphics::createImageViews() {
  749. swapChainImageViews.resize(swapChainImages.size());
  750. for (size_t i = 0; i < swapChainImages.size(); i++) {
  751. VkImageViewCreateInfo createInfo{};
  752. createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  753. createInfo.image = swapChainImages.at(i);
  754. createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  755. createInfo.format = swapChainImageFormat;
  756. createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  757. createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  758. createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  759. createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  760. createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  761. createInfo.subresourceRange.baseMipLevel = 0;
  762. createInfo.subresourceRange.levelCount = 1;
  763. createInfo.subresourceRange.baseArrayLayer = 0;
  764. createInfo.subresourceRange.layerCount = 1;
  765. if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews.at(i)) != VK_SUCCESS) {
  766. throw love::Exception("failed to create image views");
  767. }
  768. }
  769. }
  770. void Graphics::createRenderPass() {
  771. VkAttachmentDescription colorAttachment{};
  772. colorAttachment.format = swapChainImageFormat;
  773. colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
  774. colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  775. colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  776. colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  777. colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  778. colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  779. colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  780. VkAttachmentReference colorAttachmentRef{};
  781. colorAttachmentRef.attachment = 0;
  782. colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  783. VkSubpassDescription subpass{};
  784. subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  785. subpass.colorAttachmentCount = 1;
  786. subpass.pColorAttachments = &colorAttachmentRef;
  787. VkSubpassDependency dependency{};
  788. dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
  789. dependency.dstSubpass = 0;
  790. dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  791. dependency.srcAccessMask = 0;
  792. dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  793. dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  794. VkRenderPassCreateInfo renderPassInfo{};
  795. renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  796. renderPassInfo.attachmentCount = 1;
  797. renderPassInfo.pAttachments = &colorAttachment;
  798. renderPassInfo.subpassCount = 1;
  799. renderPassInfo.pSubpasses = &subpass;
  800. renderPassInfo.dependencyCount = 1;
  801. renderPassInfo.pDependencies = &dependency;
  802. if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
  803. throw love::Exception("failed to create render pass");
  804. }
  805. }
  806. void Graphics::createDefaultShaders() {
  807. for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++) {
  808. auto stype = (Shader::StandardShader)i;
  809. if (!Shader::standardShaders[i]) {
  810. std::vector<std::string> stages;
  811. stages.push_back(Shader::getDefaultCode(stype, SHADERSTAGE_VERTEX));
  812. stages.push_back(Shader::getDefaultCode(stype, SHADERSTAGE_PIXEL));
  813. Shader::standardShaders[i] = newShader(stages, { { {"vulkan", "1"} } });
  814. }
  815. }
  816. }
  817. void Graphics::createDescriptorSetLayout() {
  818. VkDescriptorSetLayoutBinding uboLayoutBinding{};
  819. uboLayoutBinding.binding = 0;
  820. uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  821. uboLayoutBinding.descriptorCount = 1;
  822. uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
  823. VkDescriptorSetLayoutBinding samplerLayoutBinding{};
  824. samplerLayoutBinding.binding = 1;
  825. samplerLayoutBinding.descriptorCount = 1;
  826. samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  827. samplerLayoutBinding.pImmutableSamplers = nullptr;
  828. samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  829. std::array<VkDescriptorSetLayoutBinding, 2> bindings = { uboLayoutBinding, samplerLayoutBinding };
  830. VkDescriptorSetLayoutCreateInfo layoutInfo{};
  831. layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  832. layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
  833. layoutInfo.pBindings = bindings.data();
  834. if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
  835. throw love::Exception("failed to create descriptor set layout");
  836. }
  837. }
  838. void Graphics::createDescriptorPool() {
  839. std::array<VkDescriptorPoolSize, 2> poolSizes{};
  840. poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  841. poolSizes[0].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
  842. poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  843. poolSizes[1].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
  844. VkDescriptorPoolCreateInfo poolInfo{};
  845. poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  846. poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
  847. poolInfo.pPoolSizes = poolSizes.data();
  848. // FIXME: When using more than 128 textures at once we will run out of memory.
  849. // we probably want to reuse descriptors per flight image
  850. // and use multiple pools in case of too many allocations
  851. poolInfo.maxSets = 128 * static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
  852. if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
  853. throw love::Exception("failed to create descriptor pool");
  854. }
  855. }
  856. std::vector<VkDescriptorSet> Graphics::createDescriptorSets(DecriptorSetConfiguration config) {
  857. std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout);
  858. VkDescriptorSetAllocateInfo allocInfo{};
  859. allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  860. allocInfo.descriptorPool = descriptorPool;
  861. allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
  862. allocInfo.pSetLayouts = layouts.data();
  863. std::vector<VkDescriptorSet> newDescriptorSets;
  864. newDescriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
  865. VkResult result = vkAllocateDescriptorSets(device, &allocInfo, newDescriptorSets.data());
  866. if (result != VK_SUCCESS) {
  867. switch (result) {
  868. case VK_ERROR_OUT_OF_HOST_MEMORY:
  869. throw love::Exception("failed to allocate descriptor sets: out of host memory");
  870. case VK_ERROR_OUT_OF_DEVICE_MEMORY:
  871. throw love::Exception("failed to allocate descriptor sets: out of device memory");
  872. case VK_ERROR_FRAGMENTED_POOL:
  873. throw love::Exception("failed to allocate descriptor sets: fragmented pool");
  874. case VK_ERROR_OUT_OF_POOL_MEMORY:
  875. throw love::Exception("failed to allocate descriptor sets: out of pool memory");
  876. default:
  877. throw love::Exception("failed to allocate descriptor sets");
  878. }
  879. }
  880. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
  881. VkDescriptorBufferInfo bufferInfo{};
  882. bufferInfo.buffer = (VkBuffer)config.buffer->getHandle();
  883. bufferInfo.offset = 0;
  884. bufferInfo.range = sizeof(graphics::Shader::BuiltinUniformData);
  885. VkDescriptorImageInfo imageInfo{};
  886. imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  887. Texture* vkTexture = (Texture*)config.texture;
  888. imageInfo.imageView = vkTexture->getImageView();
  889. imageInfo.sampler = vkTexture->getSampler();
  890. std::array<VkWriteDescriptorSet, 2> descriptorWrite{};
  891. descriptorWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  892. descriptorWrite[0].dstSet = newDescriptorSets[i];
  893. descriptorWrite[0].dstBinding = 0;
  894. descriptorWrite[0].dstArrayElement = 0;
  895. descriptorWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  896. descriptorWrite[0].descriptorCount = 1;
  897. descriptorWrite[0].pBufferInfo = &bufferInfo;
  898. descriptorWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  899. descriptorWrite[1].dstSet = newDescriptorSets[i];
  900. descriptorWrite[1].dstBinding = 1;
  901. descriptorWrite[1].dstArrayElement = 0;
  902. descriptorWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  903. descriptorWrite[1].descriptorCount = 1;
  904. descriptorWrite[1].pImageInfo = &imageInfo;
  905. vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr);
  906. }
  907. return newDescriptorSets;
  908. }
  909. void Graphics::createVulkanVertexFormat(
  910. VertexAttributes vertexAttributes,
  911. bool& useConstantVertexColor,
  912. GraphicsPipelineConfiguration& configuration) {
  913. std::set<uint32_t> usedBuffers;
  914. std::vector<VkVertexInputBindingDescription> bindingDescriptions;
  915. std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
  916. auto allBits = vertexAttributes.enableBits;
  917. bool usesColor = false;
  918. for (uint32_t i = 0; i < VertexAttributes::MAX; i++) { // change to loop like in opengl implementation ?
  919. uint32 bit = 1u << i;
  920. if (allBits & bit) {
  921. if (i == ATTRIB_COLOR) {
  922. usesColor = true;
  923. }
  924. auto attrib = vertexAttributes.attribs[i];
  925. auto bufferBinding = attrib.bufferIndex;
  926. if (usedBuffers.find(bufferBinding) == usedBuffers.end()) { // use .contains() when c++20 is enabled
  927. usedBuffers.insert(bufferBinding);
  928. VkVertexInputBindingDescription bindingDescription{};
  929. bindingDescription.binding = bufferBinding;
  930. bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
  931. bindingDescription.stride = vertexAttributes.bufferLayouts[bufferBinding].stride;
  932. bindingDescriptions.push_back(bindingDescription);
  933. }
  934. VkVertexInputAttributeDescription attributeDescription{};
  935. attributeDescription.location = i;
  936. attributeDescription.binding = bufferBinding;
  937. attributeDescription.offset = attrib.offsetFromVertex;
  938. attributeDescription.format = Vulkan::getVulkanVertexFormat(attrib.format);
  939. attributeDescriptions.push_back(attributeDescription);
  940. }
  941. }
  942. // do we need to use a constant VertexColor?
  943. if (!usesColor) {
  944. constexpr uint32_t constantColorBufferBinding = 2;
  945. VkVertexInputBindingDescription bindingDescription{};
  946. bindingDescription.binding = constantColorBufferBinding;
  947. bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
  948. bindingDescription.stride = 0; // no stride, will always read the same color multiple times.
  949. bindingDescriptions.push_back(bindingDescription);
  950. VkVertexInputAttributeDescription attributeDescription{};
  951. attributeDescription.binding = constantColorBufferBinding;
  952. attributeDescription.location = ATTRIB_COLOR;
  953. attributeDescription.offset = 0;
  954. attributeDescription.format = VK_FORMAT_R32G32B32A32_SFLOAT;
  955. useConstantVertexColor = true;
  956. }
  957. else {
  958. useConstantVertexColor = false;
  959. }
  960. configuration.vertexInputBindingDescriptions = bindingDescriptions;
  961. configuration.vertexInputAttributeDescriptions = attributeDescriptions;
  962. }
  963. VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration configuration) {
  964. auto shader = reinterpret_cast<love::graphics::vulkan::Shader*>(love::graphics::vulkan::Shader::standardShaders[Shader::STANDARD_DEFAULT]);
  965. auto shaderStages = shader->getShaderStages();
  966. VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
  967. vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  968. vertexInputInfo.vertexBindingDescriptionCount = configuration.vertexInputBindingDescriptions.size();
  969. vertexInputInfo.pVertexBindingDescriptions = configuration.vertexInputBindingDescriptions.data();
  970. vertexInputInfo.vertexAttributeDescriptionCount = configuration.vertexInputAttributeDescriptions.size();
  971. vertexInputInfo.pVertexAttributeDescriptions = configuration.vertexInputAttributeDescriptions.data();
  972. VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
  973. inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  974. inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  975. inputAssembly.primitiveRestartEnable = VK_FALSE;
  976. VkViewport viewport{};
  977. viewport.x = 0.0f;
  978. viewport.y = 0.0f;
  979. viewport.width = (float)swapChainExtent.width;
  980. viewport.height = (float)swapChainExtent.height;
  981. viewport.minDepth = 0.0f;
  982. viewport.maxDepth = 1.0f;
  983. VkRect2D scissor{};
  984. scissor.offset = { 0, 0 };
  985. scissor.extent = swapChainExtent;
  986. VkPipelineViewportStateCreateInfo viewportState{};
  987. viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  988. viewportState.viewportCount = 1;
  989. viewportState.pViewports = &viewport;
  990. viewportState.scissorCount = 1;
  991. viewportState.pScissors = &scissor;
  992. VkPipelineRasterizationStateCreateInfo rasterizer{};
  993. rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  994. rasterizer.depthClampEnable = VK_FALSE;
  995. rasterizer.rasterizerDiscardEnable = VK_FALSE;
  996. rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
  997. rasterizer.lineWidth = 1.0f;
  998. rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT;
  999. rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
  1000. rasterizer.depthBiasEnable = VK_FALSE;
  1001. rasterizer.depthBiasConstantFactor = 0.0f;
  1002. rasterizer.depthBiasClamp = 0.0f;
  1003. rasterizer.depthBiasSlopeFactor = 0.0f;
  1004. VkPipelineMultisampleStateCreateInfo multisampling{};
  1005. multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  1006. multisampling.sampleShadingEnable = VK_FALSE;
  1007. multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  1008. multisampling.minSampleShading = 1.0f; // Optional
  1009. multisampling.pSampleMask = nullptr; // Optional
  1010. multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
  1011. multisampling.alphaToOneEnable = VK_FALSE; // Optional
  1012. VkPipelineColorBlendAttachmentState colorBlendAttachment{};
  1013. colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
  1014. colorBlendAttachment.blendEnable = VK_TRUE;
  1015. colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
  1016. colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
  1017. colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
  1018. colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
  1019. colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
  1020. colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
  1021. VkPipelineColorBlendStateCreateInfo colorBlending{};
  1022. colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  1023. colorBlending.logicOpEnable = VK_FALSE;
  1024. colorBlending.logicOp = VK_LOGIC_OP_COPY;
  1025. colorBlending.attachmentCount = 1;
  1026. colorBlending.pAttachments = &colorBlendAttachment;
  1027. colorBlending.blendConstants[0] = 0.0f;
  1028. colorBlending.blendConstants[1] = 0.0f;
  1029. colorBlending.blendConstants[2] = 0.0f;
  1030. colorBlending.blendConstants[3] = 0.0f;
  1031. VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
  1032. pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  1033. pipelineLayoutInfo.setLayoutCount = 1;
  1034. pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
  1035. pipelineLayoutInfo.pushConstantRangeCount = 0;
  1036. if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
  1037. throw love::Exception("failed to create pipeline layout");
  1038. }
  1039. VkGraphicsPipelineCreateInfo pipelineInfo{};
  1040. pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  1041. pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
  1042. pipelineInfo.pStages = shaderStages.data();
  1043. pipelineInfo.pVertexInputState = &vertexInputInfo;
  1044. pipelineInfo.pInputAssemblyState = &inputAssembly;
  1045. pipelineInfo.pViewportState = &viewportState;
  1046. pipelineInfo.pRasterizationState = &rasterizer;
  1047. pipelineInfo.pMultisampleState = &multisampling;
  1048. pipelineInfo.pDepthStencilState = nullptr;
  1049. pipelineInfo.pColorBlendState = &colorBlending;
  1050. pipelineInfo.pDynamicState = nullptr;
  1051. pipelineInfo.layout = pipelineLayout;
  1052. pipelineInfo.renderPass = renderPass;
  1053. pipelineInfo.subpass = 0;
  1054. pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
  1055. pipelineInfo.basePipelineIndex = -1;
  1056. VkPipeline graphicsPipeline;
  1057. if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
  1058. throw love::Exception("failed to create graphics pipeline");
  1059. }
  1060. return graphicsPipeline;
  1061. }
  1062. void Graphics::ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration configuration) {
  1063. VkPipeline pipeline = VK_NULL_HANDLE;
  1064. for (auto const& p : graphicsPipelines) {
  1065. if (p.first == configuration) {
  1066. pipeline = p.second;
  1067. break;
  1068. }
  1069. }
  1070. if (pipeline != VK_NULL_HANDLE) {
  1071. if (currentGraphicsPipeline != pipeline) {
  1072. vkCmdBindPipeline(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
  1073. currentGraphicsPipeline = pipeline;
  1074. }
  1075. } else {
  1076. VkPipeline newPipeLine = createGraphicsPipeline(configuration);
  1077. graphicsPipelines.push_back(std::make_pair(configuration, newPipeLine));
  1078. vkCmdBindPipeline(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, newPipeLine);
  1079. currentGraphicsPipeline = newPipeLine;
  1080. }
  1081. }
  1082. void Graphics::createFramebuffers() {
  1083. swapChainFramBuffers.resize(swapChainImageViews.size());
  1084. for (size_t i = 0; i < swapChainImageViews.size(); i++) {
  1085. VkImageView attachments[] = {
  1086. swapChainImageViews.at(i)
  1087. };
  1088. VkFramebufferCreateInfo framebufferInfo{};
  1089. framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  1090. framebufferInfo.renderPass = renderPass;
  1091. framebufferInfo.attachmentCount = 1;
  1092. framebufferInfo.pAttachments = attachments;
  1093. framebufferInfo.width = swapChainExtent.width;
  1094. framebufferInfo.height = swapChainExtent.height;
  1095. framebufferInfo.layers = 1;
  1096. if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramBuffers.at(i)) != VK_SUCCESS) {
  1097. throw love::Exception("failed to create framebuffers");
  1098. }
  1099. }
  1100. }
  1101. void Graphics::createCommandPool() {
  1102. QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);
  1103. VkCommandPoolCreateInfo poolInfo{};
  1104. poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  1105. poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
  1106. poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  1107. if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
  1108. throw love::Exception("failed to create command pool");
  1109. }
  1110. }
  1111. void Graphics::createCommandBuffers() {
  1112. commandBuffers.resize(swapChainFramBuffers.size());
  1113. VkCommandBufferAllocateInfo allocInfo{};
  1114. allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  1115. allocInfo.commandPool = commandPool;
  1116. allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  1117. allocInfo.commandBufferCount = (uint32_t)commandBuffers.size();
  1118. if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
  1119. throw love::Exception("failed to allocate command buffers");
  1120. }
  1121. }
  1122. void Graphics::createSyncObjects() {
  1123. imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  1124. renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  1125. inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
  1126. imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE);
  1127. VkSemaphoreCreateInfo semaphoreInfo{};
  1128. semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  1129. VkFenceCreateInfo fenceInfo{};
  1130. fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  1131. fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  1132. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
  1133. if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores.at(i)) != VK_SUCCESS ||
  1134. vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores.at(i)) != VK_SUCCESS ||
  1135. vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences.at(i)) != VK_SUCCESS) {
  1136. throw love::Exception("failed to create synchronization objects for a frame!");
  1137. }
  1138. }
  1139. }
  1140. void Graphics::createDefaultTexture() {
  1141. Texture::Settings settings;
  1142. standardTexture = newTexture(settings);
  1143. }
  1144. void Graphics::createQuadIndexBuffer() {
  1145. if (quadIndexBuffer != nullptr)
  1146. return;
  1147. size_t size = sizeof(uint16) * getIndexCount(TRIANGLEINDEX_QUADS, LOVE_UINT16_MAX);
  1148. quadIndexBuffer = static_cast<StreamBuffer*>(newStreamBuffer(BUFFERUSAGE_INDEX, size));
  1149. auto map = quadIndexBuffer->map(size);
  1150. fillIndices(TRIANGLEINDEX_QUADS, 0, LOVE_UINT16_MAX, (uint16*)map.data);
  1151. quadIndexBuffer->unmap(size);
  1152. }
  1153. bool operator==(const Graphics::GraphicsPipelineConfiguration& first, const Graphics::GraphicsPipelineConfiguration& other) {
  1154. if (first.vertexInputAttributeDescriptions.size() != other.vertexInputAttributeDescriptions.size()) {
  1155. return false;
  1156. }
  1157. if (first.vertexInputBindingDescriptions.size() != other.vertexInputBindingDescriptions.size()) {
  1158. return false;
  1159. }
  1160. for (uint32_t i = 0; i < first.vertexInputAttributeDescriptions.size(); i++) {
  1161. const VkVertexInputAttributeDescription& x = first.vertexInputAttributeDescriptions[i];
  1162. const VkVertexInputAttributeDescription& y = other.vertexInputAttributeDescriptions[i];
  1163. if (x.binding != y.binding) {
  1164. return false;
  1165. }
  1166. if (x.location != y.location) {
  1167. return false;
  1168. }
  1169. if (x.offset != y.offset) {
  1170. return false;
  1171. }
  1172. if (x.format != y.format) {
  1173. return false;
  1174. }
  1175. }
  1176. for (uint32_t i = 0; i < first.vertexInputBindingDescriptions.size(); i++) {
  1177. const VkVertexInputBindingDescription& x = first.vertexInputBindingDescriptions[i];
  1178. const VkVertexInputBindingDescription& y = other.vertexInputBindingDescriptions[i];
  1179. if (x.binding != y.binding) {
  1180. return false;
  1181. }
  1182. if (x.inputRate != y.inputRate) {
  1183. return false;
  1184. }
  1185. if (x.stride != y.stride) {
  1186. return false;
  1187. }
  1188. }
  1189. return true;
  1190. }
  1191. void Graphics::cleanup() {
  1192. vkDeviceWaitIdle(device);
  1193. cleanupSwapChain();
  1194. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
  1195. vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
  1196. vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
  1197. vkDestroyFence(device, inFlightFences[i], nullptr);
  1198. }
  1199. vkDestroyDescriptorPool(device, descriptorPool, nullptr);
  1200. vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
  1201. vkDestroyCommandPool(device, commandPool, nullptr);
  1202. vkDestroyDevice(device, nullptr);
  1203. vkDestroySurfaceKHR(instance, surface, nullptr);
  1204. vkDestroyInstance(instance, nullptr);
  1205. }
  1206. void Graphics::cleanupSwapChain() {
  1207. std::cout << "cleanupSwapChain ";
  1208. for (size_t i = 0; i < swapChainFramBuffers.size(); i++) {
  1209. vkDestroyFramebuffer(device, swapChainFramBuffers[i], nullptr);
  1210. }
  1211. vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
  1212. for (auto const& p : graphicsPipelines) {
  1213. vkDestroyPipeline(device, p.second, nullptr);
  1214. }
  1215. graphicsPipelines.clear();
  1216. currentGraphicsPipeline = VK_NULL_HANDLE;
  1217. // vkDestroyPipelineLayout(device, pipelineLayout, nullptr); FIXME
  1218. vkDestroyRenderPass(device, renderPass, nullptr);
  1219. for (size_t i = 0; i < swapChainImageViews.size(); i++) {
  1220. vkDestroyImageView(device, swapChainImageViews[i], nullptr);
  1221. }
  1222. vkDestroySwapchainKHR(device, swapChain, nullptr);
  1223. uniformBufferMap.clear();
  1224. descriptorSetsMap.clear();
  1225. }
  1226. void Graphics::recreateSwapChain() {
  1227. vkDeviceWaitIdle(device);
  1228. cleanupSwapChain();
  1229. createSwapChain();
  1230. createImageViews();
  1231. createRenderPass();
  1232. createFramebuffers();
  1233. createDescriptorPool();
  1234. createCommandBuffers();
  1235. startRecordingGraphicsCommands();
  1236. }
  1237. love::graphics::Graphics* createInstance() {
  1238. love::graphics::Graphics* instance = nullptr;
  1239. try {
  1240. instance = new Graphics();
  1241. }
  1242. catch (love::Exception& e) {
  1243. printf("Cannot create Vulkan renderer: %s\n", e.what());
  1244. }
  1245. return instance;
  1246. }
  1247. }
  1248. }
  1249. }