summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_scene_cull.h
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_scene_cull.h')
-rw-r--r--servers/rendering/renderer_scene_cull.h205
1 files changed, 140 insertions, 65 deletions
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 051919314e..8bf262d7c0 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -34,30 +34,25 @@
#include "core/templates/pass_func.h"
#include "servers/rendering/renderer_compositor.h"
+#include "core/math/dynamic_bvh.h"
#include "core/math/geometry_3d.h"
#include "core/math/octree.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "core/templates/local_vector.h"
+#include "core/templates/paged_allocator.h"
+#include "core/templates/paged_array.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/xr/xr_interface.h"
-
class RendererSceneCull : public RendererScene {
public:
RendererSceneRender *scene_render;
enum {
- MAX_INSTANCE_CULL = 65536,
- MAX_LIGHTS_CULLED = 4096,
- MAX_REFLECTION_PROBES_CULLED = 4096,
- MAX_DECALS_CULLED = 4096,
- MAX_GI_PROBES_CULLED = 4096,
- MAX_ROOM_CULL = 32,
- MAX_LIGHTMAPS_CULLED = 4096,
- MAX_EXTERIOR_PORTALS = 128,
+ SDFGI_MAX_CASCADES = 8
};
uint64_t render_pass;
@@ -114,11 +109,17 @@ public:
struct Instance;
struct Scenario {
+ enum IndexerType {
+ INDEXER_GEOMETRY, //for geometry
+ INDEXER_VOLUMES, //for everything else
+ INDEXER_MAX
+ };
+
+ DynamicBVH indexers[INDEXER_MAX];
+
RS::ScenarioDebugMode debug;
RID self;
- Octree<Instance, true> octree;
-
List<Instance *> directional_lights;
RID environment;
RID fallback_environment;
@@ -130,13 +131,19 @@ public:
LocalVector<RID> dynamic_lights;
- Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; }
+ Scenario() {
+ indexers[INDEXER_GEOMETRY].set_index(INDEXER_GEOMETRY);
+ indexers[INDEXER_VOLUMES].set_index(INDEXER_VOLUMES);
+ debug = RS::SCENARIO_DEBUG_DISABLED;
+ }
};
+ int indexer_update_iterations = 0;
+
mutable RID_PtrOwner<Scenario> scenario_owner;
- static void *_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int);
- static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *);
+ static void _instance_pair(Instance *p_A, Instance *p_B);
+ static void _instance_unpair(Instance *p_A, Instance *p_B);
static void _instance_update_mesh_instance(Instance *p_instance);
@@ -152,6 +159,17 @@ public:
/* INSTANCING API */
+ struct InstancePair {
+ Instance *a;
+ Instance *b;
+ SelfList<InstancePair> list_a;
+ SelfList<InstancePair> list_b;
+ InstancePair() :
+ list_a(this), list_b(this) {}
+ };
+
+ PagedAllocator<InstancePair> pair_allocator;
+
struct InstanceBaseData {
virtual ~InstanceBaseData() {}
};
@@ -159,7 +177,7 @@ public:
struct Instance : RendererSceneRender::InstanceBase {
RID self;
//scenario stuff
- OctreeElementID octree_id;
+ DynamicBVH::ID indexer_id;
Scenario *scenario;
SelfList<Instance> scenario_item;
@@ -188,6 +206,9 @@ public:
InstanceBaseData *base_data;
+ SelfList<InstancePair>::List pairs;
+ uint64_t pair_check;
+
virtual void dependency_deleted(RID p_dependency) {
if (p_dependency == base) {
singleton->instance_set_base(self, RID());
@@ -205,7 +226,6 @@ public:
Instance() :
scenario_item(this),
update_item(this) {
- octree_id = 0;
scenario = nullptr;
update_aabb = false;
@@ -226,6 +246,8 @@ public:
base_data = nullptr;
custom_aabb = nullptr;
+
+ pair_check = 0;
}
~Instance() {
@@ -242,21 +264,21 @@ public:
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
struct InstanceGeometryData : public InstanceBaseData {
- List<Instance *> lighting;
+ Set<Instance *> lights;
bool lighting_dirty;
bool can_cast_shadows;
bool material_is_animated;
- List<Instance *> decals;
+ Set<Instance *> decals;
bool decal_dirty;
- List<Instance *> reflection_probes;
+ Set<Instance *> reflection_probes;
bool reflection_dirty;
- List<Instance *> gi_probes;
+ Set<Instance *> gi_probes;
bool gi_probes_dirty;
- List<Instance *> lightmap_captures;
+ Set<Instance *> lightmap_captures;
InstanceGeometryData() {
lighting_dirty = false;
@@ -271,11 +293,7 @@ public:
struct InstanceReflectionProbeData : public InstanceBaseData {
Instance *owner;
- struct PairInfo {
- List<Instance *>::Element *L; //reflection iterator in geometry
- Instance *geometry;
- };
- List<PairInfo> geometries;
+ Set<Instance *> geometries;
RID instance;
bool reflection_dirty;
@@ -294,11 +312,7 @@ public:
Instance *owner;
RID instance;
- struct PairInfo {
- List<Instance *>::Element *L; //reflection iterator in geometry
- Instance *geometry;
- };
- List<PairInfo> geometries;
+ Set<Instance *> geometries;
InstanceDecalData() {
}
@@ -307,18 +321,13 @@ public:
SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
struct InstanceLightData : public InstanceBaseData {
- struct PairInfo {
- List<Instance *>::Element *L; //light iterator in geometry
- Instance *geometry;
- };
-
RID instance;
uint64_t last_version;
List<Instance *>::Element *D; // directional light in scenario
bool shadow_dirty;
- List<PairInfo> geometries;
+ Set<Instance *> geometries;
Instance *baked_light;
@@ -339,13 +348,8 @@ public:
struct InstanceGIProbeData : public InstanceBaseData {
Instance *owner;
- struct PairInfo {
- List<Instance *>::Element *L; //gi probe iterator in geometry
- Instance *geometry;
- };
-
- List<PairInfo> geometries;
- List<PairInfo> dynamic_geometries;
+ Set<Instance *> geometries;
+ Set<Instance *> dynamic_geometries;
Set<Instance *> lights;
@@ -383,40 +387,110 @@ public:
SelfList<InstanceGIProbeData>::List gi_probe_update_list;
struct InstanceLightmapData : public InstanceBaseData {
- struct PairInfo {
- List<Instance *>::Element *L; //iterator in geometry
- Instance *geometry;
- };
- List<PairInfo> geometries;
-
+ Set<Instance *> geometries;
Set<Instance *> users;
InstanceLightmapData() {
}
};
+ uint64_t pair_pass = 1;
+
+ struct PairInstances {
+ Instance *instance = nullptr;
+ PagedAllocator<InstancePair> *pair_allocator = nullptr;
+ SelfList<InstancePair>::List pairs_found;
+ DynamicBVH *bvh = nullptr;
+ DynamicBVH *bvh2 = nullptr; //some may need to cull in two
+ uint32_t pair_mask;
+ uint64_t pair_pass;
+
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type))) {
+ //test is more coarse in indexer
+ p_instance->pair_check = pair_pass;
+ InstancePair *pair = pair_allocator->alloc();
+ pair->a = instance;
+ pair->b = p_instance;
+ pairs_found.add(&pair->list_a);
+ }
+ return false;
+ }
+
+ void pair() {
+ if (bvh) {
+ bvh->aabb_query(instance->transformed_aabb, *this);
+ }
+ if (bvh2) {
+ bvh2->aabb_query(instance->transformed_aabb, *this);
+ }
+ while (instance->pairs.first()) {
+ InstancePair *pair = instance->pairs.first()->self();
+ Instance *other_instance = instance == pair->a ? pair->b : pair->a;
+ if (other_instance->pair_check != pair_pass) {
+ //unpaired
+ _instance_unpair(instance, other_instance);
+ } else {
+ //kept
+ other_instance->pair_check = 0; // if kept, then put pair check to zero, so we can distinguish with the newly added ones
+ }
+
+ pair_allocator->free(pair);
+ }
+ while (pairs_found.first()) {
+ InstancePair *pair = pairs_found.first()->self();
+ pairs_found.remove(pairs_found.first());
+
+ if (pair->b->pair_check == pair_pass) {
+ //paired
+ _instance_pair(instance, pair->b);
+ }
+ pair->a->pairs.add(&pair->list_a);
+ pair->b->pairs.add(&pair->list_b);
+ }
+ }
+ };
+
+ struct CullResult {
+ PagedArray<Instance *> *result;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ result->push_back(p_instance);
+ return false;
+ }
+ };
+
Set<Instance *> heightfield_particle_colliders_update_list;
- int instance_cull_count;
- Instance *instance_cull_result[MAX_INSTANCE_CULL];
- Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
- Instance *light_cull_result[MAX_LIGHTS_CULLED];
- RID sdfgi_light_cull_result[MAX_LIGHTS_CULLED];
- RID light_instance_cull_result[MAX_LIGHTS_CULLED];
+ PagedArrayPool<Instance *> instance_cull_page_pool;
+ PagedArrayPool<RendererSceneRender::InstanceBase *> base_instance_cull_page_pool;
+ PagedArrayPool<RID> rid_cull_page_pool;
+
+ PagedArray<Instance *> instance_cull_result;
+ PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_render;
+ PagedArray<Instance *> instance_shadow_cull_result;
+ PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_shadow_render;
+ PagedArray<Instance *> instance_sdfgi_cull_result;
+ PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_sdfgi_render;
+ PagedArray<Instance *> light_cull_result;
+ PagedArray<RendererSceneRender::InstanceBase *> lightmap_cull_result;
+ PagedArray<Instance *> directional_shadow_cull_result;
+ PagedArray<RID> reflection_probe_instance_cull_result;
+ PagedArray<RID> light_instance_cull_result;
+ PagedArray<RID> directional_light_cull_result;
+ PagedArray<RID> gi_probe_instance_cull_result;
+ PagedArray<RID> decal_instance_cull_result;
+
+ PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES];
+
uint64_t sdfgi_light_cull_pass = 0;
- int light_cull_count;
int directional_light_count;
- RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
- RID decal_instance_cull_result[MAX_DECALS_CULLED];
- int reflection_probe_cull_count;
- int decal_cull_count;
- RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
- int gi_probe_cull_count;
- Instance *lightmap_cull_result[MAX_LIGHTS_CULLED];
- int lightmap_cull_count;
RID_PtrOwner<Instance> instance_owner;
+ bool pair_volumes_to_mesh; // used in traditional forward, unnecesary on clustered
+
virtual RID instance_create();
virtual void instance_set_base(RID p_instance, RID p_base);
@@ -460,6 +534,7 @@ public:
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
+ void _unpair_instance(Instance *p_instance);
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold);