Graphics.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /**
  2. * Copyright (c) 2006-2023 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #pragma once
  21. // löve
  22. #include "common/config.h"
  23. #include "graphics/Graphics.h"
  24. #include "StreamBuffer.h"
  25. #include "ShaderStage.h"
  26. #include "Shader.h"
  27. #include "Texture.h"
  28. // libraries
  29. #include "VulkanWrapper.h"
  30. #include "libraries/xxHash/xxhash.h"
  31. // c++
  32. #include <iostream>
  33. #include <memory>
  34. #include <functional>
  35. #include <set>
  36. namespace love
  37. {
  38. namespace graphics
  39. {
  40. namespace vulkan
  41. {
  42. struct ColorAttachment
  43. {
  44. VkFormat format = VK_FORMAT_UNDEFINED;
  45. VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  46. VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
  47. bool operator==(const ColorAttachment&attachment) const
  48. {
  49. return format == attachment.format &&
  50. loadOp == attachment.loadOp &&
  51. msaaSamples == attachment.msaaSamples;
  52. }
  53. };
  54. struct DepthStencilAttachment
  55. {
  56. VkFormat format = VK_FORMAT_UNDEFINED;
  57. VkAttachmentLoadOp depthLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  58. VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  59. VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
  60. bool operator==(const DepthStencilAttachment &attachment) const
  61. {
  62. return format == attachment.format &&
  63. depthLoadOp == attachment.depthLoadOp &&
  64. stencilLoadOp == attachment.stencilLoadOp &&
  65. msaaSamples == attachment.msaaSamples;
  66. }
  67. };
  68. struct RenderPassConfiguration
  69. {
  70. std::vector<ColorAttachment> colorAttachments;
  71. struct StaticRenderPassConfiguration
  72. {
  73. DepthStencilAttachment depthStencilAttachment;
  74. bool resolve = false;
  75. } staticData;
  76. bool operator==(const RenderPassConfiguration &conf) const
  77. {
  78. return colorAttachments == conf.colorAttachments &&
  79. (memcmp(&staticData, &conf.staticData, sizeof(StaticRenderPassConfiguration)) == 0);
  80. }
  81. };
  82. struct RenderPassConfigurationHasher
  83. {
  84. size_t operator()(const RenderPassConfiguration &configuration) const
  85. {
  86. size_t hashes[] = {
  87. XXH32(configuration.colorAttachments.data(), configuration.colorAttachments.size() * sizeof(VkFormat), 0),
  88. XXH32(&configuration.staticData, sizeof(configuration.staticData), 0),
  89. };
  90. return XXH32(hashes, sizeof(hashes), 0);
  91. }
  92. };
  93. struct FramebufferConfiguration
  94. {
  95. std::vector<VkImageView> colorViews;
  96. struct StaticFramebufferConfiguration
  97. {
  98. VkImageView depthView = VK_NULL_HANDLE;
  99. VkImageView resolveView = VK_NULL_HANDLE;
  100. uint32_t width = 0;
  101. uint32_t height = 0;
  102. VkRenderPass renderPass = VK_NULL_HANDLE;
  103. } staticData;
  104. bool operator==(const FramebufferConfiguration &conf) const
  105. {
  106. return colorViews == conf.colorViews &&
  107. (memcmp(&staticData, &conf.staticData, sizeof(StaticFramebufferConfiguration)) == 0);
  108. }
  109. };
  110. struct FramebufferConfigurationHasher
  111. {
  112. size_t operator()(const FramebufferConfiguration &configuration) const
  113. {
  114. size_t hashes[] = {
  115. XXH32(configuration.colorViews.data(), configuration.colorViews.size() * sizeof(VkImageView), 0),
  116. XXH32(&configuration.staticData, sizeof(configuration.staticData), 0),
  117. };
  118. return XXH32(hashes, sizeof(hashes), 0);
  119. }
  120. };
  121. struct OptionalInstanceExtensions
  122. {
  123. // VK_KHR_get_physical_device_properties2
  124. bool physicalDeviceProperties2 = false;
  125. };
  126. struct OptionalDeviceFeatures
  127. {
  128. // VK_EXT_extended_dynamic_state
  129. bool extendedDynamicState = false;
  130. // VK_KHR_get_memory_requirements2
  131. bool memoryRequirements2 = false;
  132. // VK_KHR_dedicated_allocation
  133. bool dedicatedAllocation = false;
  134. // VK_KHR_buffer_device_address
  135. bool bufferDeviceAddress = false;
  136. // VK_EXT_memory_budget
  137. bool memoryBudget = false;
  138. // VK_KHR_shader_float_controls
  139. bool shaderFloatControls = false;
  140. // VK_KHR_spirv_1_4
  141. bool spirv14 = false;
  142. };
  143. struct GraphicsPipelineConfiguration
  144. {
  145. VkRenderPass renderPass;
  146. VertexAttributes vertexAttributes;
  147. Shader *shader = nullptr;
  148. bool wireFrame;
  149. BlendState blendState;
  150. ColorChannelMask colorChannelMask;
  151. VkSampleCountFlagBits msaaSamples;
  152. uint32_t numColorAttachments;
  153. PrimitiveType primitiveType;
  154. struct DynamicState
  155. {
  156. CullMode cullmode = CULL_NONE;
  157. Winding winding = WINDING_MAX_ENUM;
  158. StencilAction stencilAction = STENCIL_MAX_ENUM;
  159. CompareMode stencilCompare = COMPARE_MAX_ENUM;
  160. DepthState depthState{};
  161. } dynamicState;
  162. GraphicsPipelineConfiguration()
  163. {
  164. memset(this, 0, sizeof(GraphicsPipelineConfiguration));
  165. }
  166. bool operator==(const GraphicsPipelineConfiguration &other) const
  167. {
  168. return memcmp(this, &other, sizeof(GraphicsPipelineConfiguration)) == 0;
  169. }
  170. };
  171. struct GraphicsPipelineConfigurationHasher
  172. {
  173. size_t operator() (const GraphicsPipelineConfiguration &configuration) const
  174. {
  175. return XXH32(&configuration, sizeof(GraphicsPipelineConfiguration), 0);
  176. }
  177. };
  178. struct QueueFamilyIndices
  179. {
  180. Optional<uint32_t> graphicsFamily;
  181. Optional<uint32_t> presentFamily;
  182. bool isComplete() const
  183. {
  184. return graphicsFamily.hasValue && presentFamily.hasValue;
  185. }
  186. };
  187. struct SwapChainSupportDetails
  188. {
  189. VkSurfaceCapabilitiesKHR capabilities{};
  190. std::vector<VkSurfaceFormatKHR> formats;
  191. std::vector<VkPresentModeKHR> presentModes;
  192. };
  193. struct RenderpassState
  194. {
  195. bool active = false;
  196. VkRenderPassBeginInfo beginInfo{};
  197. bool isWindow = false;
  198. bool useConfigurations = false;
  199. RenderPassConfiguration renderPassConfiguration{};
  200. FramebufferConfiguration framebufferConfiguration{};
  201. VkPipeline pipeline = VK_NULL_HANDLE;
  202. std::vector<VkImage> transitionImages;
  203. uint32_t numColorAttachments = 0;
  204. float width = 0.0f;
  205. float height = 0.0f;
  206. VkSampleCountFlagBits msaa = VK_SAMPLE_COUNT_1_BIT;
  207. std::vector<VkClearValue> clearColors;
  208. bool windowClearRequested = false;
  209. OptionalColorD mainWindowClearColorValue;
  210. OptionalDouble mainWindowClearDepthValue;
  211. OptionalInt mainWindowClearStencilValue;
  212. };
  213. struct ScreenshotReadbackBuffer
  214. {
  215. VkBuffer buffer;
  216. VmaAllocation allocation;
  217. VmaAllocationInfo allocationInfo;
  218. VkImage image;
  219. VmaAllocation imageAllocation;
  220. };
  221. class Graphics final : public love::graphics::Graphics
  222. {
  223. public:
  224. Graphics();
  225. ~Graphics();
  226. const char *getName() const override;
  227. const VkDevice getDevice() const;
  228. const VmaAllocator getVmaAllocator() const;
  229. // implementation for virtual functions
  230. love::graphics::Texture *newTexture(const love::graphics::Texture::Settings &settings, const love::graphics::Texture::Slices *data) override;
  231. love::graphics::Buffer *newBuffer(const love::graphics::Buffer::Settings &settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void *data, size_t size, size_t arraylength) override;
  232. void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override;
  233. void clear(const std::vector<OptionalColorD> &colors, OptionalInt stencil, OptionalDouble depth) override;
  234. Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override;
  235. void discard(const std::vector<bool>& colorbuffers, bool depthstencil) override;
  236. void present(void *screenshotCallbackdata) override;
  237. void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
  238. bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override;
  239. void unSetMode() override;
  240. void setActive(bool active) override;
  241. int getRequestedBackbufferMSAA() const override;
  242. int getBackbufferMSAA() const override;
  243. void setColor(Colorf c) override;
  244. void setScissor(const Rect &rect) override;
  245. void setScissor() override;
  246. void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override;
  247. void setDepthMode(CompareMode compare, bool write) override;
  248. void setFrontFaceWinding(Winding winding) override;
  249. void setColorMask(ColorChannelMask mask) override;
  250. void setBlendState(const BlendState &blend) override;
  251. void setPointSize(float size) override;
  252. void setWireframe(bool enable) override;
  253. PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
  254. bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) override;
  255. Renderer getRenderer() const override;
  256. bool usesGLSLES() const override;
  257. RendererInfo getRendererInfo() const override;
  258. void draw(const DrawCommand &cmd) override;
  259. void draw(const DrawIndexedCommand &cmd) override;
  260. void drawQuads(int start, int count, const VertexAttributes &attributes, const BufferBindings &buffers, graphics::Texture *texture) override;
  261. graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset) override;
  262. graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Texture *texture, int slice, int mipmap, const Rect &rect, image::ImageData *dest, int destx, int desty) override;
  263. // internal functions.
  264. VkCommandBuffer getCommandBufferForDataTransfer();
  265. void queueCleanUp(std::function<void()> cleanUp);
  266. void addReadbackCallback(std::function<void()> callback);
  267. void submitGpuCommands(bool present, void *screenshotCallbackData = nullptr);
  268. const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
  269. graphics::Texture *getDefaultTexture() const;
  270. VkSampler getCachedSampler(const SamplerState &sampler);
  271. void setComputeShader(Shader *computeShader);
  272. graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
  273. const OptionalDeviceFeatures &getEnabledOptionalDeviceExtensions() const;
  274. VkSampleCountFlagBits getMsaaCount(int requestedMsaa) const;
  275. void setVsync(int vsync);
  276. int getVsync() const;
  277. protected:
  278. graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
  279. graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override;
  280. graphics::StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) override;
  281. bool dispatch(int x, int y, int z) override;
  282. void initCapabilities() override;
  283. void getAPIStats(int &shaderswitches) const override;
  284. void setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) override;
  285. private:
  286. void createVulkanInstance();
  287. bool checkValidationSupport();
  288. void pickPhysicalDevice();
  289. int rateDeviceSuitability(VkPhysicalDevice device);
  290. QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
  291. void createLogicalDevice();
  292. void createPipelineCache();
  293. void initVMA();
  294. void createSurface();
  295. bool checkDeviceExtensionSupport(VkPhysicalDevice device);
  296. SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
  297. VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats);
  298. VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes);
  299. VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities);
  300. VkCompositeAlphaFlagBitsKHR chooseCompositeAlpha(const VkSurfaceCapabilitiesKHR &capabilities);
  301. void createSwapChain();
  302. void createImageViews();
  303. void createScreenshotCallbackBuffers();
  304. void createDefaultRenderPass();
  305. void createDefaultFramebuffers();
  306. VkFramebuffer createFramebuffer(FramebufferConfiguration &configuration);
  307. VkFramebuffer getFramebuffer(FramebufferConfiguration &configuration);
  308. void createDefaultShaders();
  309. VkRenderPass createRenderPass(RenderPassConfiguration &configuration);
  310. VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration &configuration);
  311. void createColorResources();
  312. VkFormat findSupportedFormat(const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
  313. VkFormat findDepthFormat();
  314. void createDepthResources();
  315. void createCommandPool();
  316. void createCommandBuffers();
  317. void createSyncObjects();
  318. void createDefaultTexture();
  319. void cleanup();
  320. void cleanupSwapChain();
  321. void recreateSwapChain();
  322. void initDynamicState();
  323. void beginFrame();
  324. void startRecordingGraphicsCommands();
  325. void endRecordingGraphicsCommands();
  326. void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration);
  327. bool usesConstantVertexColor(const VertexAttributes &attribs);
  328. void createVulkanVertexFormat(
  329. VertexAttributes vertexAttributes,
  330. std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
  331. std::vector<VkVertexInputAttributeDescription> &attributeDescriptions);
  332. void prepareDraw(
  333. const VertexAttributes &attributes,
  334. const BufferBindings &buffers, graphics::Texture *texture,
  335. PrimitiveType, CullMode);
  336. void setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture);
  337. void setDefaultRenderPass();
  338. void startRenderPass();
  339. void endRenderPass();
  340. VkSampler createSampler(const SamplerState &sampler);
  341. void cleanupUnusedObjects();
  342. void requestSwapchainRecreation();
  343. VkInstance instance = VK_NULL_HANDLE;
  344. VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
  345. uint32_t deviceApiVersion = VK_API_VERSION_1_0;
  346. bool windowHasStencil = false;
  347. int requestedMsaa = 0;
  348. VkDevice device = VK_NULL_HANDLE;
  349. OptionalInstanceExtensions optionalInstanceExtensions;
  350. OptionalDeviceFeatures optionalDeviceFeatures;
  351. VkQueue graphicsQueue = VK_NULL_HANDLE;
  352. VkQueue presentQueue = VK_NULL_HANDLE;
  353. VkSurfaceKHR surface = VK_NULL_HANDLE;
  354. VkSwapchainKHR swapChain = VK_NULL_HANDLE;
  355. VkSurfaceTransformFlagBitsKHR preTransform = {};
  356. Matrix4 displayRotation;
  357. std::vector<VkImage> swapChainImages;
  358. VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED;
  359. VkExtent2D swapChainExtent = VkExtent2D();
  360. std::vector<VkImageView> swapChainImageViews;
  361. VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
  362. VkImage colorImage = VK_NULL_HANDLE;
  363. VkImageView colorImageView = VK_NULL_HANDLE;
  364. VmaAllocation colorImageAllocation = VK_NULL_HANDLE;
  365. VkImage depthImage = VK_NULL_HANDLE;
  366. VkImageView depthImageView = VK_NULL_HANDLE;
  367. VmaAllocation depthImageAllocation = VK_NULL_HANDLE;
  368. VkRenderPass defaultRenderPass = VK_NULL_HANDLE;
  369. VkPipelineCache pipelineCache = VK_NULL_HANDLE;
  370. std::vector<VkFramebuffer> defaultFramebuffers;
  371. std::unordered_map<RenderPassConfiguration, VkRenderPass, RenderPassConfigurationHasher> renderPasses;
  372. std::unordered_map<FramebufferConfiguration, VkFramebuffer, FramebufferConfigurationHasher> framebuffers;
  373. std::unordered_map<GraphicsPipelineConfiguration, VkPipeline, GraphicsPipelineConfigurationHasher> graphicsPipelines;
  374. std::unordered_map<VkRenderPass, bool> renderPassUsages;
  375. std::unordered_map<VkFramebuffer, bool> framebufferUsages;
  376. std::unordered_map<VkPipeline, bool> pipelineUsages;
  377. std::unordered_map<uint64, VkSampler> samplers;
  378. VkCommandPool commandPool = VK_NULL_HANDLE;
  379. std::vector<VkCommandBuffer> commandBuffers;
  380. Shader *computeShader = nullptr;
  381. std::vector<VkSemaphore> imageAvailableSemaphores;
  382. std::vector<VkSemaphore> renderFinishedSemaphores;
  383. std::vector<VkFence> inFlightFences;
  384. std::vector<VkFence> imagesInFlight;
  385. int vsync = 1;
  386. VkDeviceSize minUniformBufferOffsetAlignment = 0;
  387. bool imageRequested = false;
  388. uint32_t frameCounter = 0;
  389. size_t currentFrame = 0;
  390. uint32_t imageIndex = 0;
  391. bool swapChainRecreationRequested = false;
  392. bool transitionColorDepthLayouts = false;
  393. VmaAllocator vmaAllocator = VK_NULL_HANDLE;
  394. StrongRef<love::graphics::Texture> defaultTexture;
  395. StrongRef<love::graphics::Buffer> defaultConstantColor;
  396. // functions that need to be called to cleanup objects that were needed for rendering a frame.
  397. // We need a vector for each frame in flight.
  398. std::vector<std::vector<std::function<void()>>> cleanUpFunctions;
  399. std::vector<std::vector<std::function<void()>>> readbackCallbacks;
  400. std::vector<ScreenshotReadbackBuffer> screenshotReadbackBuffers;
  401. std::set<Shader*> usedShadersInFrame;
  402. RenderpassState renderPassState;
  403. };
  404. } // vulkan
  405. } // graphics
  406. } // love