deferred_renderer.hpp 11.2 KB
Newer Older
1
2
3
4
5
#pragma once

#include <mirrage/renderer/camera_comp.hpp>
#include <mirrage/renderer/gbuffer.hpp>
#include <mirrage/renderer/model.hpp>
6
#include <mirrage/renderer/render_pass.hpp>
7
8
9
10
11

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

12
#include <mirrage/utils/min_max.hpp>
13
#include <mirrage/utils/small_vector.hpp>
14

15
16
#include <glm/gtx/quaternion.hpp>
#include <glm/vec3.hpp>
17
18
19
#include <vulkan/vulkan.hpp>


20
namespace mirrage {
21
22
23
	namespace ecs {
		class Entity_manager;
	}
24
	class Engine;
25
} // namespace mirrage
26

27
namespace mirrage::renderer {
28
29
30
31

	class Deferred_renderer_factory;
	class Deferred_renderer;

32

33
	struct Renderer_settings {
34
		int shadowmap_resolution = 2048;
Florian Oetke's avatar
Florian Oetke committed
35
36
		int shadow_quality       = 99; // 0 = lowest

37
38
		bool gi                        = true;
		bool gi_highres                = true;
Florian Oetke's avatar
Florian Oetke committed
39
		bool gi_shadows                = false;
40
41
		int  gi_diffuse_mip_level      = 1;
		int  gi_min_mip_level          = 0;
42
		int  gi_samples                = 64;
43
		int  gi_lowres_samples         = 128;
44
45
		int  gi_low_quality_mip_levels = 0;

46
47
48
49
50
		bool  tonemapping                 = true;
		float exposure_override           = 0.f;
		float scene_luminance_override    = -1.f;
		float exposure_luminance_override = -1.f;
		float scotopic_sim_weight         = 1.f;
51
52
		float min_display_luminance       = 40.f;
		float max_display_luminance       = 200.0f;
53
		float amient_light_intensity      = 0.05f;
Florian Oetke's avatar
Florian Oetke committed
54

55
		int  transparent_particle_mip_level = 0;
Florian Oetke's avatar
Florian Oetke committed
56
		bool particle_fragment_shadows      = true;
57

58
59
60
61
62
63
		bool         taa            = true;
		bool         ssao           = true;
		bool         bloom          = true;
		bool         depth_of_field = true;
		bool         particles      = true;
		std::int32_t max_particles  = 1'000'000;
64

65
		float background_intensity = 0.f;
66

67
68
69
70
		bool shadows          = true;
		bool dynamic_lighting = true;
		int  debug_gi_layer   = -1;
		bool debug_geometry   = true;
71
	};
72

73
#ifdef sf2_structDef
74
75
76
77
78
79
80
81
82
83
	sf2_structDef(Renderer_settings,
	              shadowmap_resolution,
	              shadow_quality,
	              gi,
	              gi_highres,
	              gi_shadows,
	              gi_diffuse_mip_level,
	              gi_low_quality_mip_levels,
	              min_display_luminance,
	              max_display_luminance,
84
	              amient_light_intensity,
85
	              transparent_particle_mip_level,
Florian Oetke's avatar
Florian Oetke committed
86
	              particle_fragment_shadows,
87
88
89
	              taa,
	              ssao,
	              bloom,
Florian Oetke's avatar
Florian Oetke committed
90
	              depth_of_field,
91
92
	              particles,
	              max_particles,
93
94
95
	              shadows,
	              dynamic_lighting,
	              debug_geometry);
96
97
98
99
100
101
102
103
104
105
#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
106
		glm::vec4 time;        //< time, sin(time), delta_time
107
		glm::vec4 proj_info;
108
109
110
	};


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

117
	using Render_pass_mask = std::vector<Render_pass_id>; // util::small_vector<Render_pass_id, 32>;
