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