sandbox
Loading...
Searching...
No Matches
particle_task.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_PARTICLES_PARTICLE_TASK_HPP_
3#define LIBSBX_PARTICLES_PARTICLE_TASK_HPP_
4
5#include <cstdint>
6#include <filesystem>
7#include <unordered_map>
8
9#include <vulkan/vulkan.h>
10
11#include <libsbx/memory/tracking_allocator.hpp>
12
13#include <libsbx/core/engine.hpp>
14
15#include <libsbx/graphics/task.hpp>
16#include <libsbx/graphics/graphics_module.hpp>
17#include <libsbx/graphics/commands/command_buffer.hpp>
18
19#include <libsbx/graphics/buffers/storage_buffer.hpp>
20#include <libsbx/graphics/buffers/push_handler.hpp>
21
22#include <libsbx/graphics/descriptor/descriptor_handler.hpp>
23
24#include <libsbx/graphics/pipeline/compute_pipeline.hpp>
25
26#include <libsbx/scenes/scene.hpp>
27
28#include <libsbx/particles/particle_emitter.hpp>
29
30namespace sbx::particles {
31
32class particle_task final : public graphics::task {
33
34 inline static constexpr auto default_pipeline_path = std::string_view{"engine://shaders/particles"};
35
36public:
37
38 particle_task(const std::filesystem::path& path = default_pipeline_path);
39
40 ~particle_task() override = default;
41
42 auto execute(graphics::command_buffer& command_buffer) -> void override;
43
44 auto remove_emitter(scenes::node node) -> void;
45
46 [[nodiscard]] auto particle_buffer(scenes::node node) const -> graphics::storage_buffer_handle;
47
48 [[nodiscard]] auto alive_list_buffer(scenes::node node) const -> graphics::storage_buffer_handle;
49
50 [[nodiscard]] auto indirect_buffer(scenes::node node) const -> graphics::storage_buffer_handle;
51
52private:
53
54 struct alignas(16) emitter_params {
55 math::color initial_color;
56 math::color end_color;
57 math::vector3 emitter_position;
58 std::float_t delta_time;
59 math::vector3 emission_shape_min;
60 std::float_t emission_rate;
61 math::vector3 emission_shape_max;
62 std::float_t time;
63 math::vector3 gravity;
64 std::float_t drag;
65 math::vector2 initial_speed;
66 math::vector2 initial_lifetime;
67 math::vector2 initial_size;
68 math::vector2 initial_rotation;
69 std::float_t end_size_scale;
70 std::uint32_t max_particles;
71 std::uint32_t emit_count;
72 std::uint32_t random_seed;
73 std::uint32_t texture_count;
74 std::uint32_t _pad0;
75 std::uint32_t _pad1;
76 std::uint32_t _pad2;
77 }; // struct emitter_params
78
79 static_assert(alignof(emitter_params) == 16u);
80 static_assert(sizeof(emitter_params) % 16u == 0u);
81
82 struct emitter_gpu_data {
83 // Buffers
84 graphics::storage_buffer_handle particle_buffer;
86 graphics::storage_buffer_handle alive_list_buffer;
87 graphics::storage_buffer_handle indirect_buffer;
88
89 // Descriptors
90 graphics::descriptor_handler reset_descriptor;
91 graphics::descriptor_handler clear_descriptor;
92 graphics::descriptor_handler emit_descriptor;
93 graphics::descriptor_handler simulate_descriptor;
94 graphics::descriptor_handler prepare_indirect_descriptor;
95
96 // State
97 bool reset_requested{true};
98
99 emitter_gpu_data(graphics::compute_pipeline& reset_pipeline, graphics::compute_pipeline& clear_pipeline, graphics::compute_pipeline& emit_pipeline, graphics::compute_pipeline& simulate_pipeline, graphics::compute_pipeline& prepare_indirect_pipeline)
100 : reset_descriptor{reset_pipeline, 0u},
101 clear_descriptor{clear_pipeline, 0u},
102 emit_descriptor{emit_pipeline, 0u},
103 simulate_descriptor{simulate_pipeline, 0u},
104 prepare_indirect_descriptor{prepare_indirect_pipeline, 0u} { }
105
106 }; // struct emitter_gpu_data
107
108 auto _get_or_create_gpu_data(scenes::node node, const particle_emitter& emitter) -> emitter_gpu_data&;
109
110 auto _initialize_buffers(emitter_gpu_data& gpu_data, const particle_emitter& emitter) -> void;
111
112 auto _build_emitter_params(const particle_emitter& emitter, const math::vector3& position, std::uint32_t emit_count, std::float_t delta_time) -> emitter_params;
113
114 auto _dispatch_reset(graphics::command_buffer& command_buffer, emitter_gpu_data& gpu_data) -> void;
115
116 auto _dispatch_clear(graphics::command_buffer& command_buffer, emitter_gpu_data& gpu_data, const emitter_params& params) -> void;
117
118 auto _dispatch_emit(graphics::command_buffer& command_buffer, emitter_gpu_data& gpu_data, const emitter_params& params) -> void;
119
120 auto _dispatch_simulate(graphics::command_buffer& command_buffer, emitter_gpu_data& gpu_data, const emitter_params& params) -> void;
121
122 auto _dispatch_prepare_indirect(graphics::command_buffer& command_buffer, emitter_gpu_data& gpu_data) -> void;
123
124 static auto _barrier_compute_to_compute(graphics::command_buffer& command_buffer) -> void;
125
126 static auto _barrier_compute_to_draw(graphics::command_buffer& command_buffer) -> void;
127
128 // Pipelines
129 graphics::compute_pipeline _reset_pipeline;
130 graphics::compute_pipeline _clear_pipeline;
131 graphics::compute_pipeline _emit_pipeline;
132 graphics::compute_pipeline _simulate_pipeline;
133 graphics::compute_pipeline _prepare_indirect_pipeline;
134
135 // Push handlers
136 graphics::push_handler _clear_push_handler;
137 graphics::push_handler _emit_push_handler;
138 graphics::push_handler _simulate_push_handler;
139
140 // Per-emitter GPU data
141 std::unordered_map<scenes::node, emitter_gpu_data> _emitter_gpu_data;
142
143 std::uint32_t _frame_seed{0};
144
145}; // class particle_task
146
147} // namespace sbx::particles
148
149#endif // LIBSBX_PARTICLES_PARTICLE_TASK_HPP_
Definition: tests.cpp:6
Definition: command_buffer.hpp:15
Definition: compute_pipeline.hpp:18
Definition: descriptor_handler.hpp:26
Definition: push_handler.hpp:18
Definition: resource_storage.hpp:18
Definition: task.hpp:9
A vector in two-dimensional space.
Definition: vector2.hpp:28
Definition: vector3.hpp:23
RGBA color value type.
Definition: color.hpp:48
Definition: particle_task.hpp:32
Definition: particle_emitter.hpp:23