deferred_renderer.hpp 8.37 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
#pragma once

#include <mirrage/renderer/camera_comp.hpp>
#include <mirrage/renderer/gbuffer.hpp>
#include <mirrage/renderer/model.hpp>

#include <mirrage/graphic/context.hpp>
#include <mirrage/graphic/device.hpp>
#include <mirrage/graphic/profiler.hpp>

11
12
#include <mirrage/utils/math.hpp>

13
14
15
#include <vulkan/vulkan.hpp>


16
namespace mirrage {
17
18
19
20
	namespace ecs {
		class Entity_manager;
	}
	class Meta_system;
21
} // namespace mirrage
22

23
namespace mirrage::renderer {
24
25
26
27

	class Deferred_renderer_factory;
	class Deferred_renderer;

28

29
	struct Renderer_settings {
30
		int shadowmap_resolution = 2048;
Florian Oetke's avatar
Florian Oetke committed
31
32
		int shadow_quality       = 99; // 0 = lowest

33
34
35
36
37
38
39
40
		bool  gi                        = true;
		bool  gi_highres                = true;
		int   gi_diffuse_mip_level      = 1;
		int   gi_min_mip_level          = 0;
		int   gi_samples                = 128;
		bool  gi_jitter_samples         = false;
		int   gi_low_quality_mip_levels = 0;
		float exposure_override         = 0.f;
Florian Oetke's avatar
Florian Oetke committed
41

42
43
44
45
		bool ssao  = true;
		bool bloom = true;

		float background_intensity = 1.f;
46

47
		bool dynamic_shadows = false;
48
49
		bool debug_disect    = false;
		int  debug_gi_layer  = -1;
50
	};
51

52
#ifdef sf2_structDef
53
54
55
56
57
58
	sf2_structDef(Renderer_settings,
	              shadowmap_resolution,
	              shadow_quality,
	              gi,
	              dynamic_shadows,
	              debug_gi_layer);
59
60
61
62
63
64
65
66
67
68
#endif

	struct Global_uniforms {
		glm::mat4 view_proj_mat;
		glm::mat4 view_mat;
		glm::mat4 proj_mat;
		glm::mat4 inv_view_mat;
		glm::mat4 inv_proj_mat;
		glm::vec4 eye_pos;
		glm::vec4 proj_planes; //< near, far, fov horizontal, fov vertical
69
		glm::vec4 time;        //< time, sin(time), delta_time
70
		glm::vec4 proj_info;
71
72
73
74
75
	};

	using Command_buffer_source = std::function<vk::CommandBuffer()>;

	class Pass {
76
77
	  public:
		virtual ~Pass() = default;
78

79
		virtual void update(util::Time dt)             = 0;
80
81
82
83
		virtual void draw(vk::CommandBuffer&,
		                  Command_buffer_source&,
		                  vk::DescriptorSet global_uniform_set,
		                  std::size_t       swapchain_image) = 0;
84

85
86
		virtual void shrink_to_fit() {}
		virtual void process_camera(Camera_state&) {} //< allows passes to modify the current camera
87

88
		virtual auto name() const noexcept -> const char* = 0;
89
90
91
	};

	class Pass_factory {
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
	  public:
		virtual ~Pass_factory() = default;

		virtual auto create_pass(Deferred_renderer&,
		                         ecs::Entity_manager&,
		                         util::maybe<Meta_system&>,
		                         bool& write_first_pp_buffer) -> std::unique_ptr<Pass> = 0;

		virtual auto rank_device(vk::PhysicalDevice,
		                         util::maybe<std::uint32_t> graphics_queue,
		                         int                        current_score) -> int {
			return current_score;
		}

		virtual void configure_device(vk::PhysicalDevice,
		                              util::maybe<std::uint32_t> graphics_queue,
		                              graphic::Device_create_info&) {}
109
110
	};

111
	template <class T, class... Args>
112
113
114
115
116
117
118
	auto make_pass_factory(Args&&... args) {
		return std::unique_ptr<Pass_factory>(new T(std::forward<Args>(args)...));
	}


	// shared among all Deferred_renderers in all screens
	class Deferred_renderer_factory {
119
120
121
122
123
124
125
126
127
128
129
130
131
132
	  public:
		Deferred_renderer_factory(graphic::Context&,
		                          graphic::Window& window,
		                          std::vector<std::unique_ptr<Pass_factory>>);

		auto create_renderer(ecs::Entity_manager&, util::maybe<Meta_system&>)
		        -> std::unique_ptr<Deferred_renderer>;

		void queue_commands(vk::CommandBuffer);
		auto queue_temporary_command_buffer() -> vk::CommandBuffer;

		void finish_frame();

		auto settings() const -> auto& { return *_settings; }
Florian Oetke's avatar
Florian Oetke committed
133
134
		void settings(const Renderer_settings& s, bool apply = true);
		void save_settings();
135
136
137
138
139
140

	  private:
		friend class Deferred_renderer;
		using Pass_factories = std::vector<std::unique_ptr<Pass_factory>>;
		using Settings_ptr   = std::shared_ptr<const Renderer_settings>;

Florian Oetke's avatar
Florian Oetke committed
141
142
143
144
		Settings_ptr                    _settings;
		Pass_factories                  _pass_factories;
		graphic::Window&                _window;
		graphic::Device_ptr             _device;
145
		graphic::Swapchain&             _swapchain;
Florian Oetke's avatar
Florian Oetke committed
146
147
148
149
150
151
152
153
154
		std::uint32_t                   _queue_family;
		vk::Queue                       _queue;
		vk::UniqueSemaphore             _image_acquired;
		vk::UniqueSemaphore             _image_presented;
		graphic::Command_buffer_pool    _command_buffer_pool;
		util::maybe<std::size_t>        _aquired_swapchain_image;
		std::vector<vk::CommandBuffer>  _queued_commands;
		std::vector<Deferred_renderer*> _renderer_instances;
		bool                            _recreation_pending = false;
155

156
		void _present();
157
158
159
160
161
		auto _rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t> gqueue) -> int;
		auto _init_device(vk::PhysicalDevice, util::maybe<std::uint32_t> gqueue)
		        -> graphic::Device_create_info;

