Graphics.cpp 87 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558
  1. #include "Graphics.h"
  2. #include "Buffer.h"
  3. #include "GraphicsReadback.h"
  4. #include "SDL_vulkan.h"
  5. #include "window/Window.h"
  6. #include "common/Exception.h"
  7. #include "Shader.h"
  8. #include "graphics/Texture.h"
  9. #include "Vulkan.h"
  10. #include "common/version.h"
  11. #include "common/pixelformat.h"
  12. #include <algorithm>
  13. #include <vector>
  14. #include <cstring>
  15. #include <set>
  16. #include <fstream>
  17. #include <sstream>
  18. #include <iostream>
  19. #include <array>
  20. namespace love
  21. {
  22. namespace graphics
  23. {
  24. namespace vulkan
  25. {
  26. const std::vector<const char*> validationLayers = {
  27. "VK_LAYER_KHRONOS_validation"
  28. };
  29. const std::vector<const char*> deviceExtensions = {
  30. VK_KHR_SWAPCHAIN_EXTENSION_NAME,
  31. };
  32. #ifdef NDEBUG
  33. constexpr bool enableValidationLayers = false;
  34. #else
  35. constexpr bool enableValidationLayers = true;
  36. #endif
  37. constexpr int MAX_FRAMES_IN_FLIGHT = 2;
  38. constexpr uint32_t vulkanApiVersion = VK_API_VERSION_1_0;
  39. const char *Graphics::getName() const
  40. {
  41. return "love.graphics.vulkan";
  42. }
  43. const VkDevice Graphics::getDevice() const
  44. {
  45. return device;
  46. }
  47. const VkPhysicalDevice Graphics::getPhysicalDevice() const
  48. {
  49. return physicalDevice;
  50. }
  51. const VmaAllocator Graphics::getVmaAllocator() const
  52. {
  53. return vmaAllocator;
  54. }
  55. Graphics::~Graphics()
  56. {
  57. // We already cleaned those up by clearing out batchedDrawBuffers.
  58. // We set them to nullptr here so the base class doesn't crash
  59. // when it tries to free this.
  60. batchedDrawState.vb[0] = nullptr;
  61. batchedDrawState.vb[1] = nullptr;
  62. batchedDrawState.indexBuffer = nullptr;
  63. }
  64. // START OVERRIDEN FUNCTIONS
  65. love::graphics::Texture *Graphics::newTexture(const love::graphics::Texture::Settings &settings, const love::graphics::Texture::Slices *data)
  66. {
  67. return new Texture(this, settings, data);
  68. }
  69. 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)
  70. {
  71. return new Buffer(this, settings, format, data, size, arraylength);
  72. }
  73. void Graphics::clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth)
  74. {
  75. if (!renderPassState.active)
  76. startRenderPass();
  77. VkClearAttachment attachment{};
  78. if (color.hasValue)
  79. {
  80. attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  81. attachment.clearValue.color.float32[0] = static_cast<float>(color.value.r);
  82. attachment.clearValue.color.float32[1] = static_cast<float>(color.value.g);
  83. attachment.clearValue.color.float32[2] = static_cast<float>(color.value.b);
  84. attachment.clearValue.color.float32[3] = static_cast<float>(color.value.a);
  85. }
  86. VkClearAttachment depthStencilAttachment{};
  87. if (stencil.hasValue)
  88. {
  89. depthStencilAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
  90. depthStencilAttachment.clearValue.depthStencil.stencil = static_cast<uint32_t>(stencil.value);
  91. }
  92. if (depth.hasValue)
  93. {
  94. depthStencilAttachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
  95. depthStencilAttachment.clearValue.depthStencil.depth = static_cast<float>(depth.value);
  96. }
  97. std::array<VkClearAttachment, 2> attachments = {
  98. attachment,
  99. depthStencilAttachment
  100. };
  101. VkClearRect rect{};
  102. rect.layerCount = 1;
  103. rect.rect.extent.width = static_cast<uint32_t>(renderPassState.width);
  104. rect.rect.extent.height = static_cast<uint32_t>(renderPassState.height);
  105. vkCmdClearAttachments(
  106. commandBuffers[currentFrame],
  107. static_cast<uint32_t>(attachments.size()), attachments.data(),
  108. 1, &rect);
  109. }
  110. void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt stencil, OptionalDouble depth)
  111. {
  112. if (!renderPassState.active)
  113. startRenderPass();
  114. std::vector<VkClearAttachment> attachments;
  115. for (const auto &color : colors)
  116. {
  117. VkClearAttachment attachment{};
  118. if (color.hasValue)
  119. {
  120. attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  121. attachment.clearValue.color.float32[0] = static_cast<float>(color.value.r);
  122. attachment.clearValue.color.float32[1] = static_cast<float>(color.value.g);
  123. attachment.clearValue.color.float32[2] = static_cast<float>(color.value.b);
  124. attachment.clearValue.color.float32[3] = static_cast<float>(color.value.a);
  125. }
  126. attachments.push_back(attachment);
  127. }
  128. VkClearAttachment depthStencilAttachment{};
  129. if (stencil.hasValue)
  130. {
  131. depthStencilAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
  132. depthStencilAttachment.clearValue.depthStencil.stencil = static_cast<uint32_t>(stencil.value);
  133. }
  134. if (depth.hasValue)
  135. {
  136. depthStencilAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
  137. depthStencilAttachment.clearValue.depthStencil.depth = static_cast<float>(depth.value);
  138. }
  139. attachments.push_back(depthStencilAttachment);
  140. VkClearRect rect{};
  141. rect.layerCount = 1;
  142. rect.rect.extent.width = static_cast<uint32_t>(renderPassState.width);
  143. rect.rect.extent.height = static_cast<uint32_t>(renderPassState.height);
  144. vkCmdClearAttachments(commandBuffers[currentFrame], static_cast<uint32_t>(attachments.size()), attachments.data(), 1, &rect);
  145. }
  146. void Graphics::submitGpuCommands(bool present)
  147. {
  148. flushBatchedDraws();
  149. endRecordingGraphicsCommands(present);
  150. if (imagesInFlight[imageIndex] != VK_NULL_HANDLE)
  151. vkWaitForFences(device, 1, &imagesInFlight.at(imageIndex), VK_TRUE, UINT64_MAX);
  152. imagesInFlight[imageIndex] = inFlightFences[currentFrame];
  153. std::array<VkCommandBuffer, 1> submitCommandbuffers = { commandBuffers.at(currentFrame) };
  154. VkSubmitInfo submitInfo{};
  155. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  156. VkSemaphore waitSemaphores[] = { imageAvailableSemaphores.at(currentFrame) };
  157. VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
  158. if (imageRequested)
  159. {
  160. submitInfo.waitSemaphoreCount = 1;
  161. submitInfo.pWaitSemaphores = waitSemaphores;
  162. submitInfo.pWaitDstStageMask = waitStages;
  163. imageRequested = false;
  164. }
  165. submitInfo.commandBufferCount = static_cast<uint32_t>(submitCommandbuffers.size());
  166. submitInfo.pCommandBuffers = submitCommandbuffers.data();
  167. VkSemaphore signalSemaphores[] = { renderFinishedSemaphores.at(currentFrame) };
  168. VkFence fence = VK_NULL_HANDLE;
  169. if (present)
  170. {
  171. submitInfo.signalSemaphoreCount = 1;
  172. submitInfo.pSignalSemaphores = signalSemaphores;
  173. vkResetFences(device, 1, &inFlightFences[currentFrame]);
  174. fence = inFlightFences[currentFrame];
  175. }
  176. if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, fence) != VK_SUCCESS)
  177. throw love::Exception("failed to submit draw command buffer");
  178. if (!present)
  179. {
  180. vkQueueWaitIdle(graphicsQueue);
  181. for (auto &callbacks : readbackCallbacks)
  182. {
  183. for (const auto &callback : callbacks)
  184. callback();
  185. callbacks.clear();
  186. }
  187. startRecordingGraphicsCommands(false);
  188. }
  189. }
  190. void Graphics::present(void *screenshotCallbackdata)
  191. {
  192. if (!isActive())
  193. return;
  194. if (isRenderTargetActive())
  195. throw love::Exception("present cannot be called while a render target is active.");
  196. deprecations.draw(this);
  197. submitGpuCommands(true);
  198. VkPresentInfoKHR presentInfo{};
  199. presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  200. VkSemaphore waitSemaphores[] = { renderFinishedSemaphores.at(currentFrame) };
  201. presentInfo.waitSemaphoreCount = 1;
  202. presentInfo.pWaitSemaphores = waitSemaphores;
  203. VkSwapchainKHR swapChains[] = { swapChain };
  204. presentInfo.swapchainCount = 1;
  205. presentInfo.pSwapchains = swapChains;
  206. presentInfo.pImageIndices = &imageIndex;
  207. VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo);
  208. if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized)
  209. {
  210. framebufferResized = false;
  211. recreateSwapChain();
  212. }
  213. else if (result != VK_SUCCESS)
  214. throw love::Exception("failed to present swap chain image");
  215. drawCalls = 0;
  216. renderTargetSwitchCount = 0;
  217. drawCallsBatched = 0;
  218. updatePendingReadbacks();
  219. updateTemporaryResources();
  220. currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
  221. beginFrame();
  222. updatedBatchedDrawBuffers();
  223. }
  224. void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight)
  225. {
  226. this->width = width;
  227. this->height = height;
  228. this->pixelWidth = pixelwidth;
  229. this->pixelHeight = pixelheight;
  230. resetProjection();
  231. }
  232. bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa)
  233. {
  234. requestedMsaa = msaa;
  235. cleanUpFunctions.clear();
  236. cleanUpFunctions.resize(MAX_FRAMES_IN_FLIGHT);
  237. readbackCallbacks.clear();
  238. readbackCallbacks.resize(MAX_FRAMES_IN_FLIGHT);
  239. createVulkanInstance();
  240. createSurface();
  241. pickPhysicalDevice();
  242. createLogicalDevice();
  243. initVMA();
  244. initCapabilities();
  245. createSwapChain();
  246. createImageViews();
  247. createSyncObjects();
  248. createColorResources();
  249. createDepthResources();
  250. createDefaultRenderPass();
  251. createDefaultFramebuffers();
  252. createCommandPool();
  253. createCommandBuffers();
  254. float whiteColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  255. batchedDrawBuffers.clear();
  256. batchedDrawBuffers.reserve(MAX_FRAMES_IN_FLIGHT);
  257. for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
  258. {
  259. batchedDrawBuffers.emplace_back();
  260. // Initial sizes that should be good enough for most cases. It will
  261. // resize to fit if needed, later.
  262. batchedDrawBuffers[i].vertexBuffer1 = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
  263. batchedDrawBuffers[i].vertexBuffer2 = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
  264. batchedDrawBuffers[i].indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
  265. // sometimes the VertexColor is not set, so we manually adjust it to white color
  266. batchedDrawBuffers[i].constantColorBuffer = new StreamBuffer(this, BUFFERUSAGE_VERTEX, sizeof(whiteColor));
  267. auto mapInfo = batchedDrawBuffers[i].constantColorBuffer->map(sizeof(whiteColor));
  268. memcpy(mapInfo.data, whiteColor, sizeof(whiteColor));
  269. batchedDrawBuffers[i].constantColorBuffer->unmap(sizeof(whiteColor));
  270. batchedDrawBuffers[i].constantColorBuffer->markUsed(sizeof(whiteColor));
  271. }
  272. updatedBatchedDrawBuffers();
  273. beginFrame();
  274. createDefaultTexture();
  275. createDefaultShaders();
  276. Shader::current = Shader::standardShaders[graphics::Shader::StandardShader::STANDARD_DEFAULT];
  277. createQuadIndexBuffer();
  278. restoreState(states.back());
  279. setViewportSize(width, height, pixelwidth, pixelheight);
  280. Vulkan::resetShaderSwitches();
  281. currentFrame = 0;
  282. created = true;
  283. drawCalls = 0;
  284. drawCallsBatched = 0;
  285. return true;
  286. }
  287. void Graphics::initCapabilities()
  288. {
  289. // todo
  290. capabilities.features[FEATURE_MULTI_RENDER_TARGET_FORMATS] = false;
  291. capabilities.features[FEATURE_CLAMP_ZERO] = false;
  292. capabilities.features[FEATURE_CLAMP_ONE] = false;
  293. capabilities.features[FEATURE_BLEND_MINMAX] = false;
  294. capabilities.features[FEATURE_LIGHTEN] = false;
  295. capabilities.features[FEATURE_FULL_NPOT] = false;
  296. capabilities.features[FEATURE_PIXEL_SHADER_HIGHP] = true;
  297. capabilities.features[FEATURE_SHADER_DERIVATIVES] = true;
  298. capabilities.features[FEATURE_GLSL3] = true;
  299. capabilities.features[FEATURE_GLSL4] = true;
  300. capabilities.features[FEATURE_INSTANCING] = true;
  301. capabilities.features[FEATURE_TEXEL_BUFFER] = false;
  302. capabilities.features[FEATURE_INDEX_BUFFER_32BIT] = true;
  303. capabilities.features[FEATURE_COPY_BUFFER] = true;
  304. capabilities.features[FEATURE_COPY_BUFFER_TO_TEXTURE] = true;
  305. capabilities.features[FEATURE_COPY_TEXTURE_TO_BUFFER] = true;
  306. capabilities.features[FEATURE_COPY_RENDER_TARGET_TO_BUFFER] = true;
  307. static_assert(FEATURE_MAX_ENUM == 17, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
  308. VkPhysicalDeviceProperties properties;
  309. vkGetPhysicalDeviceProperties(physicalDevice, &properties);
  310. capabilities.limits[LIMIT_POINT_SIZE] = properties.limits.pointSizeRange[1];
  311. capabilities.limits[LIMIT_TEXTURE_SIZE] = properties.limits.maxImageDimension2D;
  312. capabilities.limits[LIMIT_TEXTURE_LAYERS] = properties.limits.maxImageArrayLayers;
  313. capabilities.limits[LIMIT_VOLUME_TEXTURE_SIZE] = properties.limits.maxImageDimension3D;
  314. capabilities.limits[LIMIT_CUBE_TEXTURE_SIZE] = properties.limits.maxImageDimensionCube;
  315. capabilities.limits[LIMIT_TEXEL_BUFFER_SIZE] = properties.limits.maxTexelBufferElements; // ?
  316. capabilities.limits[LIMIT_SHADER_STORAGE_BUFFER_SIZE] = properties.limits.maxStorageBufferRange; // ?
  317. capabilities.limits[LIMIT_THREADGROUPS_X] = properties.limits.maxComputeWorkGroupSize[0]; // this is correct?
  318. capabilities.limits[LIMIT_THREADGROUPS_Y] = properties.limits.maxComputeWorkGroupSize[1];
  319. capabilities.limits[LIMIT_THREADGROUPS_Z] = properties.limits.maxComputeWorkGroupSize[2];
  320. capabilities.limits[LIMIT_RENDER_TARGETS] = properties.limits.maxColorAttachments;
  321. capabilities.limits[LIMIT_TEXTURE_MSAA] = 1; // todo
  322. capabilities.limits[LIMIT_ANISOTROPY] = properties.limits.maxSamplerAnisotropy;
  323. static_assert(LIMIT_MAX_ENUM == 13, "Graphics::initCapabilities must be updated when adding a new system limit!");
  324. capabilities.textureTypes[TEXTURE_2D] = true;
  325. capabilities.textureTypes[TEXTURE_2D_ARRAY] = true;
  326. capabilities.textureTypes[TEXTURE_VOLUME] = false;
  327. capabilities.textureTypes[TEXTURE_CUBE] = true;
  328. }
  329. void Graphics::getAPIStats(int &shaderswitches) const
  330. {
  331. shaderswitches = static_cast<int>(Vulkan::getNumShaderSwitches());
  332. }
  333. void Graphics::unSetMode()
  334. {
  335. created = false;
  336. vkDeviceWaitIdle(device);
  337. Volatile::unloadAll();
  338. cleanup();
  339. }
  340. void Graphics::setActive(bool enable)
  341. {
  342. flushBatchedDraws();
  343. active = enable;
  344. }
  345. int Graphics::getRequestedBackbufferMSAA() const
  346. {
  347. return requestedMsaa;
  348. }
  349. int Graphics::getBackbufferMSAA() const
  350. {
  351. return static_cast<int>(msaaSamples);
  352. }
  353. void Graphics::setFrontFaceWinding(Winding winding)
  354. {
  355. const auto& currentState = states.back();
  356. if (currentState.winding == winding)
  357. return;
  358. flushBatchedDraws();
  359. states.back().winding = winding;
  360. if (optionalDeviceFeatures.extendedDynamicState)
  361. ext.vkCmdSetFrontFaceEXT(
  362. commandBuffers.at(currentFrame),
  363. Vulkan::getFrontFace(winding));
  364. }
  365. void Graphics::setColorMask(ColorChannelMask mask)
  366. {
  367. flushBatchedDraws();
  368. states.back().colorMask = mask;
  369. }
  370. void Graphics::setBlendState(const BlendState &blend)
  371. {
  372. flushBatchedDraws();
  373. states.back().blend = blend;
  374. }
  375. void Graphics::setPointSize(float size)
  376. {
  377. if (size != states.back().pointSize)
  378. flushBatchedDraws();
  379. states.back().pointSize = size;
  380. }
  381. bool Graphics::usesGLSLES() const
  382. {
  383. return false;
  384. }
  385. Graphics::RendererInfo Graphics::getRendererInfo() const
  386. {
  387. VkPhysicalDeviceProperties deviceProperties;
  388. vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
  389. Graphics::RendererInfo info;
  390. info.device = deviceProperties.deviceName;
  391. info.vendor = Vulkan::getVendorName(deviceProperties.vendorID);
  392. info.version = Vulkan::getVulkanApiVersion(deviceProperties.apiVersion);
  393. std::stringstream ss;
  394. ss << "Vulkan( ";
  395. if (optionalDeviceFeatures.extendedDynamicState)
  396. ss << VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME << " ";
  397. ss << ")";
  398. info.name = ss.str();
  399. return info;
  400. }
  401. void Graphics::draw(const DrawCommand &cmd)
  402. {
  403. prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode);
  404. vkCmdDraw(commandBuffers.at(currentFrame), static_cast<uint32_t>(cmd.vertexCount), static_cast<uint32_t>(cmd.instanceCount), static_cast<uint32_t>(cmd.vertexStart), 0);
  405. drawCalls++;
  406. }
  407. void Graphics::draw(const DrawIndexedCommand &cmd)
  408. {
  409. prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode);
  410. vkCmdBindIndexBuffer(commandBuffers.at(currentFrame), (VkBuffer)cmd.indexBuffer->getHandle(), static_cast<VkDeviceSize>(cmd.indexBufferOffset), Vulkan::getVulkanIndexBufferType(cmd.indexType));
  411. vkCmdDrawIndexed(commandBuffers.at(currentFrame), static_cast<uint32_t>(cmd.indexCount), static_cast<uint32_t>(cmd.instanceCount), 0, 0, 0);
  412. drawCalls++;
  413. }
  414. void Graphics::drawQuads(int start, int count, const VertexAttributes &attributes, const BufferBindings &buffers, graphics::Texture *texture)
  415. {
  416. const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX;
  417. const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4;
  418. prepareDraw(attributes, buffers, texture, PRIMITIVE_TRIANGLES, CULL_BACK);
  419. vkCmdBindIndexBuffer(commandBuffers.at(currentFrame), (VkBuffer)quadIndexBuffer->getHandle(), 0, Vulkan::getVulkanIndexBufferType(INDEX_UINT16));
  420. int baseVertex = start * 4;
  421. for (int quadindex = 0; quadindex < count; quadindex += MAX_QUADS_PER_DRAW)
  422. {
  423. int quadcount = std::min(MAX_QUADS_PER_DRAW, count - quadindex);
  424. vkCmdDrawIndexed(commandBuffers.at(currentFrame), static_cast<uint32_t>(quadcount * 6), 1, 0, baseVertex, 0);
  425. baseVertex += quadcount * 4;
  426. drawCalls++;
  427. }
  428. }
  429. void Graphics::setColor(Colorf c)
  430. {
  431. c.r = std::min(std::max(c.r, 0.0f), 1.0f);
  432. c.g = std::min(std::max(c.g, 0.0f), 1.0f);
  433. c.b = std::min(std::max(c.b, 0.0f), 1.0f);
  434. c.a = std::min(std::max(c.a, 0.0f), 1.0f);
  435. states.back().color = c;
  436. }
  437. static VkRect2D computeScissor(const Rect &r, double bufferWidth, double bufferHeight, double dpiScale, VkSurfaceTransformFlagBitsKHR preTransform)
  438. {
  439. double x = static_cast<double>(r.x) * dpiScale;
  440. double y = static_cast<double>(r.y) * dpiScale;
  441. double w = static_cast<double>(r.w) * dpiScale;
  442. double h = static_cast<double>(r.h) * dpiScale;
  443. double scissorX, scissorY, scissorW, scissorH;
  444. switch (preTransform)
  445. {
  446. case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
  447. scissorX = bufferWidth - h - y;
  448. scissorY = x;
  449. scissorW = h;
  450. scissorH = w;
  451. break;
  452. case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
  453. scissorX = bufferWidth - w - x;
  454. scissorY = bufferHeight - h - y;
  455. scissorW = w;
  456. scissorH = h;
  457. break;
  458. case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
  459. scissorX = y;
  460. scissorY = bufferHeight - w - x;
  461. scissorW = h;
  462. scissorH = w;
  463. break;
  464. default:
  465. scissorX = x;
  466. scissorY = y;
  467. scissorW = w;
  468. scissorH = h;
  469. break;
  470. }
  471. VkRect2D scissor = {
  472. {static_cast<int32_t>(scissorX), static_cast<int32_t>(scissorY)},
  473. {static_cast<uint32_t>(scissorW), static_cast<uint32_t>(scissorH)}
  474. };
  475. return scissor;
  476. }
  477. void Graphics::setScissor(const Rect &rect)
  478. {
  479. flushBatchedDraws();
  480. VkRect2D scissor = computeScissor(rect,
  481. static_cast<double>(swapChainExtent.width),
  482. static_cast<double>(swapChainExtent.height),
  483. getCurrentDPIScale(),
  484. preTransform);
  485. vkCmdSetScissor(commandBuffers.at(currentFrame), 0, 1, &scissor);
  486. states.back().scissor = true;
  487. states.back().scissorRect = rect;
  488. }
  489. void Graphics::setScissor()
  490. {
  491. flushBatchedDraws();
  492. states.back().scissor = false;
  493. VkRect2D scissor{};
  494. scissor.offset = { 0, 0 };
  495. scissor.extent = swapChainExtent;
  496. vkCmdSetScissor(commandBuffers.at(currentFrame), 0, 1, &scissor);
  497. }
  498. void Graphics::setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask)
  499. {
  500. flushBatchedDraws();
  501. vkCmdSetStencilWriteMask(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, writemask);
  502. vkCmdSetStencilCompareMask(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, readmask);
  503. vkCmdSetStencilReference(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, value);
  504. if (optionalDeviceFeatures.extendedDynamicState)
  505. ext.vkCmdSetStencilOpEXT(
  506. commandBuffers.at(currentFrame),
  507. VK_STENCIL_FACE_FRONT_AND_BACK,
  508. VK_STENCIL_OP_KEEP, Vulkan::getStencilOp(action),
  509. VK_STENCIL_OP_KEEP, Vulkan::getCompareOp(compare));
  510. states.back().stencil.action = action;
  511. states.back().stencil.compare = compare;
  512. states.back().stencil.value = value;
  513. states.back().stencil.readMask = readmask;
  514. states.back().stencil.writeMask = writemask;
  515. }
  516. void Graphics::setDepthMode(CompareMode compare, bool write)
  517. {
  518. flushBatchedDraws();
  519. if (optionalDeviceFeatures.extendedDynamicState)
  520. {
  521. ext.vkCmdSetDepthCompareOpEXT(
  522. commandBuffers.at(currentFrame), Vulkan::getCompareOp(compare));
  523. ext.vkCmdSetDepthWriteEnableEXT(
  524. commandBuffers.at(currentFrame), Vulkan::getBool(write));
  525. }
  526. states.back().depthTest = compare;
  527. states.back().depthWrite = write;
  528. }
  529. void Graphics::setWireframe(bool enable)
  530. {
  531. flushBatchedDraws();
  532. states.back().wireframe = enable;
  533. }
  534. PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const
  535. {
  536. switch (format)
  537. {
  538. case PIXELFORMAT_NORMAL:
  539. if (isGammaCorrect())
  540. return PIXELFORMAT_RGBA8_UNORM_sRGB;
  541. else
  542. return PIXELFORMAT_RGBA8_UNORM;
  543. case PIXELFORMAT_HDR:
  544. return PIXELFORMAT_RGBA16_FLOAT;
  545. default:
  546. return format;
  547. }
  548. }
  549. bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
  550. {
  551. return true;
  552. }
  553. Renderer Graphics::getRenderer() const
  554. {
  555. return RENDERER_VULKAN;
  556. }
  557. graphics::GraphicsReadback *Graphics::newReadbackInternal(ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset)
  558. {
  559. return new GraphicsReadback(this, method, buffer, offset, size, dest, destoffset);
  560. }
  561. graphics::GraphicsReadback *Graphics::newReadbackInternal(ReadbackMethod method, love::graphics::Texture *texture, int slice, int mipmap, const Rect &rect, image::ImageData *dest, int destx, int desty)
  562. {
  563. return new GraphicsReadback(this, method, texture, slice, mipmap, rect, dest, destx, desty);
  564. }
  565. graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles)
  566. {
  567. return new ShaderStage(this, stage, source, gles, cachekey);
  568. }
  569. graphics::Shader *Graphics::newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
  570. {
  571. return new Shader(stages);
  572. }
  573. graphics::StreamBuffer *Graphics::newStreamBuffer(BufferUsage type, size_t size)
  574. {
  575. return new StreamBuffer(this, type, size);
  576. }
  577. bool Graphics::dispatch(int x, int y, int z)
  578. {
  579. if (renderPassState.active)
  580. endRenderPass();
  581. vkCmdBindPipeline(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_COMPUTE, computeShader->getComputePipeline());
  582. computeShader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_COMPUTE);
  583. vkCmdDispatch(commandBuffers.at(currentFrame), static_cast<uint32_t>(x), static_cast<uint32_t>(y), static_cast<uint32_t>(z));
  584. return true;
  585. }
  586. Matrix4 Graphics::computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const
  587. {
  588. uint32 flags = DEVICE_PROJECTION_DEFAULT;
  589. return calculateDeviceProjection(projection, flags);
  590. }
  591. void Graphics::setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture)
  592. {
  593. if (renderPassState.active)
  594. endRenderPass();
  595. bool isWindow = rts.getFirstTarget().texture == nullptr;
  596. if (isWindow)
  597. setDefaultRenderPass();
  598. else
  599. setRenderPass(rts, pixelw, pixelh, hasSRGBtexture);
  600. }
  601. // END IMPLEMENTATION OVERRIDDEN FUNCTIONS
  602. void Graphics::initDynamicState()
  603. {
  604. if (states.back().scissor)
  605. setScissor(states.back().scissorRect);
  606. else
  607. setScissor();
  608. VkViewport viewport{};
  609. viewport.x = 0.0f;
  610. viewport.y = 0.0f;
  611. viewport.width = static_cast<float>(swapChainExtent.width);
  612. viewport.height = static_cast<float>(swapChainExtent.height);
  613. viewport.minDepth = 0.0f;
  614. viewport.maxDepth = 1.0f;
  615. vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
  616. vkCmdSetStencilWriteMask(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, states.back().stencil.writeMask);
  617. vkCmdSetStencilCompareMask(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, states.back().stencil.readMask);
  618. vkCmdSetStencilReference(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, states.back().stencil.value);
  619. if (optionalDeviceFeatures.extendedDynamicState)
  620. {
  621. ext.vkCmdSetStencilOpEXT(
  622. commandBuffers.at(currentFrame),
  623. VK_STENCIL_FACE_FRONT_AND_BACK,
  624. VK_STENCIL_OP_KEEP, Vulkan::getStencilOp(states.back().stencil.action),
  625. VK_STENCIL_OP_KEEP, Vulkan::getCompareOp(states.back().stencil.compare));
  626. ext.vkCmdSetDepthCompareOpEXT(
  627. commandBuffers.at(currentFrame), Vulkan::getCompareOp(states.back().depthTest));
  628. ext.vkCmdSetDepthWriteEnableEXT(
  629. commandBuffers.at(currentFrame), Vulkan::getBool(states.back().depthWrite));
  630. ext.vkCmdSetFrontFaceEXT(
  631. commandBuffers.at(currentFrame), Vulkan::getFrontFace(states.back().winding));
  632. }
  633. }
  634. void Graphics::beginFrame()
  635. {
  636. vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
  637. while (true)
  638. {
  639. VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
  640. if (result == VK_ERROR_OUT_OF_DATE_KHR)
  641. {
  642. recreateSwapChain();
  643. continue;
  644. }
  645. else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
  646. throw love::Exception("failed to acquire swap chain image");
  647. break;
  648. }
  649. imageRequested = true;
  650. for (auto &readbackCallback : readbackCallbacks.at(currentFrame))
  651. readbackCallback();
  652. readbackCallbacks.at(currentFrame).clear();
  653. for (auto &cleanUpFn : cleanUpFunctions.at(currentFrame))
  654. cleanUpFn();
  655. cleanUpFunctions.at(currentFrame).clear();
  656. startRecordingGraphicsCommands(true);
  657. Vulkan::cmdTransitionImageLayout(
  658. commandBuffers.at(currentFrame),
  659. swapChainImages[imageIndex],
  660. VK_IMAGE_LAYOUT_UNDEFINED,
  661. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
  662. Vulkan::resetShaderSwitches();
  663. usedShadersInFrame.clear();
  664. }
  665. void Graphics::startRecordingGraphicsCommands(bool newFrame)
  666. {
  667. VkCommandBufferBeginInfo beginInfo{};
  668. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  669. beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  670. beginInfo.pInheritanceInfo = nullptr;
  671. if (vkBeginCommandBuffer(commandBuffers.at(currentFrame), &beginInfo) != VK_SUCCESS)
  672. throw love::Exception("failed to begin recording command buffer");
  673. initDynamicState();
  674. setDefaultRenderPass();
  675. }
  676. void Graphics::endRecordingGraphicsCommands(bool present) {
  677. if (renderPassState.active)
  678. endRenderPass();
  679. if (present)
  680. Vulkan::cmdTransitionImageLayout(
  681. commandBuffers.at(currentFrame),
  682. swapChainImages[imageIndex],
  683. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  684. VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
  685. if (vkEndCommandBuffer(commandBuffers.at(currentFrame)) != VK_SUCCESS)
  686. throw love::Exception("failed to record command buffer");
  687. }
  688. void Graphics::updatedBatchedDrawBuffers()
  689. {
  690. batchedDrawState.vb[0] = batchedDrawBuffers[currentFrame].vertexBuffer1;
  691. batchedDrawState.vb[0]->nextFrame();
  692. batchedDrawState.vb[1] = batchedDrawBuffers[currentFrame].vertexBuffer2;
  693. batchedDrawState.vb[1]->nextFrame();
  694. batchedDrawState.indexBuffer = batchedDrawBuffers[currentFrame].indexBuffer;
  695. batchedDrawState.indexBuffer->nextFrame();
  696. }
  697. uint32_t Graphics::getNumImagesInFlight() const
  698. {
  699. return MAX_FRAMES_IN_FLIGHT;
  700. }
  701. uint32_t Graphics::getFrameIndex() const
  702. {
  703. return currentFrame;
  704. }
  705. const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const
  706. {
  707. return minUniformBufferOffsetAlignment;
  708. }
  709. graphics::Texture *Graphics::getDefaultTexture() const
  710. {
  711. return dynamic_cast<graphics::Texture*>(standardTexture.get());
  712. }
  713. VkCommandBuffer Graphics::getCommandBufferForDataTransfer()
  714. {
  715. if (renderPassState.active)
  716. endRenderPass();
  717. return commandBuffers.at(currentFrame);
  718. }
  719. void Graphics::queueCleanUp(std::function<void()> cleanUp)
  720. {
  721. cleanUpFunctions.at(currentFrame).push_back(cleanUp);
  722. }
  723. void Graphics::addReadbackCallback(std::function<void()> callback)
  724. {
  725. readbackCallbacks.at(currentFrame).push_back(callback);
  726. }
  727. graphics::Shader::BuiltinUniformData Graphics::getCurrentBuiltinUniformData()
  728. {
  729. love::graphics::Shader::BuiltinUniformData data;
  730. data.transformMatrix = getTransform();
  731. data.projectionMatrix = displayRotation * getDeviceProjection();
  732. // The normal matrix is the transpose of the inverse of the rotation portion
  733. // (top-left 3x3) of the transform matrix.
  734. {
  735. Matrix3 normalmatrix = Matrix3(data.transformMatrix).transposedInverse();
  736. const float *e = normalmatrix.getElements();
  737. for (int i = 0; i < 3; i++)
  738. {
  739. data.normalMatrix[i].x = e[i * 3 + 0];
  740. data.normalMatrix[i].y = e[i * 3 + 1];
  741. data.normalMatrix[i].z = e[i * 3 + 2];
  742. data.normalMatrix[i].w = 0.0f;
  743. }
  744. }
  745. // Store DPI scale in an unused component of another vector.
  746. data.normalMatrix[0].w = (float)getCurrentDPIScale();
  747. // Same with point size.
  748. data.normalMatrix[1].w = getPointSize();
  749. data.screenSizeParams.x = static_cast<float>(swapChainExtent.width);
  750. data.screenSizeParams.y = static_cast<float>(swapChainExtent.height);
  751. data.screenSizeParams.z = 1.0f;
  752. data.screenSizeParams.w = 0.0f;
  753. data.constantColor = getColor();
  754. gammaCorrectColor(data.constantColor);
  755. return data;
  756. }
  757. static void checkOptionalInstanceExtensions(OptionalInstanceExtensions &ext)
  758. {
  759. uint32_t count;
  760. vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
  761. std::vector<VkExtensionProperties> extensions(count);
  762. vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data());
  763. for (const auto& extension : extensions)
  764. if (strcmp(extension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
  765. ext.physicalDeviceProperties2 = true;
  766. }
  767. void Graphics::createVulkanInstance()
  768. {
  769. if (enableValidationLayers && !checkValidationSupport())
  770. throw love::Exception("validation layers requested, but not available");
  771. VkApplicationInfo appInfo{};
  772. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  773. appInfo.pApplicationName = "LOVE";
  774. appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); //todo, get this version from somewhere else?
  775. appInfo.pEngineName = "LOVE Engine";
  776. appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
  777. appInfo.apiVersion = vulkanApiVersion;
  778. VkInstanceCreateInfo createInfo{};
  779. createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  780. createInfo.pApplicationInfo = &appInfo;
  781. createInfo.pNext = nullptr;
  782. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  783. const void *handle = window->getHandle();
  784. unsigned int count;
  785. if (SDL_Vulkan_GetInstanceExtensions((SDL_Window*)handle, &count, nullptr) != SDL_TRUE)
  786. throw love::Exception("couldn't retrieve sdl vulkan extensions");
  787. std::vector<const char*> extensions = {};
  788. checkOptionalInstanceExtensions(optionalInstanceExtensions);
  789. if (optionalInstanceExtensions.physicalDeviceProperties2)
  790. extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
  791. size_t additional_extension_count = extensions.size();
  792. extensions.resize(additional_extension_count + count);
  793. if (SDL_Vulkan_GetInstanceExtensions((SDL_Window*)handle, &count, extensions.data() + additional_extension_count) != SDL_TRUE)
  794. throw love::Exception("couldn't retrieve sdl vulkan extensions");
  795. createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
  796. createInfo.ppEnabledExtensionNames = extensions.data();
  797. if (enableValidationLayers)
  798. {
  799. createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  800. createInfo.ppEnabledLayerNames = validationLayers.data();
  801. }
  802. else
  803. {
  804. createInfo.enabledLayerCount = 0;
  805. createInfo.ppEnabledLayerNames = nullptr;
  806. }
  807. if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS)
  808. throw love::Exception("couldn't create vulkan instance");
  809. #ifdef LOVE_ANDROID
  810. volkLoadInstance(instance);
  811. #endif
  812. }
  813. bool Graphics::checkValidationSupport()
  814. {
  815. uint32_t layerCount;
  816. vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
  817. std::vector<VkLayerProperties> availableLayers(layerCount);
  818. vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
  819. for (const char *layerName : validationLayers)
  820. {
  821. bool layerFound = false;
  822. for (const auto &layerProperties : availableLayers)
  823. if (strcmp(layerName, layerProperties.layerName) == 0)
  824. {
  825. layerFound = true;
  826. break;
  827. }
  828. if (!layerFound)
  829. return false;
  830. }
  831. return true;
  832. }
  833. void Graphics::pickPhysicalDevice()
  834. {
  835. uint32_t deviceCount = 0;
  836. vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
  837. if (deviceCount == 0)
  838. throw love::Exception("failed to find GPUs with Vulkan support");
  839. std::vector<VkPhysicalDevice> devices(deviceCount);
  840. vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
  841. std::multimap<int, VkPhysicalDevice> candidates;
  842. for (const auto &device : devices)
  843. {
  844. int score = rateDeviceSuitability(device);
  845. candidates.insert(std::make_pair(score, device));
  846. }
  847. if (candidates.rbegin()->first > 0)
  848. physicalDevice = candidates.rbegin()->second;
  849. else
  850. throw love::Exception("failed to find a suitable gpu");
  851. VkPhysicalDeviceProperties properties;
  852. vkGetPhysicalDeviceProperties(physicalDevice, &properties);
  853. minUniformBufferOffsetAlignment = properties.limits.minUniformBufferOffsetAlignment;
  854. getMaxUsableSampleCount();
  855. }
  856. bool Graphics::checkDeviceExtensionSupport(VkPhysicalDevice device)
  857. {
  858. uint32_t extensionCount;
  859. vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
  860. std::vector<VkExtensionProperties> availableExtensions(extensionCount);
  861. vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
  862. std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
  863. for (const auto &extension : availableExtensions)
  864. requiredExtensions.erase(extension.extensionName);
  865. return requiredExtensions.empty();
  866. }
  867. // if the score is nonzero then the device is suitable.
  868. // A higher rating means generally better performance
  869. // if the score is 0 the device is unsuitable
  870. int Graphics::rateDeviceSuitability(VkPhysicalDevice device)
  871. {
  872. VkPhysicalDeviceProperties deviceProperties;
  873. VkPhysicalDeviceFeatures deviceFeatures;
  874. vkGetPhysicalDeviceProperties(device, &deviceProperties);
  875. vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
  876. int score = 1;
  877. // optional
  878. if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
  879. score += 1000;
  880. if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
  881. score += 100;
  882. if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)
  883. score += 10;
  884. // definitely needed
  885. QueueFamilyIndices indices = findQueueFamilies(device);
  886. if (!indices.isComplete())
  887. score = 0;
  888. bool extensionsSupported = checkDeviceExtensionSupport(device);
  889. if (!extensionsSupported)
  890. score = 0;
  891. if (extensionsSupported)
  892. {
  893. auto swapChainSupport = querySwapChainSupport(device);
  894. bool swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
  895. if (!swapChainAdequate)
  896. score = 0;
  897. }
  898. if (!deviceFeatures.samplerAnisotropy)
  899. score = 0;
  900. if (!deviceFeatures.fillModeNonSolid)
  901. score = 0;
  902. return score;
  903. }
  904. QueueFamilyIndices Graphics::findQueueFamilies(VkPhysicalDevice device)
  905. {
  906. QueueFamilyIndices indices;
  907. uint32_t queueFamilyCount = 0;
  908. vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
  909. std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
  910. vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
  911. int i = 0;
  912. for (const auto &queueFamily : queueFamilies)
  913. {
  914. if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT && queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)
  915. indices.graphicsFamily = i;
  916. VkBool32 presentSupport = false;
  917. vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
  918. if (presentSupport)
  919. indices.presentFamily = i;
  920. if (indices.isComplete())
  921. break;
  922. i++;
  923. }
  924. return indices;
  925. }
  926. static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, OptionalDeviceFeatures &optionalDeviceFeatures)
  927. {
  928. uint32_t extensionCount;
  929. vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr);
  930. std::vector<VkExtensionProperties> availableExtensions(extensionCount);
  931. vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.data());
  932. for (const auto& extension : availableExtensions)
  933. {
  934. if (strcmp(extension.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) == 0)
  935. optionalDeviceFeatures.extendedDynamicState = true;
  936. }
  937. }
  938. void Graphics::createLogicalDevice()
  939. {
  940. QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  941. std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
  942. std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value()};
  943. float queuePriority = 1.0f;
  944. for (uint32_t queueFamily : uniqueQueueFamilies)
  945. {
  946. VkDeviceQueueCreateInfo queueCreateInfo{};
  947. queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  948. queueCreateInfo.queueFamilyIndex = queueFamily;
  949. queueCreateInfo.queueCount = 1;
  950. queueCreateInfo.pQueuePriorities = &queuePriority;
  951. queueCreateInfos.push_back(queueCreateInfo);
  952. }
  953. findOptionalDeviceExtensions(physicalDevice, optionalDeviceFeatures);
  954. if (optionalDeviceFeatures.extendedDynamicState && !optionalInstanceExtensions.physicalDeviceProperties2)
  955. optionalDeviceFeatures.extendedDynamicState = false;
  956. VkPhysicalDeviceFeatures deviceFeatures{};
  957. deviceFeatures.samplerAnisotropy = VK_TRUE;
  958. deviceFeatures.fillModeNonSolid = VK_TRUE;
  959. VkDeviceCreateInfo createInfo{};
  960. createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  961. createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
  962. createInfo.pQueueCreateInfos = queueCreateInfos.data();
  963. createInfo.pEnabledFeatures = &deviceFeatures;
  964. std::vector<const char*> enabledExtensions(deviceExtensions.begin(), deviceExtensions.end());
  965. if (optionalDeviceFeatures.extendedDynamicState)
  966. enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
  967. createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
  968. createInfo.ppEnabledExtensionNames = enabledExtensions.data();
  969. if (enableValidationLayers)
  970. {
  971. createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  972. createInfo.ppEnabledLayerNames = validationLayers.data();
  973. }
  974. else
  975. createInfo.enabledLayerCount = 0;
  976. VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures{};
  977. extendedDynamicStateFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
  978. extendedDynamicStateFeatures.extendedDynamicState = Vulkan::getBool(optionalDeviceFeatures.extendedDynamicState);
  979. extendedDynamicStateFeatures.pNext = nullptr;
  980. createInfo.pNext = &extendedDynamicStateFeatures;
  981. if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS)
  982. throw love::Exception("failed to create logical device");
  983. #ifdef LOVE_ANDROID
  984. volkLoadDevice(device);
  985. #endif
  986. vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
  987. vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
  988. if (optionalDeviceFeatures.extendedDynamicState)
  989. {
  990. #ifdef LOVE_ANDROID
  991. ext.vkCmdSetCullModeEXT = vkCmdSetCullModeEXT;
  992. ext.vkCmdSetDepthBoundsTestEnableEXT = vkCmdSetDepthBoundsTestEnableEXT;
  993. ext.vkCmdSetDepthBoundsTestEnableEXT = vkCmdSetCullModeEXT;
  994. ext.vkCmdSetDepthTestEnableEXT = vkCmdSetDepthTestEnableEXT;
  995. ext.vkCmdSetDepthWriteEnableEXT = vkCmdSetDepthWriteEnableEXT;
  996. ext.vkCmdSetFrontFaceEXT = vkCmdSetFrontFaceEXT;
  997. ext.vkCmdSetPrimitiveTopologyEXT = vkCmdSetPrimitiveTopologyEXT;
  998. ext.vkCmdSetScissorWithCountEXT = vkCmdSetScissorWithCountEXT;
  999. ext.vkCmdSetStencilOpEXT = vkCmdSetStencilOpEXT;
  1000. ext.vkCmdSetStencilTestEnableEXT = vkCmdSetStencilTestEnableEXT;
  1001. ext.vkCmdSetViewportWithCountEXT = vkCmdSetViewportWithCountEXT;
  1002. #else
  1003. ext.vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)vkGetDeviceProcAddr(device, "vkCmdSetCullModeEXT");
  1004. ext.vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthBoundsTestEnableEXT");
  1005. ext.vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthCompareOpEXT");
  1006. ext.vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthTestEnableEXT");
  1007. ext.vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthWriteEnableEXT");
  1008. ext.vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)vkGetDeviceProcAddr(device, "vkCmdSetFrontFaceEXT");
  1009. ext.vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)vkGetDeviceProcAddr(device, "vkCmdSetPrimitiveTopologyEXT");
  1010. ext.vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetScissorWithCountEXT");
  1011. ext.vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilOpEXT");
  1012. ext.vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilTestEnableEXT");
  1013. ext.vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetViewportWithCountEXT");
  1014. #endif
  1015. }
  1016. }
  1017. void Graphics::initVMA()
  1018. {
  1019. VmaAllocatorCreateInfo allocatorCreateInfo = {};
  1020. allocatorCreateInfo.vulkanApiVersion = vulkanApiVersion;
  1021. allocatorCreateInfo.physicalDevice = physicalDevice;
  1022. allocatorCreateInfo.device = device;
  1023. allocatorCreateInfo.instance = instance;
  1024. #ifdef LOVE_ANDROID
  1025. VmaVulkanFunctions vulkanFunctions{};
  1026. vulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
  1027. vulkanFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
  1028. vulkanFunctions.vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties;
  1029. vulkanFunctions.vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties;
  1030. vulkanFunctions.vkAllocateMemory = vkAllocateMemory;
  1031. vulkanFunctions.vkFreeMemory = vkFreeMemory;
  1032. vulkanFunctions.vkMapMemory = vkMapMemory;
  1033. vulkanFunctions.vkUnmapMemory = vkUnmapMemory;
  1034. vulkanFunctions.vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges;
  1035. vulkanFunctions.vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges;
  1036. vulkanFunctions.vkBindBufferMemory = vkBindBufferMemory;
  1037. vulkanFunctions.vkBindImageMemory = vkBindImageMemory;
  1038. vulkanFunctions.vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements;
  1039. vulkanFunctions.vkGetImageMemoryRequirements = vkGetImageMemoryRequirements;
  1040. vulkanFunctions.vkCreateBuffer = vkCreateBuffer;
  1041. vulkanFunctions.vkCreateImage = vkCreateImage;
  1042. vulkanFunctions.vkDestroyBuffer = vkDestroyBuffer;
  1043. vulkanFunctions.vkDestroyImage = vkDestroyImage;
  1044. vulkanFunctions.vkCmdCopyBuffer = vkCmdCopyBuffer;
  1045. vulkanFunctions.vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2KHR;
  1046. vulkanFunctions.vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2KHR;
  1047. vulkanFunctions.vkBindBufferMemory2KHR = vkBindBufferMemory2KHR;
  1048. vulkanFunctions.vkBindImageMemory2KHR = vkBindImageMemory2KHR;
  1049. vulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = vkGetPhysicalDeviceMemoryProperties2KHR;
  1050. vulkanFunctions.vkGetDeviceBufferMemoryRequirements = vkGetDeviceBufferMemoryRequirements;
  1051. vulkanFunctions.vkGetDeviceImageMemoryRequirements = vkGetDeviceImageMemoryRequirements;
  1052. allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
  1053. #else
  1054. VmaVulkanFunctions vulkanFunctions{};
  1055. vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
  1056. vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
  1057. allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
  1058. #endif
  1059. if (vmaCreateAllocator(&allocatorCreateInfo, &vmaAllocator) != VK_SUCCESS)
  1060. throw love::Exception("failed to create vma allocator");
  1061. }
  1062. void Graphics::createSurface()
  1063. {
  1064. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  1065. const void *handle = window->getHandle();
  1066. if (SDL_Vulkan_CreateSurface((SDL_Window*)handle, instance, &surface) != SDL_TRUE)
  1067. throw love::Exception("failed to create window surface");
  1068. }
  1069. SwapChainSupportDetails Graphics::querySwapChainSupport(VkPhysicalDevice device)
  1070. {
  1071. SwapChainSupportDetails details;
  1072. vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
  1073. uint32_t formatCount;
  1074. vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
  1075. if (formatCount != 0)
  1076. {
  1077. details.formats.resize(formatCount);
  1078. vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
  1079. }
  1080. uint32_t presentModeCount;
  1081. vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
  1082. if (presentModeCount != 0)
  1083. {
  1084. details.presentModes.resize(presentModeCount);
  1085. vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
  1086. }
  1087. return details;
  1088. }
  1089. void Graphics::createSwapChain()
  1090. {
  1091. SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);
  1092. VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
  1093. VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
  1094. VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
  1095. if (swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||
  1096. swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR)
  1097. {
  1098. uint32_t width, height;
  1099. width = extent.width;
  1100. height = extent.height;
  1101. extent.width = height;
  1102. extent.height = width;
  1103. }
  1104. auto currentTransform = swapChainSupport.capabilities.currentTransform;
  1105. constexpr float PI = 3.14159265358979323846f;
  1106. float angle = 0.0f;
  1107. if (currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
  1108. angle = 0.0f;
  1109. else if (currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR)
  1110. angle = -PI / 2.0f;
  1111. else if (currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR)
  1112. angle = -PI;
  1113. else if (currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR)
  1114. angle = -3.0f * PI / 2.0f;
  1115. float data[] = {
  1116. cosf(angle), -sinf(angle), 0.0f, 0.0f,
  1117. sinf(angle), cosf(angle), 0.0f, 0.0f,
  1118. 0.0f, 0.0f, 1.0f, 0.0f,
  1119. 0.0f, 0.0f, 0.0f, 1.0f,
  1120. };
  1121. displayRotation = Matrix4(data);
  1122. uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
  1123. if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount)
  1124. imageCount = swapChainSupport.capabilities.maxImageCount;
  1125. VkSwapchainCreateInfoKHR createInfo{};
  1126. createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  1127. createInfo.surface = surface;
  1128. createInfo.minImageCount = imageCount;
  1129. createInfo.imageFormat = surfaceFormat.format;
  1130. createInfo.imageColorSpace = surfaceFormat.colorSpace;
  1131. createInfo.imageExtent = extent;
  1132. createInfo.imageArrayLayers = 1;
  1133. createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  1134. QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  1135. uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };
  1136. if (indices.graphicsFamily != indices.presentFamily)
  1137. {
  1138. createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  1139. createInfo.queueFamilyIndexCount = 2;
  1140. createInfo.pQueueFamilyIndices = queueFamilyIndices;
  1141. }
  1142. else
  1143. {
  1144. createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  1145. createInfo.queueFamilyIndexCount = 0;
  1146. createInfo.pQueueFamilyIndices = nullptr;
  1147. }
  1148. createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
  1149. createInfo.compositeAlpha = chooseCompositeAlpha(swapChainSupport.capabilities);
  1150. createInfo.presentMode = presentMode;
  1151. createInfo.clipped = VK_TRUE;
  1152. createInfo.oldSwapchain = VK_NULL_HANDLE;
  1153. if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS)
  1154. throw love::Exception("failed to create swap chain");
  1155. vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
  1156. swapChainImages.resize(imageCount);
  1157. vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());
  1158. swapChainImageFormat = surfaceFormat.format;
  1159. swapChainExtent = extent;
  1160. preTransform = swapChainSupport.capabilities.currentTransform;
  1161. }
  1162. VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats)
  1163. {
  1164. for (const auto& availableFormat : availableFormats)
  1165. // fixme: what if this format and colorspace is not available?
  1166. if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
  1167. return availableFormat;
  1168. return availableFormats[0];
  1169. }
  1170. VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes)
  1171. {
  1172. int vsync = Vulkan::getVsync();
  1173. const auto begin = availablePresentModes.begin();
  1174. const auto end = availablePresentModes.end();
  1175. switch (vsync) {
  1176. case -1:
  1177. if (std::find(begin, end, VK_PRESENT_MODE_FIFO_RELAXED_KHR) != availablePresentModes.end())
  1178. return VK_PRESENT_MODE_FIFO_RELAXED_KHR;
  1179. else
  1180. return VK_PRESENT_MODE_FIFO_KHR;
  1181. case 0:
  1182. if (std::find(begin, end, VK_PRESENT_MODE_MAILBOX_KHR) != availablePresentModes.end())
  1183. return VK_PRESENT_MODE_MAILBOX_KHR;
  1184. else
  1185. {
  1186. if (std::find(begin, end, VK_PRESENT_MODE_IMMEDIATE_KHR) != availablePresentModes.end())
  1187. return VK_PRESENT_MODE_IMMEDIATE_KHR;
  1188. else
  1189. return VK_PRESENT_MODE_FIFO_KHR;
  1190. }
  1191. default:
  1192. return VK_PRESENT_MODE_FIFO_KHR;
  1193. }
  1194. }
  1195. VkExtent2D Graphics::chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities)
  1196. {
  1197. if (capabilities.currentExtent.width != UINT32_MAX)
  1198. return capabilities.currentExtent;
  1199. else
  1200. {
  1201. auto window = Module::getInstance<love::window::Window>(M_WINDOW);
  1202. const void *handle = window->getHandle();
  1203. int width, height;
  1204. SDL_Vulkan_GetDrawableSize((SDL_Window*)handle, &width, &height);
  1205. VkExtent2D actualExtent = {
  1206. static_cast<uint32_t>(width),
  1207. static_cast<uint32_t>(height)
  1208. };
  1209. actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
  1210. actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
  1211. return actualExtent;
  1212. }
  1213. }
  1214. VkCompositeAlphaFlagBitsKHR Graphics::chooseCompositeAlpha(const VkSurfaceCapabilitiesKHR& capabilities)
  1215. {
  1216. if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
  1217. return VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  1218. else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
  1219. return VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
  1220. else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
  1221. return VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
  1222. else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
  1223. return VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
  1224. else
  1225. throw love::Exception("failed to find composite alpha");
  1226. }
  1227. void Graphics::createImageViews()
  1228. {
  1229. swapChainImageViews.resize(swapChainImages.size());
  1230. for (size_t i = 0; i < swapChainImages.size(); i++)
  1231. {
  1232. VkImageViewCreateInfo createInfo{};
  1233. createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  1234. createInfo.image = swapChainImages.at(i);
  1235. createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  1236. createInfo.format = swapChainImageFormat;
  1237. createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  1238. createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  1239. createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  1240. createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  1241. createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1242. createInfo.subresourceRange.baseMipLevel = 0;
  1243. createInfo.subresourceRange.levelCount = 1;
  1244. createInfo.subresourceRange.baseArrayLayer = 0;
  1245. createInfo.subresourceRange.layerCount = 1;
  1246. if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews.at(i)) != VK_SUCCESS)
  1247. throw love::Exception("failed to create image views");
  1248. }
  1249. }
  1250. void Graphics::createDefaultRenderPass()
  1251. {
  1252. RenderPassConfiguration renderPassConfiguration{};
  1253. renderPassConfiguration.colorFormats.push_back(swapChainImageFormat);
  1254. renderPassConfiguration.staticData.msaaSamples = msaaSamples;
  1255. renderPassConfiguration.staticData.depthFormat = findDepthFormat();
  1256. if (msaaSamples & VK_SAMPLE_COUNT_1_BIT)
  1257. renderPassConfiguration.staticData.resolve = false;
  1258. else
  1259. renderPassConfiguration.staticData.resolve = true;
  1260. defaultRenderPass = createRenderPass(renderPassConfiguration);
  1261. }
  1262. void Graphics::createDefaultFramebuffers()
  1263. {
  1264. defaultFramebuffers.clear();
  1265. for (const auto view : swapChainImageViews)
  1266. {
  1267. FramebufferConfiguration configuration{};
  1268. configuration.staticData.renderPass = defaultRenderPass;
  1269. configuration.staticData.width = swapChainExtent.width;
  1270. configuration.staticData.height = swapChainExtent.height;
  1271. configuration.staticData.depthView = depthImageView;
  1272. if (msaaSamples & VK_SAMPLE_COUNT_1_BIT)
  1273. configuration.colorViews.push_back(view);
  1274. else
  1275. {
  1276. configuration.colorViews.push_back(colorImageView);
  1277. configuration.staticData.resolveView = view;
  1278. }
  1279. defaultFramebuffers.push_back(createFramebuffer(configuration));
  1280. }
  1281. }
  1282. VkFramebuffer Graphics::createFramebuffer(FramebufferConfiguration &configuration)
  1283. {
  1284. std::vector<VkImageView> attachments;
  1285. for (const auto& colorView : configuration.colorViews)
  1286. attachments.push_back(colorView);
  1287. if (configuration.staticData.depthView)
  1288. attachments.push_back(configuration.staticData.depthView);
  1289. if (configuration.staticData.resolveView)
  1290. attachments.push_back(configuration.staticData.resolveView);
  1291. VkFramebufferCreateInfo createInfo{};
  1292. createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  1293. createInfo.renderPass = configuration.staticData.renderPass;
  1294. createInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
  1295. createInfo.pAttachments = attachments.data();
  1296. createInfo.width = configuration.staticData.width;
  1297. createInfo.height = configuration.staticData.height;
  1298. createInfo.layers = 1;
  1299. VkFramebuffer frameBuffer;
  1300. if (vkCreateFramebuffer(device, &createInfo, nullptr, &frameBuffer) != VK_SUCCESS)
  1301. throw love::Exception("failed to create framebuffer");
  1302. return frameBuffer;
  1303. }
  1304. VkFramebuffer Graphics::getFramebuffer(FramebufferConfiguration &configuration)
  1305. {
  1306. auto it = framebuffers.find(configuration);
  1307. if (it != framebuffers.end())
  1308. return it->second;
  1309. else
  1310. {
  1311. VkFramebuffer framebuffer = createFramebuffer(configuration);
  1312. framebuffers[configuration] = framebuffer;
  1313. return framebuffer;
  1314. }
  1315. }
  1316. void Graphics::createDefaultShaders()
  1317. {
  1318. for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++)
  1319. {
  1320. auto stype = (Shader::StandardShader)i;
  1321. if (!Shader::standardShaders[i])
  1322. {
  1323. std::vector<std::string> stages;
  1324. stages.push_back(Shader::getDefaultCode(stype, SHADERSTAGE_VERTEX));
  1325. stages.push_back(Shader::getDefaultCode(stype, SHADERSTAGE_PIXEL));
  1326. Shader::standardShaders[i] = newShader(stages, {});
  1327. }
  1328. }
  1329. }
  1330. VkRenderPass Graphics::createRenderPass(RenderPassConfiguration &configuration)
  1331. {
  1332. VkSubpassDescription subPass{};
  1333. subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  1334. std::vector<VkAttachmentDescription> attachments;
  1335. std::vector<VkAttachmentReference> colorAttachmentRefs;
  1336. uint32_t attachment = 0;
  1337. for (const auto &colorFormat : configuration.colorFormats)
  1338. {
  1339. VkAttachmentReference reference{};
  1340. reference.attachment = attachment++;
  1341. reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1342. colorAttachmentRefs.push_back(reference);
  1343. VkAttachmentDescription colorDescription{};
  1344. colorDescription.format = colorFormat;
  1345. colorDescription.samples = configuration.staticData.msaaSamples;
  1346. colorDescription.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  1347. colorDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  1348. colorDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  1349. colorDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  1350. colorDescription.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1351. colorDescription.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1352. attachments.push_back(colorDescription);
  1353. }
  1354. subPass.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
  1355. subPass.pColorAttachments = colorAttachmentRefs.data();
  1356. VkAttachmentReference depthStencilAttachmentRef{};
  1357. if (configuration.staticData.depthFormat != VK_FORMAT_UNDEFINED)
  1358. {
  1359. depthStencilAttachmentRef.attachment = attachment++;
  1360. depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  1361. subPass.pDepthStencilAttachment = &depthStencilAttachmentRef;
  1362. VkAttachmentDescription depthStencilAttachment{};
  1363. depthStencilAttachment.format = configuration.staticData.depthFormat;
  1364. depthStencilAttachment.samples = configuration.staticData.msaaSamples;
  1365. depthStencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  1366. depthStencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  1367. depthStencilAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  1368. depthStencilAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  1369. depthStencilAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  1370. depthStencilAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  1371. attachments.push_back(depthStencilAttachment);
  1372. }
  1373. VkAttachmentReference colorAttachmentResolveRef{};
  1374. if (configuration.staticData.resolve)
  1375. {
  1376. colorAttachmentResolveRef.attachment = attachment++;
  1377. colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1378. subPass.pResolveAttachments = &colorAttachmentResolveRef;
  1379. VkAttachmentDescription colorAttachmentResolve{};
  1380. colorAttachmentResolve.format = configuration.colorFormats.at(0);
  1381. colorAttachmentResolve.samples = VK_SAMPLE_COUNT_1_BIT;
  1382. colorAttachmentResolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  1383. colorAttachmentResolve.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  1384. colorAttachmentResolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  1385. colorAttachmentResolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  1386. colorAttachmentResolve.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1387. colorAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1388. attachments.push_back(colorAttachmentResolve);
  1389. }
  1390. VkSubpassDependency dependency{};
  1391. dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
  1392. dependency.dstSubpass = 0;
  1393. dependency.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
  1394. dependency.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  1395. dependency.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
  1396. dependency.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  1397. VkSubpassDependency readbackDependency{};
  1398. readbackDependency.srcSubpass = 0;
  1399. readbackDependency.dstSubpass = VK_SUBPASS_EXTERNAL;
  1400. readbackDependency.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
  1401. readbackDependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  1402. readbackDependency.dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
  1403. readbackDependency.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  1404. std::array<VkSubpassDependency, 2> dependencies = { dependency, readbackDependency };
  1405. VkRenderPassCreateInfo createInfo{};
  1406. createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  1407. createInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
  1408. createInfo.pAttachments = attachments.data();
  1409. createInfo.subpassCount = 1;
  1410. createInfo.pSubpasses = &subPass;
  1411. createInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
  1412. createInfo.pDependencies = dependencies.data();
  1413. VkRenderPass renderPass;
  1414. if (vkCreateRenderPass(device, &createInfo, nullptr, &renderPass) != VK_SUCCESS)
  1415. throw love::Exception("failed to create render pass");
  1416. return renderPass;
  1417. }
  1418. bool Graphics::usesConstantVertexColor(const VertexAttributes &vertexAttributes)
  1419. {
  1420. return !!(vertexAttributes.enableBits & (1u << ATTRIB_COLOR));
  1421. }
  1422. void Graphics::createVulkanVertexFormat(
  1423. VertexAttributes vertexAttributes,
  1424. std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
  1425. std::vector<VkVertexInputAttributeDescription> &attributeDescriptions)
  1426. {
  1427. std::set<uint32_t> usedBuffers;
  1428. auto allBits = vertexAttributes.enableBits;
  1429. bool usesColor = false;
  1430. uint8_t highestBufferBinding = 0;
  1431. // change to loop like in opengl implementation ?
  1432. for (uint32_t i = 0; i < VertexAttributes::MAX; i++)
  1433. {
  1434. uint32 bit = 1u << i;
  1435. if (allBits & bit)
  1436. {
  1437. if (i == ATTRIB_COLOR)
  1438. usesColor = true;
  1439. auto attrib = vertexAttributes.attribs[i];
  1440. auto bufferBinding = attrib.bufferIndex;
  1441. if (usedBuffers.find(bufferBinding) == usedBuffers.end()) // use .contains() when c++20 is enabled
  1442. {
  1443. usedBuffers.insert(bufferBinding);
  1444. VkVertexInputBindingDescription bindingDescription{};
  1445. bindingDescription.binding = bufferBinding;
  1446. if (vertexAttributes.instanceBits & (1u << bufferBinding))
  1447. bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
  1448. else
  1449. bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
  1450. bindingDescription.stride = vertexAttributes.bufferLayouts[bufferBinding].stride;
  1451. bindingDescriptions.push_back(bindingDescription);
  1452. highestBufferBinding = std::max(highestBufferBinding, bufferBinding);
  1453. }
  1454. VkVertexInputAttributeDescription attributeDescription{};
  1455. attributeDescription.location = i;
  1456. attributeDescription.binding = bufferBinding;
  1457. attributeDescription.offset = attrib.offsetFromVertex;
  1458. attributeDescription.format = Vulkan::getVulkanVertexFormat(attrib.format);
  1459. attributeDescriptions.push_back(attributeDescription);
  1460. }
  1461. }
  1462. // do we need to use a constant VertexColor?
  1463. if (!usesColor)
  1464. {
  1465. // FIXME: is there a case where gaps happen between buffer bindings?
  1466. // then this doesn't work. We might need to enable null buffers again.
  1467. const auto constantColorBufferBinding = highestBufferBinding + 1;
  1468. VkVertexInputBindingDescription bindingDescription{};
  1469. bindingDescription.binding = constantColorBufferBinding;
  1470. bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
  1471. bindingDescription.stride = 0; // no stride, will always read the same color multiple times.
  1472. bindingDescriptions.push_back(bindingDescription);
  1473. VkVertexInputAttributeDescription attributeDescription{};
  1474. attributeDescription.binding = constantColorBufferBinding;
  1475. attributeDescription.location = ATTRIB_COLOR;
  1476. attributeDescription.offset = 0;
  1477. attributeDescription.format = VK_FORMAT_R32G32B32A32_SFLOAT;
  1478. attributeDescriptions.push_back(attributeDescription);
  1479. }
  1480. }
  1481. void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindings &buffers, graphics::Texture *texture, PrimitiveType primitiveType, CullMode cullmode)
  1482. {
  1483. if (!renderPassState.active)
  1484. startRenderPass();
  1485. Shader::current->attach();
  1486. GraphicsPipelineConfiguration configuration{};
  1487. configuration.renderPass = renderPassState.renderPass;
  1488. configuration.vertexAttributes = attributes;
  1489. configuration.shader = (Shader*)Shader::current;
  1490. configuration.wireFrame = states.back().wireframe;
  1491. configuration.blendState = states.back().blend;
  1492. configuration.colorChannelMask = states.back().colorMask;
  1493. configuration.msaaSamples = renderPassState.msaa;
  1494. configuration.numColorAttachments = renderPassState.numColorAttachments;
  1495. configuration.primitiveType = primitiveType;
  1496. if (optionalDeviceFeatures.extendedDynamicState)
  1497. ext.vkCmdSetCullModeEXT(commandBuffers.at(currentFrame), Vulkan::getCullMode(cullmode));
  1498. else
  1499. {
  1500. configuration.dynamicState.winding = states.back().winding;
  1501. configuration.dynamicState.depthState.compare = states.back().depthTest;
  1502. configuration.dynamicState.depthState.write = states.back().depthWrite;
  1503. configuration.dynamicState.stencilAction = states.back().stencil.action;
  1504. configuration.dynamicState.stencilCompare = states.back().stencil.compare;
  1505. configuration.dynamicState.cullmode = cullmode;
  1506. }
  1507. std::vector<VkBuffer> bufferVector;
  1508. std::vector<VkDeviceSize> offsets;
  1509. for (uint32_t i = 0; i < VertexAttributes::MAX; i++)
  1510. if (buffers.useBits & (1u << i))
  1511. {
  1512. bufferVector.push_back((VkBuffer)buffers.info[i].buffer->getHandle());
  1513. offsets.push_back((VkDeviceSize)buffers.info[i].offset);
  1514. }
  1515. if (usesConstantVertexColor(attributes))
  1516. {
  1517. bufferVector.push_back((VkBuffer)batchedDrawBuffers[currentFrame].constantColorBuffer->getHandle());
  1518. offsets.push_back((VkDeviceSize)0);
  1519. }
  1520. if (texture == nullptr)
  1521. configuration.shader->setMainTex(standardTexture.get());
  1522. else
  1523. configuration.shader->setMainTex(texture);
  1524. ensureGraphicsPipelineConfiguration(configuration);
  1525. configuration.shader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS);
  1526. vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), 0, static_cast<uint32_t>(bufferVector.size()), bufferVector.data(), offsets.data());
  1527. }
  1528. void Graphics::setDefaultRenderPass()
  1529. {
  1530. renderPassState.beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  1531. renderPassState.beginInfo.renderPass = defaultRenderPass;
  1532. renderPassState.beginInfo.framebuffer = defaultFramebuffers[imageIndex];
  1533. renderPassState.beginInfo.renderArea.offset = { 0, 0 };
  1534. renderPassState.beginInfo.renderArea.extent = swapChainExtent;
  1535. renderPassState.beginInfo.clearValueCount = 0;
  1536. renderPassState.renderPass = defaultRenderPass;
  1537. renderPassState.pipeline = VK_NULL_HANDLE;
  1538. renderPassState.width = static_cast<float>(swapChainExtent.width);
  1539. renderPassState.height = static_cast<float>(swapChainExtent.height);
  1540. renderPassState.msaa = msaaSamples;
  1541. renderPassState.numColorAttachments = 1;
  1542. renderPassState.transitionImages.clear();
  1543. VkViewport viewport{};
  1544. viewport.x = 0.0f;
  1545. viewport.y = 0.0f;
  1546. viewport.width = renderPassState.width;
  1547. viewport.height = renderPassState.height;
  1548. viewport.minDepth = 0.0f;
  1549. viewport.maxDepth = 1.0f;
  1550. vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
  1551. }
  1552. void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture)
  1553. {
  1554. VkViewport viewport{};
  1555. viewport.x = 0.0f;
  1556. viewport.y = 0.0f;
  1557. viewport.width = static_cast<float>(pixelw);
  1558. viewport.height = static_cast<float>(pixelh);
  1559. viewport.minDepth = 0.0f;
  1560. viewport.maxDepth = 1.0f;
  1561. vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
  1562. auto currentCommandBuffer = commandBuffers.at(currentFrame);
  1563. // fixme: hasSRGBtexture
  1564. // fixme: msaaSamples
  1565. RenderPassConfiguration renderPassConfiguration{};
  1566. for (const auto &color : rts.colors)
  1567. {
  1568. // fixme: use mipmap and slice.
  1569. color.mipmap;
  1570. color.slice;
  1571. renderPassConfiguration.colorFormats.push_back(Vulkan::getTextureFormat(color.texture->getPixelFormat()).internalFormat);
  1572. }
  1573. if (rts.depthStencil.texture != nullptr)
  1574. {
  1575. // fixme: use mipmap and slice:
  1576. rts.depthStencil.mipmap;
  1577. rts.depthStencil.slice;
  1578. if (rts.depthStencil.texture != nullptr)
  1579. renderPassConfiguration.staticData.depthFormat = Vulkan::getTextureFormat(rts.depthStencil.texture->getPixelFormat()).internalFormat;
  1580. }
  1581. VkRenderPass renderPass;
  1582. auto it = renderPasses.find(renderPassConfiguration);
  1583. if (it != renderPasses.end())
  1584. renderPass = it->second;
  1585. else
  1586. {
  1587. renderPass = createRenderPass(renderPassConfiguration);
  1588. renderPasses[renderPassConfiguration] = renderPass;
  1589. }
  1590. FramebufferConfiguration configuration{};
  1591. std::vector<VkImage> transitionImages;
  1592. for (const auto& color : rts.colors)
  1593. {
  1594. configuration.colorViews.push_back((VkImageView)color.texture->getRenderTargetHandle());
  1595. transitionImages.push_back((VkImage) color.texture->getHandle());
  1596. }
  1597. if (rts.depthStencil.texture != nullptr)
  1598. // fixme: layout transition of depth stencil image?
  1599. configuration.staticData.depthView = (VkImageView)rts.depthStencil.texture->getRenderTargetHandle();
  1600. configuration.staticData.renderPass = renderPass;
  1601. configuration.staticData.width = static_cast<uint32_t>(pixelw);
  1602. configuration.staticData.height = static_cast<uint32_t>(pixelh);
  1603. VkFramebuffer framebuffer = getFramebuffer(configuration);
  1604. renderPassState.beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  1605. renderPassState.beginInfo.renderPass = renderPass;
  1606. renderPassState.beginInfo.framebuffer = framebuffer;
  1607. renderPassState.beginInfo.renderArea.offset = {0, 0};
  1608. renderPassState.beginInfo.renderArea.extent.width = static_cast<uint32_t>(pixelw);
  1609. renderPassState.beginInfo.renderArea.extent.height = static_cast<uint32_t>(pixelh);
  1610. renderPassState.beginInfo.clearValueCount = 0;
  1611. renderPassState.renderPass = renderPass;
  1612. renderPassState.pipeline = VK_NULL_HANDLE;
  1613. renderPassState.width = static_cast<float>(pixelw);
  1614. renderPassState.height = static_cast<float>(pixelh);
  1615. renderPassState.msaa = VK_SAMPLE_COUNT_1_BIT;
  1616. renderPassState.numColorAttachments = static_cast<uint32_t>(rts.colors.size());
  1617. renderPassState.transitionImages = std::move(transitionImages);
  1618. }
  1619. void Graphics::startRenderPass()
  1620. {
  1621. renderPassState.active = true;
  1622. for (const auto& image : renderPassState.transitionImages)
  1623. Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
  1624. vkCmdBeginRenderPass(commandBuffers.at(currentFrame), &renderPassState.beginInfo, VK_SUBPASS_CONTENTS_INLINE);
  1625. }
  1626. void Graphics::endRenderPass()
  1627. {
  1628. renderPassState.active = false;
  1629. vkCmdEndRenderPass(commandBuffers.at(currentFrame));
  1630. for (const auto &image : renderPassState.transitionImages)
  1631. Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
  1632. }
  1633. VkSampler Graphics::createSampler(const SamplerState &samplerState)
  1634. {
  1635. VkPhysicalDeviceProperties properties{};
  1636. vkGetPhysicalDeviceProperties(physicalDevice, &properties);
  1637. VkSamplerCreateInfo samplerInfo{};
  1638. samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  1639. samplerInfo.magFilter = Vulkan::getFilter(samplerState.magFilter);
  1640. samplerInfo.minFilter = Vulkan::getFilter(samplerState.minFilter);
  1641. samplerInfo.addressModeU = Vulkan::getWrapMode(samplerState.wrapU);
  1642. samplerInfo.addressModeV = Vulkan::getWrapMode(samplerState.wrapV);
  1643. samplerInfo.addressModeW = Vulkan::getWrapMode(samplerState.wrapW);
  1644. samplerInfo.anisotropyEnable = VK_TRUE;
  1645. samplerInfo.maxAnisotropy = static_cast<float>(samplerState.maxAnisotropy);
  1646. samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
  1647. samplerInfo.unnormalizedCoordinates = VK_FALSE;
  1648. if (samplerState.depthSampleMode.hasValue)
  1649. {
  1650. samplerInfo.compareEnable = VK_TRUE;
  1651. samplerInfo.compareOp = Vulkan::getCompareOp(samplerState.depthSampleMode.value);
  1652. }
  1653. else
  1654. {
  1655. samplerInfo.compareEnable = VK_FALSE;
  1656. samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
  1657. }
  1658. samplerInfo.mipmapMode = Vulkan::getMipMapMode(samplerState.mipmapFilter);
  1659. samplerInfo.mipLodBias = samplerState.lodBias;
  1660. samplerInfo.minLod = static_cast<float>(samplerState.minLod);
  1661. samplerInfo.maxLod = static_cast<float>(samplerState.maxLod);
  1662. VkSampler sampler;
  1663. if (vkCreateSampler(device, &samplerInfo, nullptr, &sampler) != VK_SUCCESS)
  1664. throw love::Exception("failed to create sampler");
  1665. return sampler;
  1666. }
  1667. void Graphics::setComputeShader(Shader *shader)
  1668. {
  1669. computeShader = shader;
  1670. }
  1671. std::set<Shader*> &Graphics::getUsedShadersInFrame()
  1672. {
  1673. return usedShadersInFrame;
  1674. }
  1675. const OptionalDeviceFeatures &Graphics::getOptionalDeviceFeatures() const
  1676. {
  1677. return optionalDeviceFeatures;
  1678. }
  1679. const OptionalDeviceExtensionFunctions &Graphics::getExtensionFunctions() const
  1680. {
  1681. return ext;
  1682. }
  1683. VkSampler Graphics::getCachedSampler(const SamplerState &samplerState)
  1684. {
  1685. auto it = samplers.find(samplerState);
  1686. if (it != samplers.end())
  1687. return it->second;
  1688. else
  1689. {
  1690. VkSampler sampler = createSampler(samplerState);
  1691. samplers.insert({samplerState, sampler});
  1692. return sampler;
  1693. }
  1694. }
  1695. VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration &configuration)
  1696. {
  1697. VkGraphicsPipelineCreateInfo pipelineInfo{};
  1698. pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  1699. auto &shaderStages = configuration.shader->getShaderStages();
  1700. std::vector<VkVertexInputBindingDescription> bindingDescriptions;
  1701. std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
  1702. createVulkanVertexFormat(configuration.vertexAttributes, bindingDescriptions, attributeDescriptions);
  1703. VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
  1704. vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  1705. vertexInputInfo.vertexBindingDescriptionCount = static_cast<uint32_t>(bindingDescriptions.size());
  1706. vertexInputInfo.pVertexBindingDescriptions = bindingDescriptions.data();
  1707. vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
  1708. vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
  1709. VkPipelineViewportStateCreateInfo viewportState{};
  1710. viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  1711. viewportState.viewportCount = 1;
  1712. viewportState.scissorCount = 1;
  1713. VkPipelineMultisampleStateCreateInfo multisampling{};
  1714. multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  1715. multisampling.sampleShadingEnable = VK_FALSE;
  1716. multisampling.rasterizationSamples = configuration.msaaSamples;
  1717. multisampling.minSampleShading = 1.0f; // Optional
  1718. multisampling.pSampleMask = nullptr; // Optional
  1719. multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
  1720. multisampling.alphaToOneEnable = VK_FALSE; // Optional
  1721. VkPipelineRasterizationStateCreateInfo rasterizer{};
  1722. rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  1723. rasterizer.depthClampEnable = VK_FALSE;
  1724. rasterizer.rasterizerDiscardEnable = VK_FALSE;
  1725. rasterizer.polygonMode = Vulkan::getPolygonMode(configuration.wireFrame);
  1726. rasterizer.lineWidth = 1.0f;
  1727. if (!optionalDeviceFeatures.extendedDynamicState)
  1728. {
  1729. rasterizer.cullMode = Vulkan::getCullMode(configuration.dynamicState.cullmode);
  1730. rasterizer.frontFace = Vulkan::getFrontFace(configuration.dynamicState.winding);
  1731. }
  1732. rasterizer.depthBiasEnable = VK_FALSE;
  1733. rasterizer.depthBiasConstantFactor = 0.0f;
  1734. rasterizer.depthBiasClamp = 0.0f;
  1735. rasterizer.depthBiasSlopeFactor = 0.0f;
  1736. VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
  1737. inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  1738. inputAssembly.topology = Vulkan::getPrimitiveTypeTopology(configuration.primitiveType);
  1739. inputAssembly.primitiveRestartEnable = VK_FALSE;
  1740. VkPipelineDepthStencilStateCreateInfo depthStencil{};
  1741. depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  1742. depthStencil.depthTestEnable = VK_TRUE;
  1743. if (!optionalDeviceFeatures.extendedDynamicState)
  1744. {
  1745. depthStencil.depthWriteEnable = Vulkan::getBool(configuration.dynamicState.depthState.write);
  1746. depthStencil.depthCompareOp = Vulkan::getCompareOp(configuration.dynamicState.depthState.compare);
  1747. }
  1748. depthStencil.depthBoundsTestEnable = VK_FALSE;
  1749. depthStencil.minDepthBounds = 0.0f;
  1750. depthStencil.maxDepthBounds = 1.0f;
  1751. depthStencil.stencilTestEnable = VK_TRUE;
  1752. if (!optionalDeviceFeatures.extendedDynamicState)
  1753. {
  1754. depthStencil.front.failOp = VK_STENCIL_OP_KEEP;
  1755. depthStencil.front.passOp = Vulkan::getStencilOp(configuration.dynamicState.stencilAction);
  1756. depthStencil.front.depthFailOp = VK_STENCIL_OP_KEEP;
  1757. depthStencil.front.compareOp = Vulkan::getCompareOp(configuration.dynamicState.stencilCompare);
  1758. depthStencil.back.failOp = VK_STENCIL_OP_KEEP;
  1759. depthStencil.back.passOp = Vulkan::getStencilOp(configuration.dynamicState.stencilAction);
  1760. depthStencil.back.depthFailOp = VK_STENCIL_OP_KEEP;
  1761. depthStencil.back.compareOp = Vulkan::getCompareOp(configuration.dynamicState.stencilCompare);
  1762. }
  1763. pipelineInfo.pDepthStencilState = &depthStencil;
  1764. VkPipelineColorBlendAttachmentState colorBlendAttachment{};
  1765. colorBlendAttachment.colorWriteMask = Vulkan::getColorMask(configuration.colorChannelMask);
  1766. colorBlendAttachment.blendEnable = Vulkan::getBool(configuration.blendState.enable);
  1767. colorBlendAttachment.srcColorBlendFactor = Vulkan::getBlendFactor(configuration.blendState.srcFactorRGB);
  1768. colorBlendAttachment.dstColorBlendFactor = Vulkan::getBlendFactor(configuration.blendState.dstFactorRGB);
  1769. colorBlendAttachment.colorBlendOp = Vulkan::getBlendOp(configuration.blendState.operationRGB);
  1770. colorBlendAttachment.srcAlphaBlendFactor = Vulkan::getBlendFactor(configuration.blendState.srcFactorA);
  1771. colorBlendAttachment.dstAlphaBlendFactor = Vulkan::getBlendFactor(configuration.blendState.dstFactorA);
  1772. colorBlendAttachment.alphaBlendOp = Vulkan::getBlendOp(configuration.blendState.operationA);
  1773. std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachments(configuration.numColorAttachments, colorBlendAttachment);
  1774. VkPipelineColorBlendStateCreateInfo colorBlending{};
  1775. colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  1776. colorBlending.logicOpEnable = VK_FALSE;
  1777. colorBlending.logicOp = VK_LOGIC_OP_COPY;
  1778. colorBlending.attachmentCount = static_cast<uint32_t>(colorBlendAttachments.size());
  1779. colorBlending.pAttachments = colorBlendAttachments.data();
  1780. colorBlending.blendConstants[0] = 0.0f;
  1781. colorBlending.blendConstants[1] = 0.0f;
  1782. colorBlending.blendConstants[2] = 0.0f;
  1783. colorBlending.blendConstants[3] = 0.0f;
  1784. std::vector<VkDynamicState> dynamicStates;
  1785. if (optionalDeviceFeatures.extendedDynamicState)
  1786. dynamicStates = {
  1787. VK_DYNAMIC_STATE_SCISSOR,
  1788. VK_DYNAMIC_STATE_VIEWPORT,
  1789. VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
  1790. VK_DYNAMIC_STATE_STENCIL_REFERENCE,
  1791. VK_DYNAMIC_STATE_CULL_MODE_EXT,
  1792. VK_DYNAMIC_STATE_FRONT_FACE_EXT,
  1793. VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
  1794. VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
  1795. VK_DYNAMIC_STATE_STENCIL_OP_EXT,
  1796. };
  1797. else
  1798. dynamicStates = {
  1799. VK_DYNAMIC_STATE_SCISSOR,
  1800. VK_DYNAMIC_STATE_VIEWPORT,
  1801. VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
  1802. VK_DYNAMIC_STATE_STENCIL_REFERENCE,
  1803. };
  1804. VkPipelineDynamicStateCreateInfo dynamicState{};
  1805. dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
  1806. dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
  1807. dynamicState.pDynamicStates = dynamicStates.data();
  1808. pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
  1809. pipelineInfo.pStages = shaderStages.data();
  1810. pipelineInfo.pVertexInputState = &vertexInputInfo;
  1811. pipelineInfo.pInputAssemblyState = &inputAssembly;
  1812. pipelineInfo.pViewportState = &viewportState;
  1813. pipelineInfo.pRasterizationState = &rasterizer;
  1814. pipelineInfo.pMultisampleState = &multisampling;
  1815. pipelineInfo.pColorBlendState = &colorBlending;
  1816. pipelineInfo.pDynamicState = &dynamicState;
  1817. pipelineInfo.layout = configuration.shader->getGraphicsPipelineLayout();
  1818. pipelineInfo.subpass = 0;
  1819. pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
  1820. pipelineInfo.basePipelineIndex = -1;
  1821. pipelineInfo.renderPass = configuration.renderPass;
  1822. VkPipeline graphicsPipeline;
  1823. if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS)
  1824. throw love::Exception("failed to create graphics pipeline");
  1825. return graphicsPipeline;
  1826. }
  1827. void Graphics::ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration) {
  1828. auto it = graphicsPipelines.find(configuration);
  1829. if (it != graphicsPipelines.end())
  1830. {
  1831. if (it->second != renderPassState.pipeline)
  1832. {
  1833. vkCmdBindPipeline(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS, it->second);
  1834. renderPassState.pipeline = it->second;
  1835. }
  1836. }
  1837. else
  1838. {
  1839. VkPipeline pipeline = createGraphicsPipeline(configuration);
  1840. graphicsPipelines.insert({configuration, pipeline});
  1841. vkCmdBindPipeline(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
  1842. renderPassState.pipeline = pipeline;
  1843. }
  1844. }
  1845. void Graphics::getMaxUsableSampleCount()
  1846. {
  1847. VkPhysicalDeviceProperties physicalDeviceProperties;
  1848. vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
  1849. VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
  1850. if (counts & VK_SAMPLE_COUNT_64_BIT && requestedMsaa >= 64)
  1851. msaaSamples = VK_SAMPLE_COUNT_64_BIT;
  1852. else if (counts & VK_SAMPLE_COUNT_32_BIT && requestedMsaa >= 32)
  1853. msaaSamples = VK_SAMPLE_COUNT_32_BIT;
  1854. else if (counts & VK_SAMPLE_COUNT_16_BIT && requestedMsaa >= 16)
  1855. msaaSamples = VK_SAMPLE_COUNT_16_BIT;
  1856. else if (counts & VK_SAMPLE_COUNT_8_BIT && requestedMsaa >= 8)
  1857. msaaSamples = VK_SAMPLE_COUNT_8_BIT;
  1858. else if (counts & VK_SAMPLE_COUNT_4_BIT && requestedMsaa >= 4)
  1859. msaaSamples = VK_SAMPLE_COUNT_4_BIT;
  1860. else if (counts & VK_SAMPLE_COUNT_2_BIT && requestedMsaa >= 2)
  1861. msaaSamples = VK_SAMPLE_COUNT_2_BIT;
  1862. else
  1863. msaaSamples = VK_SAMPLE_COUNT_1_BIT;
  1864. }
  1865. void Graphics::createColorResources()
  1866. {
  1867. if (msaaSamples & VK_SAMPLE_COUNT_1_BIT)
  1868. {
  1869. colorImage = VK_NULL_HANDLE;
  1870. colorImageView = VK_NULL_HANDLE;
  1871. }
  1872. else
  1873. {
  1874. VkFormat colorFormat = swapChainImageFormat;
  1875. VkImageCreateInfo imageInfo{};
  1876. imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  1877. imageInfo.imageType = VK_IMAGE_TYPE_2D;
  1878. imageInfo.format = colorFormat;
  1879. imageInfo.extent.width = swapChainExtent.width;
  1880. imageInfo.extent.height = swapChainExtent.height;
  1881. imageInfo.extent.depth = 1;
  1882. imageInfo.mipLevels = 1;
  1883. imageInfo.arrayLayers = 1;
  1884. imageInfo.samples = msaaSamples;
  1885. imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
  1886. imageInfo.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  1887. imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  1888. imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  1889. VmaAllocationCreateInfo allocationInfo{};
  1890. allocationInfo.usage = VMA_MEMORY_USAGE_AUTO;
  1891. allocationInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
  1892. vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &colorImage, &colorImageAllocation, nullptr);
  1893. VkImageViewCreateInfo imageViewInfo{};
  1894. imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  1895. imageViewInfo.image = colorImage;
  1896. imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  1897. imageViewInfo.format = colorFormat;
  1898. imageViewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  1899. imageViewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  1900. imageViewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  1901. imageViewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  1902. imageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1903. imageViewInfo.subresourceRange.baseMipLevel = 0;
  1904. imageViewInfo.subresourceRange.levelCount = 1;
  1905. imageViewInfo.subresourceRange.baseArrayLayer = 0;
  1906. imageViewInfo.subresourceRange.layerCount = 1;
  1907. vkCreateImageView(device, &imageViewInfo, nullptr, &colorImageView);
  1908. }
  1909. }
  1910. VkFormat Graphics::findSupportedFormat(const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
  1911. {
  1912. for (auto format : candidates)
  1913. {
  1914. VkFormatProperties properties;
  1915. vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
  1916. if (tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features)
  1917. return format;
  1918. else if (tiling == VK_IMAGE_TILING_OPTIMAL && (properties.optimalTilingFeatures & features) == features)
  1919. return format;
  1920. }
  1921. throw love::Exception("failed to find supported format");
  1922. }
  1923. VkFormat Graphics::findDepthFormat()
  1924. {
  1925. return findSupportedFormat(
  1926. { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
  1927. VK_IMAGE_TILING_OPTIMAL,
  1928. VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
  1929. );
  1930. }
  1931. void Graphics::createDepthResources()
  1932. {
  1933. VkFormat depthFormat = findDepthFormat();
  1934. VkImageCreateInfo imageInfo{};
  1935. imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  1936. imageInfo.imageType = VK_IMAGE_TYPE_2D;
  1937. imageInfo.format = depthFormat;
  1938. imageInfo.extent.width = swapChainExtent.width;
  1939. imageInfo.extent.height = swapChainExtent.height;
  1940. imageInfo.extent.depth = 1;
  1941. imageInfo.mipLevels = 1;
  1942. imageInfo.arrayLayers = 1;
  1943. imageInfo.samples = msaaSamples;
  1944. imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
  1945. imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
  1946. imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  1947. imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  1948. VmaAllocationCreateInfo allocationInfo{};
  1949. allocationInfo.usage = VMA_MEMORY_USAGE_AUTO;
  1950. allocationInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
  1951. vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &depthImage, &depthImageAllocation, nullptr);
  1952. VkImageViewCreateInfo imageViewInfo{};
  1953. imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  1954. imageViewInfo.image = depthImage;
  1955. imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  1956. imageViewInfo.format = depthFormat;
  1957. imageViewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  1958. imageViewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  1959. imageViewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  1960. imageViewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  1961. imageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
  1962. imageViewInfo.subresourceRange.baseMipLevel = 0;
  1963. imageViewInfo.subresourceRange.levelCount = 1;
  1964. imageViewInfo.subresourceRange.baseArrayLayer = 0;
  1965. imageViewInfo.subresourceRange.layerCount = 1;
  1966. vkCreateImageView(device, &imageViewInfo, nullptr, &depthImageView);
  1967. }
  1968. void Graphics::createCommandPool()
  1969. {
  1970. QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);
  1971. VkCommandPoolCreateInfo poolInfo{};
  1972. poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  1973. poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
  1974. poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
  1975. if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS)
  1976. throw love::Exception("failed to create command pool");
  1977. }
  1978. void Graphics::createCommandBuffers()
  1979. {
  1980. commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
  1981. VkCommandBufferAllocateInfo allocInfo{};
  1982. allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  1983. allocInfo.commandPool = commandPool;
  1984. allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  1985. allocInfo.commandBufferCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
  1986. if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS)
  1987. throw love::Exception("failed to allocate command buffers");
  1988. }
  1989. void Graphics::createSyncObjects()
  1990. {
  1991. imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  1992. renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  1993. inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
  1994. imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE);
  1995. VkSemaphoreCreateInfo semaphoreInfo{};
  1996. semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  1997. VkFenceCreateInfo fenceInfo{};
  1998. fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  1999. fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  2000. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
  2001. if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores.at(i)) != VK_SUCCESS ||
  2002. vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores.at(i)) != VK_SUCCESS ||
  2003. vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences.at(i)) != VK_SUCCESS)
  2004. throw love::Exception("failed to create synchronization objects for a frame!");
  2005. }
  2006. void Graphics::createDefaultTexture()
  2007. {
  2008. Texture::Settings settings;
  2009. standardTexture.reset((Texture*)newTexture(settings, nullptr));
  2010. uint8_t whitePixels[] = {255, 255, 255, 255};
  2011. standardTexture->replacePixels(whitePixels, sizeof(whitePixels), 0, 0, { 0, 0, 1, 1 }, false);
  2012. }
  2013. void Graphics::cleanup()
  2014. {
  2015. cleanupSwapChain();
  2016. for (auto &cleanUpFns : cleanUpFunctions)
  2017. for (auto &cleanUpFn : cleanUpFns)
  2018. cleanUpFn();
  2019. cleanUpFunctions.clear();
  2020. vmaDestroyAllocator(vmaAllocator);
  2021. batchedDrawBuffers.clear();
  2022. for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
  2023. {
  2024. vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
  2025. vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
  2026. vkDestroyFence(device, inFlightFences[i], nullptr);
  2027. }
  2028. vkFreeCommandBuffers(device, commandPool, MAX_FRAMES_IN_FLIGHT, commandBuffers.data());
  2029. for (auto const &p : samplers)
  2030. vkDestroySampler(device, p.second, nullptr);
  2031. samplers.clear();
  2032. for (const auto &[key, val] : renderPasses)
  2033. vkDestroyRenderPass(device, val, nullptr);
  2034. // fixme: maybe we should clean up some pipelines if they haven't been used in a while.
  2035. for (auto const &p : graphicsPipelines)
  2036. vkDestroyPipeline(device, p.second, nullptr);
  2037. graphicsPipelines.clear();
  2038. vkDestroyCommandPool(device, commandPool, nullptr);
  2039. vkDestroyDevice(device, nullptr);
  2040. vkDestroySurfaceKHR(instance, surface, nullptr);
  2041. vkDestroyInstance(instance, nullptr);
  2042. }
  2043. void Graphics::cleanupSwapChain()
  2044. {
  2045. for (const auto &framebuffer : defaultFramebuffers)
  2046. vkDestroyFramebuffer(device, framebuffer, nullptr);
  2047. vkDestroyRenderPass(device, defaultRenderPass, nullptr);
  2048. vkDestroyImageView(device, colorImageView, nullptr);
  2049. vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation);
  2050. vkDestroyImageView(device, depthImageView, nullptr);
  2051. vmaDestroyImage(vmaAllocator, depthImage, depthImageAllocation);
  2052. for (const auto &[key, val] : framebuffers)
  2053. vkDestroyFramebuffer(device, val, nullptr);
  2054. framebuffers.clear();
  2055. for (const auto &swapChainImageView : swapChainImageViews)
  2056. vkDestroyImageView(device, swapChainImageView, nullptr);
  2057. swapChainImageViews.clear();
  2058. vkDestroySwapchainKHR(device, swapChain, nullptr);
  2059. }
  2060. void Graphics::recreateSwapChain()
  2061. {
  2062. vkDeviceWaitIdle(device);
  2063. cleanupSwapChain();
  2064. createSwapChain();
  2065. createImageViews();
  2066. createColorResources();
  2067. createDepthResources();
  2068. createDefaultRenderPass();
  2069. createDefaultFramebuffers();
  2070. }
  2071. love::graphics::Graphics *createInstance()
  2072. {
  2073. love::graphics::Graphics *instance = nullptr;
  2074. try
  2075. {
  2076. instance = new Graphics();
  2077. }
  2078. catch (love::Exception &e)
  2079. {
  2080. printf("Cannot create Vulkan renderer: %s\n", e.what());
  2081. }
  2082. return instance;
  2083. }
  2084. } // vulkan
  2085. } // graphics
  2086. } // love