118
119
120

	// shared among all Deferred_renderers in all screens
	class Deferred_renderer_factory {
121
	  public:
122
123
124
		Deferred_renderer_factory(Engine&          engine,
		                          graphic::Window& window,
		                          std::vector<std::unique_ptr<Render_pass_factory>>);
125
		~Deferred_renderer_factory();
126

127
128
129
130
		auto create_renderer(util::maybe<ecs::Entity_manager&> = util::nothing,
		                     Render_pass_mask = Render_pass_mask{}) -> std::unique_ptr<Deferred_renderer>;

		template <class... Passes>
Florian Oetke's avatar
Florian Oetke committed
131
		auto create_renderer(util::maybe<ecs::Entity_manager&> ecs = util::nothing)
132
133
		        -> std::unique_ptr<Deferred_renderer>
		{
Florian Oetke's avatar
Florian Oetke committed
134
			return create_renderer(ecs, Render_pass_mask{render_pass_id_of<Passes>()...});
135
136
137
		}

		auto all_passes_mask() const noexcept -> auto& { return _all_passes_mask; }
138
139
140
141

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

Florian Oetke's avatar
Florian Oetke committed
142
143
		auto create_compute_command_buffer() -> vk::UniqueCommandBuffer;

144
145
146
		auto model_material_sampler() const noexcept { return *_model_material_sampler; }
		auto model_descriptor_set_layout() const noexcept { return *_model_desc_set_layout; }

Florian Oetke's avatar
Florian Oetke committed
147
148
		auto compute_queue() const noexcept { return _compute_queue; }

149
150
151
		void finish_frame();

		auto settings() const -> auto& { return *_settings; }
Florian Oetke's avatar
Florian Oetke committed
152
153
		void settings(const Renderer_settings& s, bool apply = true);
		void save_settings();
154

155
156
157
158
159
		auto global_uniforms_layout() const noexcept { return *_global_uniform_descriptor_set_layout; }
		auto compute_storage_buffer_layout() const { return *_compute_storage_buffer_layout; }
		auto compute_uniform_buffer_layout() const { return *_compute_uniform_buffer_layout; }


160
161
	  private:
		friend class Deferred_renderer;
162
		struct Asset_loaders;
163
		using Pass_factories = std::vector<std::unique_ptr<Render_pass_factory>>;
164
		using Settings_ptr   = asset::Ptr<Renderer_settings>;
165

166
		Engine&                         _engine;
167
		asset::Asset_manager&           _assets;
Florian Oetke's avatar
Florian Oetke committed
168
169
170
171
		Settings_ptr                    _settings;
		Pass_factories                  _pass_factories;
		graphic::Window&                _window;
		graphic::Device_ptr             _device;
172
		graphic::Swapchain&             _swapchain;
Florian Oetke's avatar
Florian Oetke committed
173
174
175
176
		std::uint32_t                   _draw_queue_family;
		std::uint32_t                   _compute_queue_family;
		vk::Queue                       _draw_queue;
		vk::Queue                       _compute_queue;
Florian Oetke's avatar
Florian Oetke committed
177
178
179
		vk::UniqueSemaphore             _image_acquired;
		vk::UniqueSemaphore             _image_presented;
		graphic::Command_buffer_pool    _command_buffer_pool;
Florian Oetke's avatar
Florian Oetke committed
180
		graphic::Command_buffer_pool    _compute_command_buffer_pool;
Florian Oetke's avatar
Florian Oetke committed
181
182
183
184
		util::maybe<std::size_t>        _aquired_swapchain_image;
		std::vector<vk::CommandBuffer>  _queued_commands;
		std::vector<Deferred_renderer*> _renderer_instances;
		bool                            _recreation_pending = false;
185
186
		vk::UniqueSampler               _model_material_sampler;
		vk::UniqueDescriptorSetLayout   _model_desc_set_layout;
187
188
189
		vk::UniqueDescriptorSetLayout   _global_uniform_descriptor_set_layout;
		vk::UniqueDescriptorSetLayout   _compute_storage_buffer_layout;
		vk::UniqueDescriptorSetLayout   _compute_uniform_buffer_layout;
190
		std::unique_ptr<Asset_loaders>  _asset_loaders;
191
		Render_pass_mask                _all_passes_mask;
192

Florian Oetke's avatar
Florian Oetke committed
193
		class Profiler_menu;
194
		class Settings_menu;
Florian Oetke's avatar
Florian Oetke committed
195
		std::unique_ptr<Profiler_menu> _profiler_menu;
196
		std::unique_ptr<Settings_menu> _settings_menu;
Florian Oetke's avatar
Florian Oetke committed
197

198
		void _present();
199
200
201
202
203
		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;
204
205
	};

206