		auto _aquire_next_image() -> std::size_t;
162
163
164
	};

	class Deferred_renderer {
165
166
167
168
169
	  public:
		Deferred_renderer(Deferred_renderer_factory&,
		                  std::vector<std::unique_ptr<Pass_factory>>&,
		                  ecs::Entity_manager&,
		                  util::maybe<Meta_system&>);
Florian Oetke's avatar
Florian Oetke committed
170
171
		Deferred_renderer(const Deferred_renderer&) = delete;
		auto operator=(const Deferred_renderer&) -> Deferred_renderer& = delete;
172
		~Deferred_renderer();
173

Florian Oetke's avatar
Florian Oetke committed
174
175
		void recreate();

176
		template <class T>
Florian Oetke's avatar
Florian Oetke committed
177
		auto find_pass() -> util::tracking_ptr<T> {
178
179
180
			auto pass = std::find_if(_passes.begin(), _passes.end(), [](auto& p) {
				return dynamic_cast<T*>(&*p) != nullptr;
			});
181

Florian Oetke's avatar
Florian Oetke committed
182
183
			return pass != _passes.end() ? util::tracking_ptr<T>(pass->create_ptr())
			                             : util::tracking_ptr<T>{};
184
185
186
187
188
189
190
		}

		void update(util::Time dt);
		void draw();

		void shrink_to_fit();

Florian Oetke's avatar
Florian Oetke committed
191
192
		auto texture_cache() -> auto& { return *_texture_cache; }
		auto model_loader() -> auto& { return *_model_loader; }
193

Florian Oetke's avatar
Florian Oetke committed
194
195
		auto gbuffer() noexcept -> auto& { return *_gbuffer; }
		auto gbuffer() const noexcept -> auto& { return *_gbuffer; }
196
		auto global_uniforms() const noexcept -> auto& { return _global_uniforms; }
197
198
199
		auto global_uniforms_layout() const noexcept {
			return *_global_uniform_descriptor_set_layout;
		}
200

Florian Oetke's avatar
Florian Oetke committed
201
202
203
204
		auto device() noexcept -> auto& { return *_factory->_device; }
		auto window() noexcept -> auto& { return _factory->_window; }
		auto swapchain() noexcept -> auto& { return _factory->_swapchain; }
		auto queue_family() const noexcept { return _factory->_queue_family; }
205
206
207
208

		auto create_descriptor_set(vk::DescriptorSetLayout) -> vk::UniqueDescriptorSet;
		auto descriptor_pool() noexcept -> auto& { return _descriptor_set_pool; }

209
210
211
		auto noise_descriptor_set_layout() const noexcept { return *_noise_descriptor_set_layout; }
		auto noise_descriptor_set() const noexcept { return *_noise_descriptor_set; }

212
213
		auto active_camera() noexcept -> util::maybe<Camera_state&>;

Florian Oetke's avatar
Florian Oetke committed
214
215
		auto settings() const -> auto& { return _factory->settings(); }
		void save_settings() { _factory->save_settings(); }
216
217
218
		void settings(const Renderer_settings& s, bool apply = true) {
			_factory->settings(s, apply);
		}
Florian Oetke's avatar
Florian Oetke committed
219

220
221
222
223
224

		auto profiler() const noexcept -> auto& { return _profiler; }
		auto profiler() noexcept -> auto& { return _profiler; }

	  private:
225
226
		friend class Deferred_renderer_factory;

Florian Oetke's avatar
Florian Oetke committed
227
228
229
		Deferred_renderer_factory* _factory;
		ecs::Entity_manager*       _entity_manager;
		util::maybe<Meta_system&>  _meta_system;
230
231
		graphic::Descriptor_pool   _descriptor_set_pool;

Florian Oetke's avatar
Florian Oetke committed
232
233
234
		std::unique_ptr<GBuffer> _gbuffer;
		Global_uniforms          _global_uniforms;
		graphic::Profiler        _profiler;
235
236
237
		float                    _time_acc      = 0.f;
		float                    _delta_time    = 0.f;
		std::uint32_t            _frame_counter = 0;
238

Florian Oetke's avatar
Florian Oetke committed
239
240
		std::unique_ptr<graphic::Texture_cache> _texture_cache;
		std::unique_ptr<Model_loader>           _model_loader;
241
242
243
244
245

		vk::UniqueDescriptorSetLayout _global_uniform_descriptor_set_layout;
		vk::UniqueDescriptorSet       _global_uniform_descriptor_set;
		graphic::Dynamic_buffer       _global_uniform_buffer;

246
247
248
249
250
		graphic::Texture_ptr                 _blue_noise;
		vk::UniqueSampler                    _noise_sampler;
		graphic::Image_descriptor_set_layout _noise_descriptor_set_layout;
		vk::UniqueDescriptorSet              _noise_descriptor_set;

Florian Oetke's avatar
Florian Oetke committed
251
		std::vector<util::trackable<Pass>> _passes;
252

Florian Oetke's avatar
Florian Oetke committed
253
		Camera_comp::Pool*        _cameras;
254
255
256
257
258
		util::maybe<Camera_state> _active_camera;

		void _write_global_uniform_descriptor_set();
		void _update_global_uniforms(vk::CommandBuffer, const Camera_state& camera);
	};
259
} // namespace mirrage::renderer