Graphics.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. #pragma once
  2. // löve
  3. #include "common/config.h"
  4. #include "graphics/Graphics.h"
  5. #include "StreamBuffer.h"
  6. #include "ShaderStage.h"
  7. #include "Shader.h"
  8. #include "Texture.h"
  9. // libraries
  10. #include "VulkanWrapper.h"
  11. #include "libraries/xxHash/xxhash.h"
  12. // c++
  13. #include <optional>
  14. #include <iostream>
  15. #include <memory>
  16. #include <functional>
  17. #include <set>
  18. namespace love
  19. {
  20. namespace graphics
  21. {
  22. namespace vulkan
  23. {
  24. struct RenderPassAttachment
  25. {
  26. VkFormat format = VK_FORMAT_UNDEFINED;
  27. bool discard = true;
  28. bool operator==(const RenderPassAttachment &attachment) const
  29. {
  30. return format == attachment.format && discard == attachment.discard;
  31. }
  32. };
  33. struct RenderPassConfiguration
  34. {
  35. std::vector<RenderPassAttachment> colorAttachments;
  36. struct StaticRenderPassConfiguration
  37. {
  38. VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
  39. RenderPassAttachment depthAttachment;
  40. bool resolve = false;
  41. } staticData;
  42. bool operator==(const RenderPassConfiguration &conf) const
  43. {
  44. return colorAttachments == conf.colorAttachments &&
  45. (memcmp(&staticData, &conf.staticData, sizeof(StaticRenderPassConfiguration)) == 0);
  46. }
  47. };
  48. struct RenderPassConfigurationHasher
  49. {
  50. size_t operator()(const RenderPassConfiguration &configuration) const
  51. {
  52. size_t hashes[] = {
  53. XXH32(configuration.colorAttachments.data(), configuration.colorAttachments.size() * sizeof(VkFormat), 0),
  54. XXH32(&configuration.staticData, sizeof(configuration.staticData), 0),
  55. };
  56. return XXH32(hashes, sizeof(hashes), 0);
  57. }
  58. };
  59. struct FramebufferConfiguration
  60. {
  61. std::vector<VkImageView> colorViews;
  62. struct StaticFramebufferConfiguration
  63. {
  64. VkImageView depthView = VK_NULL_HANDLE;
  65. VkImageView resolveView = VK_NULL_HANDLE;
  66. uint32_t width = 0;
  67. uint32_t height = 0;
  68. VkRenderPass renderPass = VK_NULL_HANDLE;
  69. } staticData;
  70. bool operator==(const FramebufferConfiguration &conf) const
  71. {
  72. return colorViews == conf.colorViews &&
  73. (memcmp(&staticData, &conf.staticData, sizeof(StaticFramebufferConfiguration)) == 0);
  74. }
  75. };
  76. struct FramebufferConfigurationHasher
  77. {
  78. size_t operator()(const FramebufferConfiguration &configuration) const
  79. {
  80. size_t hashes[] = {
  81. XXH32(configuration.colorViews.data(), configuration.colorViews.size() * sizeof(VkImageView), 0),
  82. XXH32(&configuration.staticData, sizeof(configuration.staticData), 0),
  83. };
  84. return XXH32(hashes, sizeof(hashes), 0);
  85. }
  86. };
  87. struct OptionalInstanceExtensions
  88. {
  89. bool physicalDeviceProperties2 = false;
  90. };
  91. struct OptionalDeviceFeatures
  92. {
  93. // VK_EXT_extended_dynamic_state
  94. bool extendedDynamicState = false;
  95. // VK_KHR_get_memory_requirements2
  96. bool memoryRequirements2 = false;
  97. // VK_KHR_dedicated_allocation
  98. bool dedicatedAllocation = false;
  99. // VK_KHR_buffer_device_address
  100. bool bufferDeviceAddress = false;
  101. // VK_EXT_memory_budget
  102. bool memoryBudget = false;
  103. // VK_KHR_shader_float_controls
  104. bool shaderFloatControls = false;
  105. // VK_KHR_spirv_1_4
  106. bool spirv14 = false;
  107. };
  108. struct OptionalDeviceExtensionFunctions
  109. {
  110. // VK_EXT_extended_dynamic_state
  111. PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT = nullptr;
  112. PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT = nullptr;
  113. PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT = nullptr;
  114. PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT = nullptr;
  115. PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT = nullptr;
  116. PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT = nullptr;
  117. PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT = nullptr;
  118. PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT = nullptr;
  119. PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT = nullptr;
  120. PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT = nullptr;
  121. PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT = nullptr;
  122. // VK_KHR_get_memory_requirements2
  123. PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR = nullptr;
  124. PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR = nullptr;
  125. PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR = nullptr;
  126. // VK_KHR_buffer_device_address
  127. PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR = nullptr;
  128. PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR = nullptr;
  129. PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR = nullptr;
  130. };
  131. struct GraphicsPipelineConfiguration
  132. {
  133. VkRenderPass renderPass;
  134. VertexAttributes vertexAttributes;
  135. Shader *shader = nullptr;
  136. bool wireFrame;
  137. BlendState blendState;
  138. ColorChannelMask colorChannelMask;
  139. VkSampleCountFlagBits msaaSamples;
  140. uint32_t numColorAttachments;
  141. PrimitiveType primitiveType;
  142. struct DynamicState
  143. {
  144. CullMode cullmode = CULL_NONE;
  145. Winding winding = WINDING_MAX_ENUM;
  146. StencilAction stencilAction = STENCIL_MAX_ENUM;
  147. CompareMode stencilCompare = COMPARE_MAX_ENUM;
  148. DepthState depthState{};
  149. } dynamicState;
  150. GraphicsPipelineConfiguration()
  151. {
  152. memset(this, 0, sizeof(GraphicsPipelineConfiguration));
  153. }
  154. bool operator==(const GraphicsPipelineConfiguration &other) const
  155. {
  156. return memcmp(this, &other, sizeof(GraphicsPipelineConfiguration)) == 0;
  157. }
  158. };
  159. struct GraphicsPipelineConfigurationHasher
  160. {
  161. size_t operator() (const GraphicsPipelineConfiguration &configuration) const
  162. {
  163. return XXH32(&configuration, sizeof(GraphicsPipelineConfiguration), 0);
  164. }
  165. };
  166. struct SamplerStateHasher
  167. {
  168. size_t operator()(const SamplerState &samplerState) const
  169. {
  170. return XXH32(&samplerState, sizeof(SamplerState), 0);
  171. }
  172. };
  173. struct BatchedDrawBuffers
  174. {
  175. StreamBuffer *vertexBuffer1;
  176. StreamBuffer *vertexBuffer2;
  177. StreamBuffer *indexBuffer;
  178. StreamBuffer *constantColorBuffer;
  179. ~BatchedDrawBuffers()
  180. {
  181. delete vertexBuffer1;
  182. delete vertexBuffer2;
  183. delete indexBuffer;
  184. delete constantColorBuffer;
  185. }
  186. };
  187. struct QueueFamilyIndices
  188. {
  189. std::optional<uint32_t> graphicsFamily;
  190. std::optional<uint32_t> presentFamily;
  191. bool isComplete() const
  192. {
  193. return graphicsFamily.has_value() && presentFamily.has_value();
  194. }
  195. };
  196. struct SwapChainSupportDetails
  197. {
  198. VkSurfaceCapabilitiesKHR capabilities{};
  199. std::vector<VkSurfaceFormatKHR> formats;
  200. std::vector<VkPresentModeKHR> presentModes;
  201. };
  202. struct RenderpassState
  203. {
  204. bool active = false;
  205. VkRenderPassBeginInfo beginInfo{};
  206. bool useConfigurations = false;
  207. RenderPassConfiguration renderPassConfiguration{};
  208. FramebufferConfiguration framebufferConfiguration{};
  209. VkPipeline pipeline = VK_NULL_HANDLE;
  210. std::vector<VkImage> transitionImages;
  211. uint32_t numColorAttachments = 0;
  212. float width = 0.0f;
  213. float height = 0.0f;
  214. VkSampleCountFlagBits msaa = VK_SAMPLE_COUNT_1_BIT;
  215. };
  216. class Graphics final : public love::graphics::Graphics
  217. {
  218. public:
  219. #ifdef LOVE_ANDROID
  220. Graphics() {
  221. auto result = volkInitialize();
  222. if (result != VK_SUCCESS) {
  223. throw love::Exception("could not initialize volk");
  224. }
  225. }
  226. #else
  227. Graphics() = default;
  228. #endif
  229. virtual ~Graphics();
  230. const char *getName() const override;
  231. const VkDevice getDevice() const;
  232. const VmaAllocator getVmaAllocator() const;
  233. // implementation for virtual functions
  234. love::graphics::Texture *newTexture(const love::graphics::Texture::Settings &settings, const love::graphics::Texture::Slices *data) override;
  235. 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;
  236. void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override;
  237. void clear(const std::vector<OptionalColorD> &colors, OptionalInt stencil, OptionalDouble depth) override;
  238. Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override;
  239. void discard(const std::vector<bool>& colorbuffers, bool depthstencil) override;
  240. void present(void *screenshotCallbackdata) override;
  241. void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
  242. bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override;
  243. void unSetMode() override;
  244. void setActive(bool active) override;
  245. int getRequestedBackbufferMSAA() const override;
  246. int getBackbufferMSAA() const override;
  247. void setColor(Colorf c) override;
  248. void setScissor(const Rect &rect) override;
  249. void setScissor() override;
  250. void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override;
  251. void setDepthMode(CompareMode compare, bool write) override;
  252. void setFrontFaceWinding(Winding winding) override;
  253. void setColorMask(ColorChannelMask mask) override;
  254. void setBlendState(const BlendState &blend) override;
  255. void setPointSize(float size) override;
  256. void setWireframe(bool enable) override;
  257. PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
  258. bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) override;
  259. Renderer getRenderer() const override;
  260. bool usesGLSLES() const override;
  261. RendererInfo getRendererInfo() const override;
  262. void draw(const DrawCommand &cmd) override;
  263. void draw(const DrawIndexedCommand &cmd) override;
  264. void drawQuads(int start, int count, const VertexAttributes &attributes, const BufferBindings &buffers, graphics::Texture *texture) override;
  265. graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset) override;
  266. graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Texture *texture, int slice, int mipmap, const Rect &rect, image::ImageData *dest, int destx, int desty) override;
  267. VkCommandBuffer getCommandBufferForDataTransfer();
  268. void queueCleanUp(std::function<void()> cleanUp);
  269. void addReadbackCallback(std::function<void()> callback);
  270. void submitGpuCommands(bool present);
  271. uint32_t getNumImagesInFlight() const;
  272. uint32_t getFrameIndex() const;
  273. const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
  274. graphics::Texture *getDefaultTexture() const;
  275. VkSampler getCachedSampler(const SamplerState &samplerState);
  276. void setComputeShader(Shader *computeShader);
  277. std::set<Shader*> &getUsedShadersInFrame();
  278. graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
  279. const OptionalDeviceFeatures &getEnabledOptionalDeviceExtensions() const;
  280. protected:
  281. graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
  282. graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override;
  283. graphics::StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) override;
  284. bool dispatch(int x, int y, int z) override;
  285. void initCapabilities() override;
  286. void getAPIStats(int &shaderswitches) const override;
  287. void setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) override;
  288. private:
  289. void createVulkanInstance();
  290. bool checkValidationSupport();
  291. void pickPhysicalDevice();
  292. void getMaxUsableSampleCount();
  293. int rateDeviceSuitability(VkPhysicalDevice device);
  294. QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
  295. void createLogicalDevice();
  296. void initVMA();
  297. void createSurface();
  298. bool checkDeviceExtensionSupport(VkPhysicalDevice device);
  299. SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
  300. VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats);
  301. VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes);
  302. VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities);
  303. VkCompositeAlphaFlagBitsKHR chooseCompositeAlpha(const VkSurfaceCapabilitiesKHR &capabilities);
  304. void createSwapChain();
  305. void createImageViews();
  306. void createDefaultRenderPass();
  307. void createDefaultFramebuffers();
  308. VkFramebuffer createFramebuffer(FramebufferConfiguration &configuration);
  309. VkFramebuffer getFramebuffer(FramebufferConfiguration &configuration);
  310. void createDefaultShaders();
  311. VkRenderPass createRenderPass(RenderPassConfiguration &configuration);
  312. VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration &configuration);
  313. void createColorResources();
  314. VkFormat findSupportedFormat(const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
  315. VkFormat findDepthFormat();
  316. void createDepthResources();
  317. void createCommandPool();
  318. void createCommandBuffers();
  319. void createSyncObjects();
  320. void createDefaultTexture();
  321. void cleanup();
  322. void cleanupSwapChain();
  323. void recreateSwapChain();
  324. void initDynamicState();
  325. void beginFrame();
  326. void startRecordingGraphicsCommands(bool newFrame);
  327. void endRecordingGraphicsCommands(bool present);
  328. void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration);
  329. void updatedBatchedDrawBuffers();
  330. bool usesConstantVertexColor(const VertexAttributes &attribs);
  331. void createVulkanVertexFormat(
  332. VertexAttributes vertexAttributes,
  333. std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
  334. std::vector<VkVertexInputAttributeDescription> &attributeDescriptions);
  335. void prepareDraw(const VertexAttributes &attributes, const BufferBindings &buffers, graphics::Texture *texture, 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 &samplerState);
  341. VkInstance instance = VK_NULL_HANDLE;
  342. VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
  343. int requestedMsaa = 0;
  344. VkDevice device = VK_NULL_HANDLE;
  345. OptionalInstanceExtensions optionalInstanceExtensions;
  346. OptionalDeviceFeatures optionalDeviceFeatures;
  347. OptionalDeviceExtensionFunctions ext;
  348. VkQueue graphicsQueue = VK_NULL_HANDLE;
  349. VkQueue presentQueue = VK_NULL_HANDLE;
  350. VkSurfaceKHR surface = VK_NULL_HANDLE;
  351. VkSwapchainKHR swapChain = VK_NULL_HANDLE;
  352. VkSurfaceTransformFlagBitsKHR preTransform = {};
  353. Matrix4 displayRotation;
  354. std::vector<VkImage> swapChainImages;
  355. VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED;
  356. VkExtent2D swapChainExtent = VkExtent2D();
  357. std::vector<VkImageView> swapChainImageViews;
  358. VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
  359. VkImage colorImage = VK_NULL_HANDLE;
  360. VkImageView colorImageView = VK_NULL_HANDLE;
  361. VmaAllocation colorImageAllocation = VK_NULL_HANDLE;
  362. VkImage depthImage = VK_NULL_HANDLE;
  363. VkImageView depthImageView = VK_NULL_HANDLE;
  364. VmaAllocation depthImageAllocation = VK_NULL_HANDLE;
  365. VkRenderPass defaultRenderPass = VK_NULL_HANDLE;
  366. std::vector<VkFramebuffer> defaultFramebuffers;
  367. std::unordered_map<RenderPassConfiguration, VkRenderPass, RenderPassConfigurationHasher> renderPasses;
  368. std::unordered_map<FramebufferConfiguration, VkFramebuffer, FramebufferConfigurationHasher> framebuffers;
  369. std::unordered_map<GraphicsPipelineConfiguration, VkPipeline, GraphicsPipelineConfigurationHasher> graphicsPipelines;
  370. std::unordered_map<SamplerState, VkSampler, SamplerStateHasher> samplers;
  371. VkCommandPool commandPool = VK_NULL_HANDLE;
  372. std::vector<VkCommandBuffer> commandBuffers;
  373. Shader* computeShader = nullptr;
  374. std::vector<VkSemaphore> imageAvailableSemaphores;
  375. std::vector<VkSemaphore> renderFinishedSemaphores;
  376. std::vector<VkFence> inFlightFences;
  377. std::vector<VkFence> imagesInFlight;
  378. VkDeviceSize minUniformBufferOffsetAlignment = 0;
  379. bool imageRequested = false;
  380. size_t currentFrame = 0;
  381. uint32_t imageIndex = 0;
  382. bool framebufferResized = false;
  383. bool transitionColorDepthLayouts = false;
  384. VmaAllocator vmaAllocator = VK_NULL_HANDLE;
  385. std::unique_ptr<Texture> standardTexture = nullptr;
  386. // we need an array of draw buffers, since the frames are being rendered asynchronously
  387. // and we can't (or shouldn't) update the contents of the buffers while they're still in flight / being rendered.
  388. std::vector<BatchedDrawBuffers> batchedDrawBuffers;
  389. // functions that need to be called to cleanup objects that were needed for rendering a frame.
  390. // just like batchedDrawBuffers we need a vector for each frame in flight.
  391. std::vector<std::vector<std::function<void()>>> cleanUpFunctions;
  392. std::vector<std::vector<std::function<void()>>> readbackCallbacks;
  393. std::set<Shader*> usedShadersInFrame;
  394. RenderpassState renderPassState;
  395. };
  396. } // vulkan
  397. } // graphics
  398. } // love