207
	class Deferred_renderer {
208
209
	  public:
		Deferred_renderer(Deferred_renderer_factory&,
210
211
		                  std::vector<Render_pass_factory*>,
		                  util::maybe<ecs::Entity_manager&>,
212
		                  Engine&);
Florian Oetke's avatar
Florian Oetke committed
213
214
		Deferred_renderer(const Deferred_renderer&) = delete;
		auto operator=(const Deferred_renderer&) -> Deferred_renderer& = delete;
215
		~Deferred_renderer();
216

Florian Oetke's avatar
Florian Oetke committed
217
218
		void recreate();

219
220
221
222
223
		void update(util::Time dt);
		void draw();

		void shrink_to_fit();

Florian Oetke's avatar
Florian Oetke committed
224
225
		auto gbuffer() noexcept -> auto& { return *_gbuffer; }
		auto gbuffer() const noexcept -> auto& { return *_gbuffer; }
226
227
		auto global_uniforms() const noexcept -> auto& { return _global_uniforms; }

228
		auto asset_manager() noexcept -> auto& { return _factory->_assets; }
Florian Oetke's avatar
Florian Oetke committed
229
230
231
		auto device() noexcept -> auto& { return *_factory->_device; }
		auto window() noexcept -> auto& { return _factory->_window; }
		auto swapchain() noexcept -> auto& { return _factory->_swapchain; }
Florian Oetke's avatar
Florian Oetke committed
232
233
234
235
236
		auto queue_family() const noexcept { return _factory->_draw_queue_family; }
		auto compute_queue_family() const noexcept { return _factory->_compute_queue_family; }

		auto compute_queue() const noexcept { return _factory->compute_queue(); }
		auto create_compute_command_buffer() { return _factory->create_compute_command_buffer(); }
237

238
		auto create_descriptor_set(vk::DescriptorSetLayout, std::int32_t bindings) -> graphic::DescriptorSet;
239
240
		auto descriptor_pool() noexcept -> auto& { return _descriptor_set_pool; }

241
242
243
		auto noise_descriptor_set_layout() const noexcept { return *_noise_descriptor_set_layout; }
		auto noise_descriptor_set() const noexcept { return *_noise_descriptor_set; }

244
245
		auto billboard_model() const noexcept -> auto& { return _billboard_model; }

246
247
248
		auto model_material_sampler() const noexcept { return _factory->model_material_sampler(); }
		auto model_descriptor_set_layout() const noexcept { return _factory->model_descriptor_set_layout(); }

249
250
251
252
		auto global_uniforms_layout() const noexcept { return _factory->global_uniforms_layout(); }
		auto compute_storage_buffer_layout() const { return _factory->compute_storage_buffer_layout(); }
		auto compute_uniform_buffer_layout() const { return _factory->compute_uniform_buffer_layout(); }

253
254
		auto active_camera() noexcept -> util::maybe<Camera_state&>;

Florian Oetke's avatar
Florian Oetke committed
255
256
		auto settings() const -> auto& { return _factory->settings(); }
		void save_settings() { _factory->save_settings(); }
257
		void settings(const Renderer_settings& s, bool apply = true) { _factory->settings(s, apply); }
Florian Oetke's avatar
Florian Oetke committed
258

259
260
261
262
263
264
265
		void debug_draw(const std::vector<Debug_geometry>& lines)
		{
			if(_factory->settings().debug_geometry) {
				auto& queue = _frame_data.debug_geometry_queue;
				queue.insert(queue.end(), lines.begin(), lines.end());
			}
		}
Florian Oetke's avatar
Florian Oetke committed
266
267
268
269
270
271
		void debug_draw(const Debug_geometry& line)
		{
			if(_factory->settings().debug_geometry) {
				_frame_data.debug_geometry_queue.emplace_back(line);
			}
		}
272
		void debug_draw_sphere(const glm::vec3& center, float radius, const util::Rgb&);
273
		auto low_level_draw_queue() -> auto& { return _frame_data.geometry_queue; }
274

275
276
277
278
279

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

	  private:
280
281
		friend class Deferred_renderer_factory;

282
283
284
285
		Engine*                           _engine;
		Deferred_renderer_factory*        _factory;
		util::maybe<ecs::Entity_manager&> _entity_manager;
		graphic::Descriptor_pool          _descriptor_set_pool;
286

Florian Oetke's avatar
Florian Oetke committed
287
288
289
		std::unique_ptr<GBuffer> _gbuffer;
		Global_uniforms          _global_uniforms;
		graphic::Profiler        _profiler;
290
291
292
		float                    _time_acc      = 0.f;
		float                    _delta_time    = 0.f;
		std::uint32_t            _frame_counter = 0;
293

294
295
		graphic::DescriptorSet  _global_uniform_descriptor_set;
		graphic::Dynamic_buffer _global_uniform_buffer;
296

297
298
299
		graphic::Texture_ptr                 _blue_noise;
		vk::UniqueSampler                    _noise_sampler;
		graphic::Image_descriptor_set_layout _noise_descriptor_set_layout;
300
		graphic::DescriptorSet               _noise_descriptor_set;
301

302
303
		Model _billboard_model;

304
		std::vector<Render_pass_factory*>         _pass_factories;
305
		std::vector<std::unique_ptr<Render_pass>> _passes;
306

307
308
309
		util::maybe<Camera_comp::Pool&> _cameras;
		util::maybe<Camera_state>       _active_camera;
		Frame_data                      _frame_data;
310
311
312
313

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