Graphics.cpp 77 KB

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