1 #pragma once 2 3 #include "osapi/osapi.h" 4 5 #include "RenderFrame.h" 6 7 #include <vulkan/vulkan.hpp> 8 9 #if SDL_VERSION_ATLEAST(2, 0, 6) 10 #define SDL_SUPPORTS_VULKAN 1 11 #else 12 #define SDL_SUPPORTS_VULKAN 0 13 #endif 14 15 namespace graphics { 16 namespace vulkan { 17 18 struct QueueIndex { 19 // Poor mans std::optional 20 bool initialized = false; 21 uint32_t index = 0; 22 }; 23 24 struct PhysicalDeviceValues { 25 vk::PhysicalDevice device; 26 vk::PhysicalDeviceProperties properties; 27 vk::PhysicalDeviceFeatures features; 28 29 std::vector<vk::ExtensionProperties> extensions; 30 31 vk::SurfaceCapabilitiesKHR surfaceCapabilities; 32 std::vector<vk::SurfaceFormatKHR> surfaceFormats; 33 std::vector<vk::PresentModeKHR> presentModes; 34 35 std::vector<vk::QueueFamilyProperties> queueProperties; 36 QueueIndex graphicsQueueIndex; 37 QueueIndex transferQueueIndex; 38 QueueIndex presentQueueIndex; 39 }; 40 41 class VulkanRenderer { 42 public: 43 explicit VulkanRenderer(std::unique_ptr<os::GraphicsOperations> graphicsOps); 44 45 bool initialize(); 46 47 void flip(); 48 49 void shutdown(); 50 51 private: 52 static constexpr uint32_t MAX_FRAMES_IN_FLIGHT = 2; 53 54 bool initDisplayDevice(); 55 56 bool initializeInstance(); 57 58 bool initializeSurface(); 59 60 bool pickPhysicalDevice(PhysicalDeviceValues& deviceValues); 61 62 bool createLogicalDevice(PhysicalDeviceValues& deviceValues); 63 64 bool createSwapChain(PhysicalDeviceValues& deviceValues); 65 66 vk::UniqueShaderModule loadShader(const SCP_string& name); 67 68 void createGraphicsPipeline(); 69 70 void createRenderPass(); 71 72 void createFrameBuffers(); 73 74 void createCommandPool(const PhysicalDeviceValues& values); 75 76 void createPresentSyncObjects(); 77 78 void drawScene(vk::Framebuffer destinationFb, vk::CommandBuffer cmdBuffer); 79 80 void acquireNextSwapChainImage(); 81 82 std::unique_ptr<os::GraphicsOperations> m_graphicsOps; 83 84 vk::UniqueInstance m_vkInstance; 85 vk::UniqueDebugReportCallbackEXT m_debugReport; 86 87 vk::UniqueSurfaceKHR m_vkSurface; 88 89 vk::UniqueDevice m_device; 90 91 vk::Queue m_graphicsQueue; 92 vk::Queue m_transferQueue; 93 vk::Queue m_presentQueue; 94 95 vk::UniqueSwapchainKHR m_swapChain; 96 vk::Format m_swapChainImageFormat; 97 vk::Extent2D m_swapChainExtent; 98 SCP_vector<vk::Image> m_swapChainImages; 99 SCP_vector<vk::UniqueImageView> m_swapChainImageViews; 100 SCP_vector<vk::UniqueFramebuffer> m_swapChainFramebuffers; 101 SCP_vector<RenderFrame*> m_swapChainImageRenderImage; 102 103 uint32_t m_currentSwapChainImage = 0; 104 105 vk::UniqueRenderPass m_renderPass; 106 vk::UniquePipelineLayout m_pipelineLayout; 107 vk::UniquePipeline m_graphicsPipeline; 108 109 uint32_t m_currentFrame = 0; 110 std::array<std::unique_ptr<RenderFrame>, MAX_FRAMES_IN_FLIGHT> m_frames; 111 112 vk::UniqueCommandPool m_graphicsCommandPool; 113 114 #if SDL_SUPPORTS_VULKAN 115 bool m_debugReportEnabled = false; 116 #endif 117 }; 118 119 } // namespace vulkan 120 } // namespace graphics 121