PixelBullet  0.0.1
A C++ game engine
Loading...
Searching...
No Matches
graphics.h
1#pragma once
2
3#include "pixelbullet/graphics/renderer.h"
4#include "pixelbullet/time/elapsed.h"
5
6#include <volk.h>
7
8#include <filesystem>
9#include <map>
10#include <memory>
11#include <mutex>
12#include <string>
13#include <thread>
14#include <vector>
15
16namespace pixelbullet
17{
18struct ApplicationSpecification;
19class CommandPool;
20class RenderStage;
21class Descriptor;
22class PhysicalDevice;
23class LogicalDevice;
24class Swapchain;
25class CommandBuffer;
26class Instance;
27class RenderTarget2D;
28class Surface;
29class Window;
30
35{
36public:
37 enum class PrepareFrameOutcome
38 {
39 Skipped,
40 Rebuilt,
41 Ready
42 };
43
44 enum class RenderFrameOutcome
45 {
46 Skipped,
47 Rendered
48 };
49
50 enum class FrameOutcome
51 {
52 Skipped,
53 Rebuilt,
54 Rendered
55 };
56
57 Graphics(const ApplicationSpecification& specification, Window& window);
58 ~Graphics();
59
60 PrepareFrameOutcome PrepareFrame();
61 RenderFrameOutcome RenderPreparedFrame();
62 FrameOutcome Update();
63
64 static std::string StringifyResultVk(VkResult result);
65 static void CheckVk(VkResult result);
66
71 void CaptureScreenshot(const std::filesystem::path& filename, std::size_t id = 0) const;
72
73 std::shared_ptr<CommandPool> GetCommandPool(VkQueueFlagBits queueType = VK_QUEUE_GRAPHICS_BIT,
74 const std::thread::id& threadId = std::this_thread::get_id()) const;
75
81 {
82 return renderer_.get();
83 }
84
89 void SetRenderer(std::unique_ptr<Renderer>&& renderer);
90
91 const RenderStage* GetRenderStage(uint32_t index) const;
92
93 const Descriptor* GetAttachment(const std::string& name) const;
94 const RenderTarget2D* GetRenderTarget(const std::string& name) const;
95
96 const PhysicalDevice* GetPhysicalDevice() const
97 {
98 return physical_device_.get();
99 }
100 const LogicalDevice* GetLogicalDevice() const
101 {
102 return logical_device_.get();
103 }
104 const VkPipelineCache& GetPipelineCache() const
105 {
106 return pipeline_cache_;
107 }
108
109 const Surface* GetSurface(std::size_t id) const
110 {
111 return surfaces_[id].get();
112 }
113 const Swapchain* GetSwapchain(std::size_t id) const
114 {
115 return swapchains_[id].get();
116 }
117 bool HasSwapchain(std::size_t id) const
118 {
119 return id < swapchains_.size() && static_cast<bool>(swapchains_[id]);
120 }
121 bool HasPreparedFrame() const
122 {
123 return prepared_frame_ready_;
124 }
125 uint32_t GetPreparedImageIndex(std::size_t id) const
126 {
127 ASSERT(prepared_frame_ready_ && HasSwapchain(id), "No prepared swapchain image is available");
128 return swapchains_[id]->GetActiveImageIndex();
129 }
130 void SetFramebufferResized(std::size_t id)
131 {
132 per_surface_buffers_[id]->framebuffer_resized = true;
133 }
134
135 const Instance* GetInstance() const
136 {
137 return instance_.get();
138 }
139 const Window& GetWindow() const
140 {
141 return window_;
142 }
143 Window& GetWindow()
144 {
145 return window_;
146 }
147
148private:
149 void CreatePipelineCache();
150 void ResetRenderStages();
151 void RebuildRenderStages(bool recreateSwapchain);
152 void RecreateSwapchain();
153 void RecreateCommandBuffers(std::size_t id);
154 void RebuildRenderTargets();
155 void RecreateAttachmentsMap();
156 void StartRenderpass(std::size_t id, RenderStage& renderStage);
157 bool EndRenderpass(std::size_t id, RenderStage& renderStage);
158
159private:
160 const ApplicationSpecification& specification_;
161 Window& window_;
162 std::unique_ptr<Renderer> renderer_;
163 std::map<std::string, const Descriptor*> attachments_;
164 std::map<std::string, std::unique_ptr<RenderTarget2D>> render_targets_;
165 std::vector<std::unique_ptr<Swapchain>> swapchains_;
166 bool prepared_frame_ready_ = false;
167
168 using CommandPoolKey = std::pair<std::thread::id, VkQueueFlagBits>;
169
170 mutable std::map<CommandPoolKey, std::shared_ptr<CommandPool>> command_pools_;
171 mutable std::mutex command_pools_mutex_;
173 Elapsed elapsed_purge_;
174
175 struct PerSurfaceBuffers
176 {
177 std::vector<VkSemaphore> present_completes;
178 std::vector<VkSemaphore> render_completes;
179 std::vector<VkFence> flight_fences;
180 std::vector<VkFence> image_fences;
181 std::size_t current_frame = 0;
182 bool framebuffer_resized = false;
183
184 std::vector<std::unique_ptr<CommandBuffer>> command_buffers;
185 };
186 std::vector<std::unique_ptr<PerSurfaceBuffers>> per_surface_buffers_;
187
188 std::unique_ptr<Instance> instance_;
189 std::unique_ptr<PhysicalDevice> physical_device_;
190 std::unique_ptr<LogicalDevice> logical_device_;
191 VkPipelineCache pipeline_cache_ = VK_NULL_HANDLE;
192 std::vector<std::unique_ptr<Surface>> surfaces_;
193};
194} // namespace pixelbullet
#define ASSERT(condition,...)
Asserts that a condition is true.
Definition assert.h:163
Definition descriptor.h:75
Module that manages the Vulkan instance_, Surface, Window and the renderpass structure.
Definition graphics.h:35
void CaptureScreenshot(const std::filesystem::path &filename, std::size_t id=0) const
Definition graphics.cc:259
Renderer * GetRenderer() const
Definition graphics.h:80
void SetRenderer(std::unique_ptr< Renderer > &&renderer)
Definition graphics.cc:313
Definition physical_device.h:12
Definition render_stage.h:209
Definition render_target.h:38
Class used to manage Subrender objects to create a list of render pass.
Definition renderer.h:13
Definition window.h:23
Contains configuration options for both the game and the engine.
Definition specification.h:145