sandbox
Loading...
Searching...
No Matches
frustum_culling_task.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_MODELS_FRUSTUM_CULLING_TASK_HPP_
3#define LIBSBX_MODELS_FRUSTUM_CULLING_TASK_HPP_
4
5#include <cstdint>
6#include <array>
7#include <optional>
8#include <vector>
9#include <filesystem>
10#include <unordered_map>
11
12#include <vulkan/vulkan.h>
13
14#include <easy/profiler.h>
15
16#include <magic_enum/magic_enum.hpp>
17
18#include <libsbx/math/vector3.hpp>
19#include <libsbx/math/vector4.hpp>
20#include <libsbx/math/matrix4x4.hpp>
21
22#include <libsbx/core/engine.hpp>
23
24#include <libsbx/graphics/task.hpp>
25#include <libsbx/graphics/graphics_module.hpp>
26#include <libsbx/graphics/commands/command_buffer.hpp>
27#include <libsbx/graphics/buffers/storage_buffer.hpp>
28#include <libsbx/graphics/buffers/push_handler.hpp>
29#include <libsbx/graphics/pipeline/compute_pipeline.hpp>
30#include <libsbx/graphics/render_pass/swapchain.hpp>
31
32#include <libsbx/assets/assets_module.hpp>
33
34#include <libsbx/scenes/scenes_module.hpp>
35#include <libsbx/scenes/scene.hpp>
36#include <libsbx/scenes/components/camera.hpp>
37
38#include <libsbx/models/mesh.hpp>
39#include <libsbx/models/material.hpp>
40#include <libsbx/models/material_draw_list.hpp>
41#include <libsbx/models/static_mesh_material_draw_list.hpp>
42
43namespace sbx::models {
44
45struct local_aabb {
46 math::vector4f center; // xyz = center, w = pad
47 math::vector4f extents; // xyz = half-extents, w = pad
48}; // struct local_aabb
49
51 std::array<math::vector4f, 6> planes;
52}; // struct frustum_planes
53
55
56 inline static constexpr auto default_pipeline_path = std::string_view{"engine://shaders/frustum_culling"};
57
58public:
59
60 static constexpr auto no_cascade = std::uint32_t{0xFFFFFFFF};
61
63 graphics::storage_buffer_handle commands_buffer;
64 graphics::storage_buffer_handle instances_buffer;
65 }; // struct culled_range_view
66
67 frustum_culling_task(const std::filesystem::path& path = default_pipeline_path);
68
69 ~frustum_culling_task() override;
70
71 auto execute(graphics::command_buffer& command_buffer) -> void override;
72
73 auto culled(bucket bucket, const material_key& key, std::uint32_t cascade = no_cascade) const -> std::optional<culled_range_view>;
74
75 auto set_debug_view_projection(const math::matrix4x4& vp) -> void {
76 _debug_view_projection = vp;
77 }
78
79 auto clear_debug_view_projection() -> void {
80 _debug_view_projection.reset();
81 }
82
83private:
84
85 static constexpr auto ring_size = graphics::swapchain::max_frames_in_flight;
86
87 struct prefix_sum_result {
88 std::vector<std::uint32_t> prefix_sum;
89 std::uint32_t total_instances;
90 }; // struct prefix_sum_result
91
92 struct culled_range_key {
93 models::bucket bucket;
94 models::material_key key;
95 std::uint32_t cascade;
96
97 auto operator==(const culled_range_key& other) const -> bool = default;
98 }; // struct culled_range_key
99
100 struct culled_range_key_hash {
101 auto operator()(const culled_range_key& key) const -> std::size_t {
102 auto seed = std::size_t{0};
103
104 utility::hash_combine(seed, key.bucket, key.key, key.cascade);
105
106 return seed;
107 }
108 }; // struct culled_range_key_hash
109
110 struct culled_range_data {
111 std::array<graphics::storage_buffer_handle, ring_size> commands_buffers;
112 std::array<graphics::storage_buffer_handle, ring_size> instances_buffers;
113 }; // struct culled_range_data
114
115 struct cull_job {
116 graphics::storage_buffer_handle input_commands;
117 graphics::storage_buffer_handle input_instances;
118 graphics::storage_buffer_handle output_commands;
119 graphics::storage_buffer_handle output_instances;
120 graphics::buffer::address_type transforms_address;
121 std::uint32_t bounds_offset_bytes;
122 std::uint32_t prefix_offset_bytes;
123 std::uint32_t frustum_offset_bytes;
124 std::uint32_t command_count;
125 std::uint32_t instance_count;
126 }; // struct cull_job
127
128 static auto _extract_frustum_planes(const math::matrix4x4f& view_projection) -> frustum_planes;
129
130 auto _get_or_create_culled_range(const culled_range_key& key, VkDeviceSize commands_size, VkDeviceSize instances_size) -> culled_range_data&;
131
132 auto _build_bounds(const static_mesh_material_draw_list::bucket_entry& entry) -> std::vector<local_aabb>;
133
134 auto _build_prefix_sum(const static_mesh_material_draw_list::bucket_entry& entry) -> prefix_sum_result;
135
136 auto _collect_bucket(bucket current_bucket, std::uint32_t cascade, std::uint32_t frustum_index, static_mesh_material_draw_list& draw_list, std::vector<local_aabb>& bounds, std::vector<std::uint32_t>& prefix_sums, std::vector<cull_job>& jobs) -> void;
137
138 std::unordered_map<culled_range_key, culled_range_data, culled_range_key_hash> _culled_ranges;
139
140 std::array<graphics::storage_buffer_handle, ring_size> _bounds_buffers;
141 std::array<graphics::storage_buffer_handle, ring_size> _prefix_sum_buffers;
142 std::array<graphics::storage_buffer_handle, ring_size> _frustum_buffers;
143
144 graphics::compute_pipeline _pipeline;
145 graphics::push_handler _push_handler;
146
147 std::optional<math::matrix4x4> _debug_view_projection;
148
149}; // class frustum_culling_task
150
151} // namespace sbx::models
152
153#endif // LIBSBX_MODELS_FRUSTUM_CULLING_TASK_HPP_
Definition: command_buffer.hpp:15
Definition: resource_storage.hpp:18
Definition: task.hpp:9
Definition: matrix4x4.hpp:26
Definition: vector4.hpp:24
Definition: frustum_culling_task.hpp:54
Definition: frustum_culling_task.hpp:62
Definition: frustum_culling_task.hpp:50
Definition: frustum_culling_task.hpp:45
Definition: material.hpp:87