Graphics.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #ifndef LOVE_GRAPHICS_VULKAN_GRAPHICS_H
  2. #define LOVE_GRAPHICS_VULKAN_GRAPHICS_H
  3. // löve
  4. #include "graphics/Graphics.h"
  5. #include "StreamBuffer.h"
  6. #include "ShaderStage.h"
  7. #include "Shader.h"
  8. #include "Texture.h"
  9. #include <common/config.h>
  10. // libraries
  11. #include <vulkan/vulkan.h>
  12. #include "vk_mem_alloc.h"
  13. #include "libraries/xxHash/xxhash.h"
  14. // c++
  15. #include <optional>
  16. #include <iostream>
  17. #include <memory>
  18. #include <functional>
  19. namespace love {
  20. namespace graphics {
  21. namespace vulkan {
  22. struct GraphicsPipelineConfiguration {
  23. VertexAttributes vertexAttributes;
  24. Shader* shader = nullptr;
  25. PrimitiveType primitiveType = PRIMITIVE_MAX_ENUM;
  26. bool wireFrame;
  27. BlendState blendState;
  28. ColorChannelMask colorChannelMask;
  29. Winding winding;
  30. CullMode cullmode;
  31. VkFormat framebufferFormat;
  32. float viewportWidth;
  33. float viewportHeight;
  34. std::optional<Rect> scissorRect;
  35. GraphicsPipelineConfiguration() {
  36. memset(this, 0, sizeof(GraphicsPipelineConfiguration));
  37. }
  38. bool operator==(const GraphicsPipelineConfiguration& other) const {
  39. return memcmp(this, &other, sizeof(GraphicsPipelineConfiguration)) == 0;
  40. }
  41. };
  42. struct GraphicsPipelineConfigurationHasher {
  43. size_t operator() (const GraphicsPipelineConfiguration &configuration) const {
  44. return XXH32(&configuration, sizeof(GraphicsPipelineConfiguration), 0);
  45. }
  46. };
  47. struct SamplerStateHasher {
  48. size_t operator()(const SamplerState &samplerState) const {
  49. return XXH32(&samplerState, sizeof(SamplerState), 0);
  50. }
  51. };
  52. struct BatchedDrawBuffers {
  53. StreamBuffer* vertexBuffer1;
  54. StreamBuffer* vertexBuffer2;
  55. StreamBuffer* indexBuffer;
  56. StreamBuffer* constantColorBuffer;
  57. ~BatchedDrawBuffers() {
  58. delete vertexBuffer1;
  59. delete vertexBuffer2;
  60. delete indexBuffer;
  61. delete constantColorBuffer;
  62. }
  63. };
  64. struct QueueFamilyIndices {
  65. std::optional<uint32_t> graphicsFamily;
  66. std::optional<uint32_t> presentFamily;
  67. bool isComplete() {
  68. return graphicsFamily.has_value() && presentFamily.has_value();
  69. }
  70. };
  71. struct SwapChainSupportDetails {
  72. VkSurfaceCapabilitiesKHR capabilities{};
  73. std::vector<VkSurfaceFormatKHR> formats;
  74. std::vector<VkPresentModeKHR> presentModes;
  75. };
  76. class Graphics final : public love::graphics::Graphics {
  77. public:
  78. Graphics() = default;
  79. virtual ~Graphics();
  80. const char* getName() const override;
  81. const VkDevice getDevice() const;
  82. const VkPhysicalDevice getPhysicalDevice() const;
  83. const VmaAllocator getVmaAllocator() const;
  84. // implementation for virtual functions
  85. love::graphics::Texture* newTexture(const love::graphics::Texture::Settings& settings, const love::graphics::Texture::Slices* data = nullptr) override;
  86. 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;
  87. void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override;
  88. void clear(const std::vector<OptionalColorD>& colors, OptionalInt stencil, OptionalDouble depth) override;
  89. Matrix4 computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const override;
  90. void discard(const std::vector<bool>& colorbuffers, bool depthstencil) override { }
  91. void present(void* screenshotCallbackdata) override;
  92. void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
  93. bool setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override;
  94. void unSetMode() override;
  95. void setActive(bool active) override;
  96. int getRequestedBackbufferMSAA() const override { return 0; }
  97. int getBackbufferMSAA() const override { return 0; }
  98. void setColor(Colorf c) override;
  99. void setScissor(const Rect& rect) override;
  100. void setScissor() override;
  101. void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override { }
  102. void setDepthMode(CompareMode compare, bool write) override { }
  103. void setFrontFaceWinding(Winding winding) override;
  104. void setColorMask(ColorChannelMask mask) override;
  105. void setBlendState(const BlendState& blend) override;
  106. void setPointSize(float size) override;
  107. void setWireframe(bool enable) override;
  108. PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
  109. bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override;
  110. Renderer getRenderer() const override;
  111. bool usesGLSLES() const override;
  112. RendererInfo getRendererInfo() const override;
  113. void draw(const DrawCommand& cmd) override;
  114. void draw(const DrawIndexedCommand& cmd) override;
  115. void drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) override;
  116. GraphicsReadback* newReadbackInternal(ReadbackMethod method, love::graphics::Buffer* buffer, size_t offset, size_t size, data::ByteData* dest, size_t destoffset) override { return nullptr; };
  117. GraphicsReadback* newReadbackInternal(ReadbackMethod method, love::graphics::Texture* texture, int slice, int mipmap, const Rect& rect, image::ImageData* dest, int destx, int desty) { return nullptr; }
  118. void queueDatatransfer(std::function<void(VkCommandBuffer)> command, std::function<void()> cleanUp);
  119. void queueCleanUp(std::function<void()> cleanUp);
  120. VkCommandBuffer beginSingleTimeCommands();
  121. void endSingleTimeCommands(VkCommandBuffer);
  122. uint32_t getNumImagesInFlight() const;
  123. const PFN_vkCmdPushDescriptorSetKHR getVkCmdPushDescriptorSetKHRFunctionPointer() const;
  124. const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
  125. graphics::Texture* getDefaultTexture() const;
  126. VkSampler getCachedSampler(const SamplerState&);
  127. protected:
  128. graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override {
  129. return new ShaderStage(this, stage, source, gles, cachekey);
  130. }
  131. graphics::Shader* newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override {
  132. return new Shader(stages);
  133. }
  134. graphics::StreamBuffer* newStreamBuffer(BufferUsage type, size_t size) override;
  135. bool dispatch(int x, int y, int z) override { return false; }
  136. void initCapabilities() override;
  137. void getAPIStats(int& shaderswitches) const override;
  138. void setRenderTargetsInternal(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) override;
  139. private:
  140. void createVulkanInstance();
  141. bool checkValidationSupport();
  142. void pickPhysicalDevice();
  143. int rateDeviceSuitability(VkPhysicalDevice device);
  144. QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
  145. void createLogicalDevice();
  146. void initVMA();
  147. void createSurface();
  148. bool checkDeviceExtensionSupport(VkPhysicalDevice device);
  149. SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
  150. VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
  151. VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
  152. VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
  153. void createSwapChain();
  154. void createImageViews();
  155. void createDefaultShaders();
  156. VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration);
  157. void createCommandPool();
  158. void createCommandBuffers();
  159. void createSyncObjects();
  160. void createDefaultTexture();
  161. void cleanup();
  162. void cleanupSwapChain();
  163. void recreateSwapChain();
  164. void startRecordingGraphicsCommands();
  165. void endRecordingGraphicsCommands();
  166. void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration);
  167. graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
  168. void updatedBatchedDrawBuffers();
  169. bool usesConstantVertexColor(const VertexAttributes&);
  170. void createVulkanVertexFormat(
  171. VertexAttributes vertexAttributes,
  172. std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
  173. std::vector<VkVertexInputAttributeDescription> &attributeDescriptions);
  174. void prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType, CullMode);
  175. void startRenderPass(Texture*, uint32_t w, uint32_t h);
  176. void endRenderPass();
  177. VkSampler createSampler(const SamplerState&);
  178. VkInstance instance = VK_NULL_HANDLE;
  179. VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
  180. VkDevice device = VK_NULL_HANDLE;
  181. VkQueue graphicsQueue = VK_NULL_HANDLE;
  182. VkQueue presentQueue = VK_NULL_HANDLE;
  183. VkSurfaceKHR surface = VK_NULL_HANDLE;
  184. VkSwapchainKHR swapChain = VK_NULL_HANDLE;
  185. std::vector<VkImage> swapChainImages;
  186. VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED;
  187. VkExtent2D swapChainExtent = VkExtent2D();
  188. std::vector<VkImageView> swapChainImageViews;
  189. VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
  190. VkPipeline currentGraphicsPipeline = VK_NULL_HANDLE;
  191. std::unordered_map<GraphicsPipelineConfiguration, VkPipeline, GraphicsPipelineConfigurationHasher> graphicsPipelines;
  192. std::unordered_map<SamplerState, VkSampler, SamplerStateHasher> samplers;
  193. VkCommandPool commandPool = VK_NULL_HANDLE;
  194. std::vector<VkCommandBuffer> commandBuffers;
  195. std::vector<VkCommandBuffer> dataTransferCommandBuffers;
  196. std::vector<VkSemaphore> imageAvailableSemaphores;
  197. std::vector<VkSemaphore> renderFinishedSemaphores;
  198. std::vector<VkFence> inFlightFences;
  199. std::vector<VkFence> imagesInFlight;
  200. VkDeviceSize minUniformBufferOffsetAlignment;
  201. PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSet;
  202. size_t currentFrame = 0;
  203. uint32_t imageIndex = 0;
  204. bool framebufferResized = false;
  205. VmaAllocator vmaAllocator = VK_NULL_HANDLE;
  206. std::unique_ptr<Texture> standardTexture = nullptr;
  207. // we need an array of draw buffers, since the frames are being rendered asynchronously
  208. // and we can't (or shouldn't) update the contents of the buffers while they're still in flight / being rendered.
  209. std::vector<BatchedDrawBuffers> batchedDrawBuffers;
  210. // functions that need to be called to cleanup objects that were needed for rendering a frame.
  211. // just like batchedDrawBuffers we need a vector for each frame in flight.
  212. std::vector<std::vector<std::function<void()>>> cleanUpFunctions;
  213. graphics::Texture* currentTexture = nullptr;
  214. // render pass variables.
  215. VkFormat currentFramebufferOutputFormat = VK_FORMAT_UNDEFINED;
  216. Texture* renderTargetTexture;
  217. float currentViewportWidth = 0;
  218. float currentViewportHeight = 0;
  219. };
  220. } // vulkan
  221. } // graphics
  222. } // love
  223. #endif