Browse Source

Replace Octree by DynamicBVH in cull code

-Much greater pairing/unpairing performance
-For now, using it for culling too, but this will change in a couple of days.
-Added a paged allocator, to efficiently alloc/free some types of objects.
reduz 4 years ago
parent
commit
83058597cf

+ 24 - 1
core/math/dynamic_bvh.cpp

@@ -49,7 +49,6 @@ DynamicBVH::Node *DynamicBVH::_create_node(Node *p_parent, void *p_data) {
 	Node *node = memnew(Node);
 	Node *node = memnew(Node);
 	node->parent = p_parent;
 	node->parent = p_parent;
 	node->data = p_data;
 	node->data = p_data;
-	node->childs[1] = 0;
 	return (node);
 	return (node);
 }
 }
 
 
@@ -335,6 +334,7 @@ DynamicBVH::ID DynamicBVH::insert(const AABB &p_box, void *p_userdata) {
 
 
 	ID id;
 	ID id;
 	id.node = leaf;
 	id.node = leaf;
+
 	return id;
 	return id;
 }
 }
 
 
@@ -389,12 +389,35 @@ void DynamicBVH::_extract_leaves(Node *p_node, List<ID> *r_elements) {
 	}
 	}
 }
 }
 
 
+void DynamicBVH::set_index(uint32_t p_index) {
+	ERR_FAIL_COND(bvh_root != nullptr);
+	index = p_index;
+}
+
+uint32_t DynamicBVH::get_index() const {
+	return index;
+}
+
 void DynamicBVH::get_elements(List<ID> *r_elements) {
 void DynamicBVH::get_elements(List<ID> *r_elements) {
 	if (bvh_root) {
 	if (bvh_root) {
 		_extract_leaves(bvh_root, r_elements);
 		_extract_leaves(bvh_root, r_elements);
 	}
 	}
 }
 }
 
 
+int DynamicBVH::get_leaf_count() const {
+	return total_leaves;
+}
+int DynamicBVH::get_max_depth() const {
+	if (bvh_root) {
+		int depth = 1;
+		int max_depth = 0;
+		bvh_root->get_max_depth(depth, max_depth);
+		return max_depth;
+	} else {
+		return 0;
+	}
+}
+
 DynamicBVH::~DynamicBVH() {
 DynamicBVH::~DynamicBVH() {
 	clear();
 	clear();
 }
 }

+ 116 - 9
core/math/dynamic_bvh.h

@@ -61,13 +61,10 @@ class DynamicBVH {
 
 
 public:
 public:
 	struct ID {
 	struct ID {
-		Node *node;
+		Node *node = nullptr;
 
 
 	public:
 	public:
 		_FORCE_INLINE_ bool is_valid() const { return node != nullptr; }
 		_FORCE_INLINE_ bool is_valid() const { return node != nullptr; }
-		_FORCE_INLINE_ ID() {
-			node = nullptr;
-		}
 	};
 	};
 
 
 private:
 private:
@@ -134,6 +131,48 @@ private:
 					(min.z <= b.max.z) &&
 					(min.z <= b.max.z) &&
 					(max.z >= b.min.z));
 					(max.z >= b.min.z));
 		}
 		}
+
+		_FORCE_INLINE_ bool intersects_convex(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const {
+			Vector3 half_extents = (max - min) * 0.5;
+			Vector3 ofs = min + half_extents;
+
+			for (int i = 0; i < p_plane_count; i++) {
+				const Plane &p = p_planes[i];
+				Vector3 point(
+						(p.normal.x > 0) ? -half_extents.x : half_extents.x,
+						(p.normal.y > 0) ? -half_extents.y : half_extents.y,
+						(p.normal.z > 0) ? -half_extents.z : half_extents.z);
+				point += ofs;
+				if (p.is_point_over(point)) {
+					return false;
+				}
+			}
+
+			// Make sure all points in the shape aren't fully separated from the AABB on
+			// each axis.
+			int bad_point_counts_positive[3] = { 0 };
+			int bad_point_counts_negative[3] = { 0 };
+
+			for (int k = 0; k < 3; k++) {
+				for (int i = 0; i < p_point_count; i++) {
+					if (p_points[i].coord[k] > ofs.coord[k] + half_extents.coord[k]) {
+						bad_point_counts_positive[k]++;
+					}
+					if (p_points[i].coord[k] < ofs.coord[k] - half_extents.coord[k]) {
+						bad_point_counts_negative[k]++;
+					}
+				}
+
+				if (bad_point_counts_negative[k] == p_point_count) {
+					return false;
+				}
+				if (bad_point_counts_positive[k] == p_point_count) {
+					return false;
+				}
+			}
+
+			return true;
+		}
 	};
 	};
 
 
 	struct Node {
 	struct Node {
@@ -144,14 +183,14 @@ private:
 			void *data;
 			void *data;
 		};
 		};
 
 
-		_FORCE_INLINE_ bool is_leaf() const { return data != nullptr; }
+		_FORCE_INLINE_ bool is_leaf() const { return childs[1] == nullptr; }
 		_FORCE_INLINE_ bool is_internal() const { return (!is_leaf()); }
 		_FORCE_INLINE_ bool is_internal() const { return (!is_leaf()); }
 
 
 		_FORCE_INLINE_ int get_index_in_parent() const {
 		_FORCE_INLINE_ int get_index_in_parent() const {
 			ERR_FAIL_COND_V(!parent, 0);
 			ERR_FAIL_COND_V(!parent, 0);
 			return (parent->childs[1] == this) ? 1 : 0;
 			return (parent->childs[1] == this) ? 1 : 0;
 		}
 		}
-		_FORCE_INLINE_ void get_max_depth(int depth, int &maxdepth) {
+		void get_max_depth(int depth, int &maxdepth) {
 			if (is_internal()) {
 			if (is_internal()) {
 				childs[0]->get_max_depth(depth + 1, maxdepth);
 				childs[0]->get_max_depth(depth + 1, maxdepth);
 				childs[1]->get_max_depth(depth + 1, maxdepth);
 				childs[1]->get_max_depth(depth + 1, maxdepth);
@@ -183,6 +222,7 @@ private:
 	int lkhd = -1;
 	int lkhd = -1;
 	int total_leaves = 0;
 	int total_leaves = 0;
 	uint32_t opath = 0;
 	uint32_t opath = 0;
+	uint32_t index = 0;
 
 
 	enum {
 	enum {
 		ALLOCA_STACK_SIZE = 128
 		ALLOCA_STACK_SIZE = 128
@@ -245,6 +285,9 @@ public:
 	void remove(const ID &p_id);
 	void remove(const ID &p_id);
 	void get_elements(List<ID> *r_elements);
 	void get_elements(List<ID> *r_elements);
 
 
+	int get_leaf_count() const;
+	int get_max_depth() const;
+
 	/* Discouraged, but works as a reference on how it must be used */
 	/* Discouraged, but works as a reference on how it must be used */
 	struct DefaultQueryResult {
 	struct DefaultQueryResult {
 		virtual bool operator()(void *p_data) = 0; //return true whether you want to continue the query
 		virtual bool operator()(void *p_data) = 0; //return true whether you want to continue the query
@@ -254,9 +297,13 @@ public:
 	template <class QueryResult>
 	template <class QueryResult>
 	_FORCE_INLINE_ void aabb_query(const AABB &p_aabb, QueryResult &r_result);
 	_FORCE_INLINE_ void aabb_query(const AABB &p_aabb, QueryResult &r_result);
 	template <class QueryResult>
 	template <class QueryResult>
+	_FORCE_INLINE_ void convex_query(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, QueryResult &r_result);
+	template <class QueryResult>
 	_FORCE_INLINE_ void ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result);
 	_FORCE_INLINE_ void ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result);
 
 
-	DynamicBVH();
+	void set_index(uint32_t p_index);
+	uint32_t get_index() const;
+
 	~DynamicBVH();
 	~DynamicBVH();
 };
 };
 
 
@@ -278,8 +325,8 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) {
 	LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time.
 	LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time.
 
 
 	do {
 	do {
-		const Node *n = stack[depth - 1];
 		depth--;
 		depth--;
+		const Node *n = stack[depth];
 		if (n->volume.intersects(volume)) {
 		if (n->volume.intersects(volume)) {
 			if (n->is_internal()) {
 			if (n->is_internal()) {
 				if (depth > threshold) {
 				if (depth > threshold) {
@@ -303,8 +350,67 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) {
 	} while (depth > 0);
 	} while (depth > 0);
 }
 }
 
 
+template <class QueryResult>
+void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, QueryResult &r_result) {
+	if (!bvh_root) {
+		return;
+	}
+
+	//generate a volume anyway to improve pre-testing
+	Volume volume;
+	for (int i = 0; i < p_point_count; i++) {
+		if (i == 0) {
+			volume.min = p_points[0];
+			volume.max = p_points[0];
+		} else {
+			volume.min.x = MIN(volume.min.x, p_points[i].x);
+			volume.min.y = MIN(volume.min.y, p_points[i].y);
+			volume.min.z = MIN(volume.min.z, p_points[i].z);
+
+			volume.max.x = MAX(volume.max.x, p_points[i].x);
+			volume.max.y = MAX(volume.max.y, p_points[i].y);
+			volume.max.z = MAX(volume.max.z, p_points[i].z);
+		}
+	}
+
+	const Node **stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *));
+	stack[0] = bvh_root;
+	int32_t depth = 1;
+	int32_t threshold = ALLOCA_STACK_SIZE - 2;
+
+	LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time.
+
+	do {
+		depth--;
+		const Node *n = stack[depth];
+		if (n->volume.intersects(volume) && n->volume.intersects_convex(p_planes, p_plane_count, p_points, p_point_count)) {
+			if (n->is_internal()) {
+				if (depth > threshold) {
+					if (aux_stack.empty()) {
+						aux_stack.resize(ALLOCA_STACK_SIZE * 2);
+						copymem(aux_stack.ptr(), stack, ALLOCA_STACK_SIZE * sizeof(const Node *));
+					} else {
+						aux_stack.resize(aux_stack.size() * 2);
+					}
+					stack = aux_stack.ptr();
+					threshold = aux_stack.size() - 2;
+				}
+				stack[depth++] = n->childs[0];
+				stack[depth++] = n->childs[1];
+			} else {
+				if (r_result(n->data)) {
+					return;
+				}
+			}
+		}
+	} while (depth > 0);
+}
 template <class QueryResult>
 template <class QueryResult>
 void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result) {
 void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result) {
+	if (!bvh_root) {
+		return;
+	}
+
 	Vector3 ray_dir = (p_to - p_from);
 	Vector3 ray_dir = (p_to - p_from);
 	ray_dir.normalize();
 	ray_dir.normalize();
 
 
@@ -327,7 +433,8 @@ void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResu
 	LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time.
 	LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time.
 
 
 	do {
 	do {
-		const Node *node = stack[--depth];
+		depth--;
+		const Node *node = stack[depth];
 		bounds[0] = node->volume.min;
 		bounds[0] = node->volume.min;
 		bounds[1] = node->volume.max;
 		bounds[1] = node->volume.max;
 		real_t tmin = 1.f, lambda_min = 0.f;
 		real_t tmin = 1.f, lambda_min = 0.f;

+ 129 - 0
core/templates/paged_allocator.h

@@ -0,0 +1,129 @@
+/*************************************************************************/
+/*  paged_allocator.h                                                    */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef PAGED_ALLOCATOR_H
+#define PAGED_ALLOCATOR_H
+
+#include "core/os/memory.h"
+#include "core/os/spin_lock.h"
+#include "core/typedefs.h"
+
+template <class T, bool thread_safe = false>
+class PagedAllocator {
+	T **page_pool = nullptr;
+	T ***available_pool = nullptr;
+	uint32_t pages_allocated = 0;
+	uint32_t allocs_available = 0;
+
+	uint32_t page_shift = 0;
+	uint32_t page_mask = 0;
+	uint32_t page_size = 0;
+	SpinLock spin_lock;
+
+public:
+	T *alloc() {
+		if (thread_safe) {
+			spin_lock.lock();
+		}
+		if (unlikely(allocs_available == 0)) {
+			uint32_t pages_used = pages_allocated;
+
+			pages_allocated++;
+			page_pool = (T **)memrealloc(page_pool, sizeof(T *) * pages_allocated);
+			available_pool = (T ***)memrealloc(available_pool, sizeof(T **) * pages_allocated);
+
+			page_pool[pages_used] = (T *)memalloc(sizeof(T) * page_size);
+			available_pool[pages_used] = (T **)memalloc(sizeof(T *) * page_size);
+
+			for (uint32_t i = 0; i < page_size; i++) {
+				available_pool[0][i] = &page_pool[pages_used][i];
+			}
+			allocs_available += page_size;
+		}
+
+		allocs_available--;
+		T *alloc = available_pool[allocs_available >> page_shift][allocs_available & page_mask];
+		if (thread_safe) {
+			spin_lock.unlock();
+		}
+		memnew_placement(alloc, T);
+		return alloc;
+	}
+
+	void free(T *p_mem) {
+		if (thread_safe) {
+			spin_lock.lock();
+		}
+		p_mem->~T();
+		available_pool[allocs_available >> page_shift][allocs_available & page_mask] = p_mem;
+		if (thread_safe) {
+			spin_lock.unlock();
+		}
+		allocs_available++;
+	}
+
+	void reset() {
+		ERR_FAIL_COND(allocs_available < pages_allocated * page_size);
+		if (pages_allocated) {
+			for (uint32_t i = 0; i < pages_allocated; i++) {
+				memfree(page_pool[i]);
+				memfree(available_pool[i]);
+			}
+			memfree(page_pool);
+			memfree(available_pool);
+			page_pool = nullptr;
+			available_pool = nullptr;
+			pages_allocated = 0;
+			allocs_available = 0;
+		}
+	}
+	bool is_configured() const {
+		return page_size > 0;
+	}
+
+	void configure(uint32_t p_page_size, bool p_thread_safe) {
+		ERR_FAIL_COND(page_pool != nullptr); //sanity check
+		ERR_FAIL_COND(p_page_size == 0);
+		page_size = nearest_power_of_2_templated(p_page_size);
+		page_mask = page_size - 1;
+		page_shift = get_shift_from_power_of_2(page_size);
+	}
+
+	PagedAllocator(uint32_t p_page_size = 4096, bool p_thread_safe = false) { // power of 2 recommended because of alignment with OS page sizes. Even if element is bigger, its still a multiple and get rounded amount of pages
+		configure(p_page_size, false);
+	}
+
+	~PagedAllocator() {
+		ERR_FAIL_COND_MSG(allocs_available < pages_allocated * page_size, "Pages in use exist at exit in PagedAllocator");
+		reset();
+	}
+};
+
+#endif // PAGED_ALLOCATOR_H

+ 1 - 1
core/templates/paged_array.h

@@ -329,7 +329,7 @@ public:
 		}
 		}
 	}
 	}
 
 
-	uint64_t size() const {
+	_FORCE_INLINE_ uint64_t size() const {
 		return count;
 		return count;
 	}
 	}
 
 

+ 13 - 0
core/templates/rid_owner.h

@@ -346,6 +346,18 @@ public:
 		alloc.free(p_rid);
 		alloc.free(p_rid);
 	}
 	}
 
 
+	_FORCE_INLINE_ uint32_t get_rid_count() const {
+		return alloc.get_rid_count();
+	}
+
+	_FORCE_INLINE_ RID get_rid_by_index(uint32_t p_index) {
+		return alloc.get_rid_by_index(p_index);
+	}
+
+	_FORCE_INLINE_ T *get_ptr_by_index(uint32_t p_index) {
+		return *alloc.get_ptr_by_index(p_index);
+	}
+
 	_FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) {
 	_FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) {
 		return alloc.get_owned_list(p_owned);
 		return alloc.get_owned_list(p_owned);
 	}
 	}
@@ -353,6 +365,7 @@ public:
 	void set_description(const char *p_descrption) {
 	void set_description(const char *p_descrption) {
 		alloc.set_description(p_descrption);
 		alloc.set_description(p_descrption);
 	}
 	}
+
 	RID_PtrOwner(uint32_t p_target_chunk_byte_size = 4096) :
 	RID_PtrOwner(uint32_t p_target_chunk_byte_size = 4096) :
 			alloc(p_target_chunk_byte_size) {}
 			alloc(p_target_chunk_byte_size) {}
 };
 };

+ 31 - 31
servers/rendering/renderer_rd/renderer_scene_render_forward.cpp

@@ -1532,7 +1532,7 @@ void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_ins
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi) {
+void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, bool p_using_sdfgi) {
 	scene_state.current_shader_index = 0;
 	scene_state.current_shader_index = 0;
 	scene_state.current_material_index = 0;
 	scene_state.current_material_index = 0;
 	scene_state.used_sss = false;
 	scene_state.used_sss = false;
@@ -1544,8 +1544,8 @@ void RendererSceneRenderForward::_fill_render_list(InstanceBase **p_cull_result,
 
 
 	//fill list
 	//fill list
 
 
-	for (int i = 0; i < p_cull_count; i++) {
-		InstanceBase *inst = p_cull_result[i];
+	for (int i = 0; i < (int)p_instances.size(); i++) {
+		InstanceBase *inst = p_instances[i];
 
 
 		//add geometry for drawing
 		//add geometry for drawing
 		switch (inst->base_type) {
 		switch (inst->base_type) {
@@ -1635,14 +1635,14 @@ void RendererSceneRenderForward::_fill_render_list(InstanceBase **p_cull_result,
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform) {
+void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform) {
 	uint32_t lightmaps_used = 0;
 	uint32_t lightmaps_used = 0;
-	for (int i = 0; i < p_lightmap_cull_count; i++) {
+	for (int i = 0; i < (int)p_lightmaps.size(); i++) {
 		if (i >= (int)scene_state.max_lightmaps) {
 		if (i >= (int)scene_state.max_lightmaps) {
 			break;
 			break;
 		}
 		}
 
 
-		InstanceBase *lm = p_lightmap_cull_result[i];
+		InstanceBase *lm = p_lightmaps[i];
 		Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis;
 		Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis;
 		to_lm = to_lm.inverse().transposed(); //will transform normals
 		to_lm = to_lm.inverse().transposed(); //will transform normals
 		RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
 		RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
@@ -1654,7 +1654,7 @@ void RendererSceneRenderForward::_setup_lightmaps(InstanceBase **p_lightmap_cull
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
 	RenderBufferDataForward *render_buffer = nullptr;
 	RenderBufferDataForward *render_buffer = nullptr;
 	if (p_render_buffer.is_valid()) {
 	if (p_render_buffer.is_valid()) {
 		render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
 		render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
@@ -1709,7 +1709,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 
 
 		opaque_framebuffer = render_buffer->color_fb;
 		opaque_framebuffer = render_buffer->color_fb;
 
 
-		if (!low_end && p_gi_probe_cull_count > 0) {
+		if (!low_end && p_gi_probes.size() > 0) {
 			using_giprobe = true;
 			using_giprobe = true;
 			render_buffer->ensure_gi();
 			render_buffer->ensure_gi();
 		}
 		}
@@ -1776,13 +1776,13 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 		ERR_FAIL(); //bug?
 		ERR_FAIL(); //bug?
 	}
 	}
 
 
-	_setup_lightmaps(p_lightmap_cull_result, p_lightmap_cull_count, p_cam_transform);
+	_setup_lightmaps(p_lightmaps, p_cam_transform);
 	_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
 	_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
 
 
 	_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
 	_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
 
 
 	render_list.clear();
 	render_list.clear();
-	_fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, using_sdfgi);
+	_fill_render_list(p_instances, PASS_MODE_COLOR, using_sdfgi);
 
 
 	bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
 	bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
 
 
@@ -1864,7 +1864,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 		clear_color = p_default_bg_color;
 		clear_color = p_default_bg_color;
 	}
 	}
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probe_cull_result, p_gi_probe_cull_count);
+	RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes);
 
 
 	render_list.sort_by_key(false);
 	render_list.sort_by_key(false);
 
 
@@ -1903,7 +1903,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 	}
 	}
 
 
 	if (using_sdfgi || using_giprobe) {
 	if (using_sdfgi || using_giprobe) {
-		_process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probe_cull_result, p_gi_probe_cull_count);
+		_process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probes);
 	}
 	}
 
 
 	_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid());
 	_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid());
@@ -1949,8 +1949,8 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 		dc.set_depth_correction(true);
 		dc.set_depth_correction(true);
 		CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse());
 		CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse());
 		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
 		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
-		for (int i = 0; i < p_gi_probe_cull_count; i++) {
-			_debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
+		for (int i = 0; i < (int)p_gi_probes.size(); i++) {
+			_debug_giprobe(p_gi_probes[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
 		}
 		}
 		RD::get_singleton()->draw_list_end();
 		RD::get_singleton()->draw_list_end();
 	}
 	}
@@ -2027,7 +2027,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2046,9 +2046,9 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase
 
 
 	PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
 	PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
 
 
-	_fill_render_list(p_cull_result, p_cull_count, pass_mode);
+	_fill_render_list(p_instances, pass_mode);
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);
+	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
 
 
 	RENDER_TIMESTAMP("Render Shadow");
 	RENDER_TIMESTAMP("Render Shadow");
 
 
@@ -2064,7 +2064,7 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count) {
+void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) {
 	RENDER_TIMESTAMP("Setup Render Collider Heightfield");
 	RENDER_TIMESTAMP("Setup Render Collider Heightfield");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2079,9 +2079,9 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,
 
 
 	PassMode pass_mode = PASS_MODE_SHADOW;
 	PassMode pass_mode = PASS_MODE_SHADOW;
 
 
-	_fill_render_list(p_cull_result, p_cull_count, pass_mode);
+	_fill_render_list(p_instances, pass_mode);
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);
+	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
 
 
 	RENDER_TIMESTAMP("Render Collider Heightield");
 	RENDER_TIMESTAMP("Render Collider Heightield");
 
 
@@ -2097,7 +2097,7 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
 	RENDER_TIMESTAMP("Setup Rendering Material");
 	RENDER_TIMESTAMP("Setup Rendering Material");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2112,9 +2112,9 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
 	render_list.clear();
 	render_list.clear();
 
 
 	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
 	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
-	_fill_render_list(p_cull_result, p_cull_count, pass_mode);
+	_fill_render_list(p_instances, pass_mode);
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);
+	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
 
 
 	RENDER_TIMESTAMP("Render Material");
 	RENDER_TIMESTAMP("Render Material");
 
 
@@ -2136,7 +2136,7 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
 	RENDER_TIMESTAMP("Setup Rendering UV2");
 	RENDER_TIMESTAMP("Setup Rendering UV2");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2151,9 +2151,9 @@ void RendererSceneRenderForward::_render_uv2(InstanceBase **p_cull_result, int p
 	render_list.clear();
 	render_list.clear();
 
 
 	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
 	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
-	_fill_render_list(p_cull_result, p_cull_count, pass_mode);
+	_fill_render_list(p_instances, pass_mode);
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);
+	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
 
 
 	RENDER_TIMESTAMP("Render Material");
 	RENDER_TIMESTAMP("Render Material");
 
 
@@ -2197,7 +2197,7 @@ void RendererSceneRenderForward::_render_uv2(InstanceBase **p_cull_result, int p
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
 	RENDER_TIMESTAMP("Render SDFGI");
 	RENDER_TIMESTAMP("Render SDFGI");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2209,7 +2209,7 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto
 	render_list.clear();
 	render_list.clear();
 
 
 	PassMode pass_mode = PASS_MODE_SDF;
 	PassMode pass_mode = PASS_MODE_SDF;
-	_fill_render_list(p_cull_result, p_cull_count, pass_mode);
+	_fill_render_list(p_instances, pass_mode);
 	render_list.sort_by_key(false);
 	render_list.sort_by_key(false);
 	_fill_instances(render_list.elements, render_list.element_count, true);
 	_fill_instances(render_list.elements, render_list.element_count, true);
 
 
@@ -2453,7 +2453,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 	}
 	}
 }
 }
 
 
-RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) {
+RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes) {
 	if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
 	if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
 		RD::get_singleton()->free(render_pass_uniform_set);
 		RD::get_singleton()->free(render_pass_uniform_set);
 	}
 	}
@@ -2516,8 +2516,8 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 		u.ids.resize(MAX_GI_PROBES);
 		u.ids.resize(MAX_GI_PROBES);
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		for (int i = 0; i < MAX_GI_PROBES; i++) {
 		for (int i = 0; i < MAX_GI_PROBES; i++) {
-			if (i < p_gi_probe_cull_count) {
-				RID tex = gi_probe_instance_get_texture(p_gi_probe_cull_result[i]);
+			if (i < (int)p_gi_probes.size()) {
+				RID tex = gi_probe_instance_get_texture(p_gi_probes[i]);
 				if (!tex.is_valid()) {
 				if (!tex.is_valid()) {
 					tex = default_tex;
 					tex = default_tex;
 				}
 				}

+ 9 - 9
servers/rendering/renderer_rd/renderer_scene_render_forward.h

@@ -266,7 +266,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
 
 
 	void _update_render_base_uniform_set();
 	void _update_render_base_uniform_set();
 	RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
 	RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
-	RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count);
+	RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes);
 
 
 	struct LightmapData {
 	struct LightmapData {
 		float normal_xform[12];
 		float normal_xform[12];
@@ -567,26 +567,26 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
 	};
 	};
 
 
 	void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
 	void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
-	void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform);
+	void _setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform);
 
 
 	void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
 	void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
 	void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
 	void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
 	_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
 	_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
 	_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
 	_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
 
 
-	void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi = false);
+	void _fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, bool p_using_sdfgi = false);
 
 
 	Map<Size2i, RID> sdfgi_framebuffer_size_cache;
 	Map<Size2i, RID> sdfgi_framebuffer_size_cache;
 
 
 	bool low_end = false;
 	bool low_end = false;
 
 
 protected:
 protected:
-	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
-	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
-	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
-	virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
-	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
-	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count);
+	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
+	virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
+	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+	virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
+	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances);
 
 
 public:
 public:
 	virtual void set_time(double p_time, double p_step);
 	virtual void set_time(double p_time, double p_step);

+ 69 - 54
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -1153,7 +1153,7 @@ void RendererSceneRenderRD::_sdfgi_update_cascades(RID p_render_buffers) {
 	RD::get_singleton()->buffer_update(rb->sdfgi->cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, true);
 	RD::get_singleton()->buffer_update(rb->sdfgi->cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, true);
 }
 }
 
 
-void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) {
+void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_environment, const PagedArray<RID> &p_directional_light_instances, const RID *p_positional_light_instances, uint32_t p_positional_light_count) {
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	ERR_FAIL_COND(rb == nullptr);
 	ERR_FAIL_COND(rb == nullptr);
 	if (rb->sdfgi == nullptr) {
 	if (rb->sdfgi == nullptr) {
@@ -1179,7 +1179,7 @@ void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_envi
 
 
 			SDGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS];
 			SDGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS];
 			uint32_t idx = 0;
 			uint32_t idx = 0;
-			for (uint32_t j = 0; j < p_directional_light_count; j++) {
+			for (uint32_t j = 0; j < (uint32_t)p_directional_light_instances.size(); j++) {
 				if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
 				if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
 					break;
 					break;
 				}
 				}
@@ -1402,7 +1402,7 @@ void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_envi
 	RENDER_TIMESTAMP("<SDFGI Update Probes");
 	RENDER_TIMESTAMP("<SDFGI Update Probes");
 }
 }
 
 
-void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, uint32_t &r_gi_probes_used) {
+void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used) {
 	r_gi_probes_used = 0;
 	r_gi_probes_used = 0;
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	ERR_FAIL_COND(rb == nullptr);
 	ERR_FAIL_COND(rb == nullptr);
@@ -1417,8 +1417,8 @@ void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transfor
 
 
 	for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) {
 	for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) {
 		RID texture;
 		RID texture;
-		if (i < p_gi_probe_cull_count) {
-			GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_gi_probe_cull_result[i]);
+		if (i < (int)p_gi_probes.size()) {
+			GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_gi_probes[i]);
 
 
 			if (gipi) {
 			if (gipi) {
 				texture = gipi->texture;
 				texture = gipi->texture;
@@ -1489,12 +1489,12 @@ void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transfor
 		}
 		}
 	}
 	}
 
 
-	if (p_gi_probe_cull_count > 0) {
-		RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GI::GIProbeData) * MIN(RenderBuffers::MAX_GIPROBES, p_gi_probe_cull_count), gi_probe_data, true);
+	if (p_gi_probes.size() > 0) {
+		RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GI::GIProbeData) * MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size()), gi_probe_data, true);
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) {
+void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes) {
 	RENDER_TIMESTAMP("Render GI");
 	RENDER_TIMESTAMP("Render GI");
 
 
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -1512,7 +1512,7 @@ void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_rough
 	push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
 	push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
 	push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
 	push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
 	push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
 	push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
-	push_constant.max_giprobes = MIN(RenderBuffers::MAX_GIPROBES, p_gi_probe_cull_count);
+	push_constant.max_giprobes = MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size());
 	push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH;
 	push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH;
 	push_constant.use_sdfgi = rb->sdfgi != nullptr;
 	push_constant.use_sdfgi = rb->sdfgi != nullptr;
 
 
@@ -4061,7 +4061,7 @@ bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {
 	return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
 	return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
 }
 }
 
 
-void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) {
+void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<InstanceBase *> &p_dynamic_objects) {
 	GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
 	GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
 	ERR_FAIL_COND(!gi_probe);
 	ERR_FAIL_COND(!gi_probe);
 
 
@@ -4420,7 +4420,7 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
 
 
 	uint32_t light_count = 0;
 	uint32_t light_count = 0;
 
 
-	if (p_update_light_instances || p_dynamic_object_count > 0) {
+	if (p_update_light_instances || p_dynamic_objects.size() > 0) {
 		light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size());
 		light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size());
 
 
 		{
 		{
@@ -4470,7 +4470,7 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
 		}
 		}
 	}
 	}
 
 
-	if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_object_count) {
+	if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_objects.size()) {
 		// PROCESS MIPMAPS
 		// PROCESS MIPMAPS
 		if (gi_probe->mipmaps.size()) {
 		if (gi_probe->mipmaps.size()) {
 			//can update mipmaps
 			//can update mipmaps
@@ -4563,7 +4563,7 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
 
 
 	gi_probe->has_dynamic_object_data = false; //clear until dynamic object data is used again
 	gi_probe->has_dynamic_object_data = false; //clear until dynamic object data is used again
 
 
-	if (p_dynamic_object_count && gi_probe->dynamic_maps.size()) {
+	if (p_dynamic_objects.size() && gi_probe->dynamic_maps.size()) {
 		Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
 		Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
 		int multiplier = gi_probe->dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
 		int multiplier = gi_probe->dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
 
 
@@ -4577,7 +4577,7 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
 		AABB probe_aabb(Vector3(), octree_size);
 		AABB probe_aabb(Vector3(), octree_size);
 
 
 		//this could probably be better parallelized in compute..
 		//this could probably be better parallelized in compute..
-		for (int i = 0; i < p_dynamic_object_count; i++) {
+		for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
 			InstanceBase *instance = p_dynamic_objects[i];
 			InstanceBase *instance = p_dynamic_objects[i];
 			//not used, so clear
 			//not used, so clear
 			instance->depth_layer = 0;
 			instance->depth_layer = 0;
@@ -4648,7 +4648,12 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
 				CameraMatrix cm;
 				CameraMatrix cm;
 				cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]);
 				cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]);
 
 
-				_render_material(to_world_xform * xform, cm, true, &instance, 1, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
+				if (cull_argument.size() == 0) {
+					cull_argument.push_back(nullptr);
+				}
+				cull_argument[0] = instance;
+
+				_render_material(to_world_xform * xform, cm, true, cull_argument, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
 
 
 				GIProbeDynamicPushConstant push_constant;
 				GIProbeDynamicPushConstant push_constant;
 				zeromem(&push_constant, sizeof(GIProbeDynamicPushConstant));
 				zeromem(&push_constant, sizeof(GIProbeDynamicPushConstant));
@@ -6001,11 +6006,11 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
 	return rb->data;
 	return rb->data;
 }
 }
 
 
-void RendererSceneRenderRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
-	for (int i = 0; i < p_reflection_probe_cull_count; i++) {
-		RID rpi = p_reflection_probe_cull_result[i];
+void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment) {
+	for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
+		RID rpi = p_reflections[i];
 
 
-		if (i >= (int)cluster.max_reflections) {
+		if (i >= cluster.max_reflections) {
 			reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
 			reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
 			continue;
 			continue;
 		}
 		}
@@ -6056,19 +6061,19 @@ void RendererSceneRenderRD::_setup_reflections(RID *p_reflection_probe_cull_resu
 		reflection_probe_instance_set_render_pass(rpi, RSG::rasterizer->get_frame_number());
 		reflection_probe_instance_set_render_pass(rpi, RSG::rasterizer->get_frame_number());
 	}
 	}
 
 
-	if (p_reflection_probe_cull_count) {
-		RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, MIN(cluster.max_reflections, (unsigned int)p_reflection_probe_cull_count) * sizeof(ReflectionData), cluster.reflections, true);
+	if (p_reflections.size()) {
+		RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, MIN(cluster.max_reflections, (unsigned int)p_reflections.size()) * sizeof(ReflectionData), cluster.reflections, true);
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
+void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
 	uint32_t light_count = 0;
 	uint32_t light_count = 0;
 	r_directional_light_count = 0;
 	r_directional_light_count = 0;
 	r_positional_light_count = 0;
 	r_positional_light_count = 0;
 	sky_scene_state.ubo.directional_light_count = 0;
 	sky_scene_state.ubo.directional_light_count = 0;
 
 
-	for (int i = 0; i < p_light_cull_count; i++) {
-		RID li = p_light_cull_result[i];
+	for (int i = 0; i < (int)p_lights.size(); i++) {
+		RID li = p_lights[i];
 		RID base = light_instance_get_base_light(li);
 		RID base = light_instance_get_base_light(li);
 
 
 		ERR_CONTINUE(base.is_null());
 		ERR_CONTINUE(base.is_null());
@@ -6421,15 +6426,15 @@ void RendererSceneRenderRD::_setup_lights(RID *p_light_cull_result, int p_light_
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::_setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform) {
+void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform) {
 	Transform uv_xform;
 	Transform uv_xform;
 	uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
 	uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
 	uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
 	uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
 
 
-	p_decal_count = MIN((uint32_t)p_decal_count, cluster.max_decals);
+	uint32_t decal_count = MIN((uint32_t)p_decals.size(), cluster.max_decals);
 	int idx = 0;
 	int idx = 0;
-	for (int i = 0; i < p_decal_count; i++) {
-		RID di = p_decal_instances[i];
+	for (uint32_t i = 0; i < decal_count; i++) {
+		RID di = p_decals[i];
 		RID decal = decal_instance_get_base(di);
 		RID decal = decal_instance_get_base(di);
 
 
 		Transform xform = decal_instance_get_transform(di);
 		Transform xform = decal_instance_get_transform(di);
@@ -7097,7 +7102,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 	RD::get_singleton()->compute_list_end();
 	RD::get_singleton()->compute_list_end();
 }
 }
 
 
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
 	Color clear_color;
 	Color clear_color;
 	if (p_render_buffers.is_valid()) {
 	if (p_render_buffers.is_valid()) {
 		RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 		RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -7108,17 +7113,23 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
 	}
 	}
 
 
 	//assign render indices to giprobes
 	//assign render indices to giprobes
-	for (int i = 0; i < p_gi_probe_cull_count; i++) {
-		GIProbeInstance *giprobe_inst = gi_probe_instance_owner.getornull(p_gi_probe_cull_result[i]);
+	for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) {
+		GIProbeInstance *giprobe_inst = gi_probe_instance_owner.getornull(p_gi_probes[i]);
 		if (giprobe_inst) {
 		if (giprobe_inst) {
 			giprobe_inst->render_index = i;
 			giprobe_inst->render_index = i;
 		}
 		}
 	}
 	}
 
 
+	const PagedArray<RID> *lights = &p_lights;
+	const PagedArray<RID> *reflections = &p_reflection_probes;
+	const PagedArray<RID> *gi_probes = &p_gi_probes;
+
+	PagedArray<RID> empty;
+
 	if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
 	if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
-		p_light_cull_count = 0;
-		p_reflection_probe_cull_count = 0;
-		p_gi_probe_cull_count = 0;
+		lights = &empty;
+		reflections = &empty;
+		gi_probes = &empty;
 	}
 	}
 
 
 	cluster.builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
 	cluster.builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
@@ -7131,17 +7142,17 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
 		}
 		}
 	} else {
 	} else {
 		//do not render reflections when rendering a reflection probe
 		//do not render reflections when rendering a reflection probe
-		_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
+		_setup_reflections(*reflections, p_cam_transform.affine_inverse(), p_environment);
 	}
 	}
 
 
 	uint32_t directional_light_count = 0;
 	uint32_t directional_light_count = 0;
 	uint32_t positional_light_count = 0;
 	uint32_t positional_light_count = 0;
-	_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows, directional_light_count, positional_light_count);
-	_setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse());
+	_setup_lights(*lights, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows, directional_light_count, positional_light_count);
+	_setup_decals(p_decals, p_cam_transform.affine_inverse());
 	cluster.builder.bake_cluster(); //bake to cluster
 	cluster.builder.bake_cluster(); //bake to cluster
 
 
 	uint32_t gi_probe_count = 0;
 	uint32_t gi_probe_count = 0;
-	_setup_giprobes(p_render_buffers, p_cam_transform, p_gi_probe_cull_result, p_gi_probe_cull_count, gi_probe_count);
+	_setup_giprobes(p_render_buffers, p_cam_transform, *gi_probes, gi_probe_count);
 
 
 	if (p_render_buffers.is_valid()) {
 	if (p_render_buffers.is_valid()) {
 		bool directional_shadows = false;
 		bool directional_shadows = false;
@@ -7154,7 +7165,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
 		_update_volumetric_fog(p_render_buffers, p_environment, p_cam_projection, p_cam_transform, p_shadow_atlas, directional_light_count, directional_shadows, positional_light_count, gi_probe_count);
 		_update_volumetric_fog(p_render_buffers, p_environment, p_cam_projection, p_cam_transform, p_shadow_atlas, directional_light_count, directional_shadows, positional_light_count, gi_probe_count);
 	}
 	}
 
 
-	_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, directional_light_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
+	_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, directional_light_count, *gi_probes, p_lightmaps, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
 
 
 	if (p_render_buffers.is_valid()) {
 	if (p_render_buffers.is_valid()) {
 		RENDER_TIMESTAMP("Tonemap");
 		RENDER_TIMESTAMP("Tonemap");
@@ -7167,7 +7178,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
 	LightInstance *light_instance = light_instance_owner.getornull(p_light);
 	LightInstance *light_instance = light_instance_owner.getornull(p_light);
 	ERR_FAIL_COND(!light_instance);
 	ERR_FAIL_COND(!light_instance);
 
 
@@ -7318,7 +7329,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
 
 
 	if (render_cubemap) {
 	if (render_cubemap) {
 		//rendering to cubemap
 		//rendering to cubemap
-		_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
+		_render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
 		if (finalize_cubemap) {
 		if (finalize_cubemap) {
 			//reblit
 			//reblit
 			atlas_rect.size.height /= 2;
 			atlas_rect.size.height /= 2;
@@ -7329,7 +7340,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
 	} else {
 	} else {
 		//render shadow
 		//render shadow
 
 
-		_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
+		_render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
 
 
 		//copy to atlas
 		//copy to atlas
 		if (use_linear_depth) {
 		if (use_linear_depth) {
@@ -7343,11 +7354,11 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
-	_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_framebuffer, p_region);
+void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+	_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);
 }
 }
 
 
-void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) {
+void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) {
 	//print_line("rendering region " + itos(p_region));
 	//print_line("rendering region " + itos(p_region));
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	ERR_FAIL_COND(!rb);
 	ERR_FAIL_COND(!rb);
@@ -7370,7 +7381,7 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, Ins
 	}
 	}
 
 
 	//print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(rb->sdfgi->cascades[cascade].cell_size));
 	//print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(rb->sdfgi->cascades[cascade].cell_size));
-	_render_sdfgi(p_render_buffers, from, size, bounds, p_cull_result, p_cull_count, rb->sdfgi->render_albedo, rb->sdfgi->render_emission, rb->sdfgi->render_emission_aniso, rb->sdfgi->render_geom_facing);
+	_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, rb->sdfgi->render_albedo, rb->sdfgi->render_emission, rb->sdfgi->render_emission_aniso, rb->sdfgi->render_geom_facing);
 
 
 	if (cascade_next != cascade) {
 	if (cascade_next != cascade) {
 		RENDER_TIMESTAMP(">SDFGI Update SDF");
 		RENDER_TIMESTAMP(">SDFGI Update SDF");
@@ -7684,7 +7695,7 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, Ins
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) {
 	ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
 	ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
 	Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
 	Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
 	CameraMatrix cm;
 	CameraMatrix cm;
@@ -7698,16 +7709,14 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
 
 
 	RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider);
 	RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider);
 
 
-	_render_particle_collider_heightfield(fb, cam_xform, cm, p_cull_result, p_cull_count);
+	_render_particle_collider_heightfield(fb, cam_xform, cm, p_instances);
 }
 }
 
 
-void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) {
+void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result) {
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	ERR_FAIL_COND(!rb);
 	ERR_FAIL_COND(!rb);
 	ERR_FAIL_COND(!rb->sdfgi);
 	ERR_FAIL_COND(!rb->sdfgi);
 
 
-	ERR_FAIL_COND(p_positional_light_cull_count == 0);
-
 	_sdfgi_update_cascades(p_render_buffers); //need cascades updated for this
 	_sdfgi_update_cascades(p_render_buffers); //need cascades updated for this
 
 
 	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
 	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -7743,7 +7752,7 @@ void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uin
 
 
 			int idx = 0;
 			int idx = 0;
 
 
-			for (uint32_t j = 0; j < p_positional_light_cull_count[i]; j++) {
+			for (uint32_t j = 0; j < (uint32_t)p_positional_light_cull_result[i].size(); j++) {
 				if (idx == SDFGI::MAX_STATIC_LIGHTS) {
 				if (idx == SDFGI::MAX_STATIC_LIGHTS) {
 					break;
 					break;
 				}
 				}
@@ -7982,8 +7991,11 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
 		}
 		}
 	}
 	}
 
 
-	InstanceBase *cull = &ins;
-	_render_uv2(&cull, 1, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
+	if (cull_argument.size() == 0) {
+		cull_argument.push_back(nullptr);
+	}
+	cull_argument[0] = &ins;
+	_render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
 
 
 	TypedArray<Image> ret;
 	TypedArray<Image> ret;
 
 
@@ -8534,6 +8546,8 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
 	environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/volumetric_fog/use_filter"));
 	environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/volumetric_fog/use_filter"));
 	environment_set_volumetric_fog_directional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/directional_shadow_shrink"));
 	environment_set_volumetric_fog_directional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/directional_shadow_shrink"));
 	environment_set_volumetric_fog_positional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/positional_shadow_shrink"));
 	environment_set_volumetric_fog_positional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/positional_shadow_shrink"));
+
+	cull_argument.set_page_pool(&cull_argument_pool);
 }
 }
 
 
 RendererSceneRenderRD::~RendererSceneRenderRD() {
 RendererSceneRenderRD::~RendererSceneRenderRD() {
@@ -8598,4 +8612,5 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
 	RD::get_singleton()->free(shadow_sampler);
 	RD::get_singleton()->free(shadow_sampler);
 
 
 	directional_shadow_atlas_set_size(0);
 	directional_shadow_atlas_set_size(0);
+	cull_argument.reset(); //avoid exit error
 }
 }

+ 23 - 20
servers/rendering/renderer_rd/renderer_scene_render_rd.h

@@ -104,17 +104,17 @@ protected:
 	};
 	};
 	virtual RenderBufferData *_create_render_buffer_data() = 0;
 	virtual RenderBufferData *_create_render_buffer_data() = 0;
 
 
-	void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
-	void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform);
-	void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
-	void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, uint32_t &r_gi_probes_used);
-
-	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
-	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
-	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
-	virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
-	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
-	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count) = 0;
+	void _setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
+	void _setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform);
+	void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);
+	void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used);
+
+	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
+	virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
+	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+	virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
+	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) = 0;
 
 
 	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
 	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
 	void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
 	void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
@@ -134,8 +134,11 @@ protected:
 	void _setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size);
 	void _setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size);
 	void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
 	void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
 	void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
 	void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
-	void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count);
+	void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);
 
 
+	// needed for a single argument calls (material and uv2)
+	PagedArrayPool<InstanceBase *> cull_argument_pool;
+	PagedArray<InstanceBase *> cull_argument; //need this to exist
 private:
 private:
 	RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
 	RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
 	double time_step = 0;
 	double time_step = 0;
@@ -1513,7 +1516,7 @@ public:
 	virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const;
 	virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const;
 	virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const;
 	virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const;
 	virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const;
 	virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const;
-	virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count);
+	virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const PagedArray<RID> &p_directional_light_instances, const RID *p_positional_light_instances, uint32_t p_positional_light_count);
 	RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
 	RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
 	/* SKY API */
 	/* SKY API */
 
 
@@ -1822,7 +1825,7 @@ public:
 	RID gi_probe_instance_create(RID p_base);
 	RID gi_probe_instance_create(RID p_base);
 	void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
 	void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
 	bool gi_probe_needs_update(RID p_probe) const;
 	bool gi_probe_needs_update(RID p_probe) const;
-	void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects);
+	void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects);
 
 
 	void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
 	void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
 
 
@@ -1897,16 +1900,16 @@ public:
 	float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
 	float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
 	float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
 	float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
 
 
-	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
+	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
 
 
-	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
+	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
 
 
-	void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
+	void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
 
 
-	void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count);
-	void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count);
+	void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances);
+	void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);
 
 
-	void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count);
+	void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances);
 
 
 	virtual void set_scene_pass(uint64_t p_pass) {
 	virtual void set_scene_pass(uint64_t p_pass) {
 		scene_pass = p_pass;
 		scene_pass = p_pass;

File diff suppressed because it is too large
+ 333 - 297
servers/rendering/renderer_scene_cull.cpp


+ 140 - 65
servers/rendering/renderer_scene_cull.h

@@ -34,30 +34,25 @@
 #include "core/templates/pass_func.h"
 #include "core/templates/pass_func.h"
 #include "servers/rendering/renderer_compositor.h"
 #include "servers/rendering/renderer_compositor.h"
 
 
+#include "core/math/dynamic_bvh.h"
 #include "core/math/geometry_3d.h"
 #include "core/math/geometry_3d.h"
 #include "core/math/octree.h"
 #include "core/math/octree.h"
 #include "core/os/semaphore.h"
 #include "core/os/semaphore.h"
 #include "core/os/thread.h"
 #include "core/os/thread.h"
 #include "core/templates/local_vector.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/rid_owner.h"
 #include "core/templates/self_list.h"
 #include "core/templates/self_list.h"
 #include "servers/rendering/renderer_scene.h"
 #include "servers/rendering/renderer_scene.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/xr/xr_interface.h"
 #include "servers/xr/xr_interface.h"
-
 class RendererSceneCull : public RendererScene {
 class RendererSceneCull : public RendererScene {
 public:
 public:
 	RendererSceneRender *scene_render;
 	RendererSceneRender *scene_render;
 
 
 	enum {
 	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;
 	uint64_t render_pass;
@@ -114,11 +109,17 @@ public:
 	struct Instance;
 	struct Instance;
 
 
 	struct Scenario {
 	struct Scenario {
+		enum IndexerType {
+			INDEXER_GEOMETRY, //for geometry
+			INDEXER_VOLUMES, //for everything else
+			INDEXER_MAX
+		};
+
+		DynamicBVH indexers[INDEXER_MAX];
+
 		RS::ScenarioDebugMode debug;
 		RS::ScenarioDebugMode debug;
 		RID self;
 		RID self;
 
 
-		Octree<Instance, true> octree;
-
 		List<Instance *> directional_lights;
 		List<Instance *> directional_lights;
 		RID environment;
 		RID environment;
 		RID fallback_environment;
 		RID fallback_environment;
@@ -130,13 +131,19 @@ public:
 
 
 		LocalVector<RID> dynamic_lights;
 		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;
 	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);
 	static void _instance_update_mesh_instance(Instance *p_instance);
 
 
@@ -152,6 +159,17 @@ public:
 
 
 	/* INSTANCING API */
 	/* 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 {
 	struct InstanceBaseData {
 		virtual ~InstanceBaseData() {}
 		virtual ~InstanceBaseData() {}
 	};
 	};
@@ -159,7 +177,7 @@ public:
 	struct Instance : RendererSceneRender::InstanceBase {
 	struct Instance : RendererSceneRender::InstanceBase {
 		RID self;
 		RID self;
 		//scenario stuff
 		//scenario stuff
-		OctreeElementID octree_id;
+		DynamicBVH::ID indexer_id;
 		Scenario *scenario;
 		Scenario *scenario;
 		SelfList<Instance> scenario_item;
 		SelfList<Instance> scenario_item;
 
 
@@ -188,6 +206,9 @@ public:
 
 
 		InstanceBaseData *base_data;
 		InstanceBaseData *base_data;
 
 
+		SelfList<InstancePair>::List pairs;
+		uint64_t pair_check;
+
 		virtual void dependency_deleted(RID p_dependency) {
 		virtual void dependency_deleted(RID p_dependency) {
 			if (p_dependency == base) {
 			if (p_dependency == base) {
 				singleton->instance_set_base(self, RID());
 				singleton->instance_set_base(self, RID());
@@ -205,7 +226,6 @@ public:
 		Instance() :
 		Instance() :
 				scenario_item(this),
 				scenario_item(this),
 				update_item(this) {
 				update_item(this) {
-			octree_id = 0;
 			scenario = nullptr;
 			scenario = nullptr;
 
 
 			update_aabb = false;
 			update_aabb = false;
@@ -226,6 +246,8 @@ public:
 			base_data = nullptr;
 			base_data = nullptr;
 
 
 			custom_aabb = nullptr;
 			custom_aabb = nullptr;
+
+			pair_check = 0;
 		}
 		}
 
 
 		~Instance() {
 		~Instance() {
@@ -242,21 +264,21 @@ public:
 	void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
 	void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
 
 
 	struct InstanceGeometryData : public InstanceBaseData {
 	struct InstanceGeometryData : public InstanceBaseData {
-		List<Instance *> lighting;
+		Set<Instance *> lights;
 		bool lighting_dirty;
 		bool lighting_dirty;
 		bool can_cast_shadows;
 		bool can_cast_shadows;
 		bool material_is_animated;
 		bool material_is_animated;
 
 
-		List<Instance *> decals;
+		Set<Instance *> decals;
 		bool decal_dirty;
 		bool decal_dirty;
 
 
-		List<Instance *> reflection_probes;
+		Set<Instance *> reflection_probes;
 		bool reflection_dirty;
 		bool reflection_dirty;
 
 
-		List<Instance *> gi_probes;
+		Set<Instance *> gi_probes;
 		bool gi_probes_dirty;
 		bool gi_probes_dirty;
 
 
-		List<Instance *> lightmap_captures;
+		Set<Instance *> lightmap_captures;
 
 
 		InstanceGeometryData() {
 		InstanceGeometryData() {
 			lighting_dirty = false;
 			lighting_dirty = false;
@@ -271,11 +293,7 @@ public:
 	struct InstanceReflectionProbeData : public InstanceBaseData {
 	struct InstanceReflectionProbeData : public InstanceBaseData {
 		Instance *owner;
 		Instance *owner;
 
 
-		struct PairInfo {
-			List<Instance *>::Element *L; //reflection iterator in geometry
-			Instance *geometry;
-		};
-		List<PairInfo> geometries;
+		Set<Instance *> geometries;
 
 
 		RID instance;
 		RID instance;
 		bool reflection_dirty;
 		bool reflection_dirty;
@@ -294,11 +312,7 @@ public:
 		Instance *owner;
 		Instance *owner;
 		RID instance;
 		RID instance;
 
 
-		struct PairInfo {
-			List<Instance *>::Element *L; //reflection iterator in geometry
-			Instance *geometry;
-		};
-		List<PairInfo> geometries;
+		Set<Instance *> geometries;
 
 
 		InstanceDecalData() {
 		InstanceDecalData() {
 		}
 		}
@@ -307,18 +321,13 @@ public:
 	SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
 	SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
 
 
 	struct InstanceLightData : public InstanceBaseData {
 	struct InstanceLightData : public InstanceBaseData {
-		struct PairInfo {
-			List<Instance *>::Element *L; //light iterator in geometry
-			Instance *geometry;
-		};
-
 		RID instance;
 		RID instance;
 		uint64_t last_version;
 		uint64_t last_version;
 		List<Instance *>::Element *D; // directional light in scenario
 		List<Instance *>::Element *D; // directional light in scenario
 
 
 		bool shadow_dirty;
 		bool shadow_dirty;
 
 
-		List<PairInfo> geometries;
+		Set<Instance *> geometries;
 
 
 		Instance *baked_light;
 		Instance *baked_light;
 
 
@@ -339,13 +348,8 @@ public:
 	struct InstanceGIProbeData : public InstanceBaseData {
 	struct InstanceGIProbeData : public InstanceBaseData {
 		Instance *owner;
 		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;
 		Set<Instance *> lights;
 
 
@@ -383,40 +387,110 @@ public:
 	SelfList<InstanceGIProbeData>::List gi_probe_update_list;
 	SelfList<InstanceGIProbeData>::List gi_probe_update_list;
 
 
 	struct InstanceLightmapData : public InstanceBaseData {
 	struct InstanceLightmapData : public InstanceBaseData {
-		struct PairInfo {
-			List<Instance *>::Element *L; //iterator in geometry
-			Instance *geometry;
-		};
-		List<PairInfo> geometries;
-
+		Set<Instance *> geometries;
 		Set<Instance *> users;
 		Set<Instance *> users;
 
 
 		InstanceLightmapData() {
 		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;
 	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;
 	uint64_t sdfgi_light_cull_pass = 0;
-	int light_cull_count;
 	int directional_light_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;
 	RID_PtrOwner<Instance> instance_owner;
 
 
+	bool pair_volumes_to_mesh; // used in traditional forward, unnecesary on clustered
+
 	virtual RID instance_create();
 	virtual RID instance_create();
 
 
 	virtual void instance_set_base(RID p_instance, RID p_base);
 	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_instance_aabb(Instance *p_instance);
 	_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
 	_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
 	_FORCE_INLINE_ void _update_instance_lightmap_captures(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);
 	_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);
 
 

+ 9 - 8
servers/rendering/renderer_scene_render.h

@@ -32,6 +32,7 @@
 #define RENDERINGSERVERSCENERENDER_H
 #define RENDERINGSERVERSCENERENDER_H
 
 
 #include "core/math/camera_matrix.h"
 #include "core/math/camera_matrix.h"
+#include "core/templates/paged_array.h"
 #include "servers/rendering/renderer_storage.h"
 #include "servers/rendering/renderer_storage.h"
 
 
 class RendererSceneRender {
 class RendererSceneRender {
@@ -55,7 +56,7 @@ public:
 	virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
 	virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
 	virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
 	virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
 	virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
 	virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
-	virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0;
+	virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const PagedArray<RID> &p_directionals, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0;
 
 
 	/* SKY API */
 	/* SKY API */
 
 
@@ -231,17 +232,17 @@ public:
 	virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
 	virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
 	virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
 	virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
 	virtual bool gi_probe_needs_update(RID p_probe) const = 0;
 	virtual bool gi_probe_needs_update(RID p_probe) const = 0;
-	virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0;
+	virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects) = 0;
 
 
 	virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
 	virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
 
 
-	virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
+	virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
 
 
-	virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
-	virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
-	virtual void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) = 0;
-	virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) = 0;
-	virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count) = 0;
+	virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
+	virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+	virtual void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) = 0;
+	virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_lights) = 0;
+	virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) = 0;
 
 
 	virtual void set_scene_pass(uint64_t p_pass) = 0;
 	virtual void set_scene_pass(uint64_t p_pass) = 0;
 	virtual void set_time(double p_time, double p_step) = 0;
 	virtual void set_time(double p_time, double p_step) = 0;

+ 3 - 0
servers/rendering_server.cpp

@@ -2359,6 +2359,9 @@ RenderingServer::RenderingServer() {
 	ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/directional_shadow_shrink", PropertyInfo(Variant::INT, "rendering/volumetric_fog/directional_shadow_shrink", PROPERTY_HINT_RANGE, "32,2048,1"));
 	ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/directional_shadow_shrink", PropertyInfo(Variant::INT, "rendering/volumetric_fog/directional_shadow_shrink", PROPERTY_HINT_RANGE, "32,2048,1"));
 	GLOBAL_DEF("rendering/volumetric_fog/positional_shadow_shrink", 512);
 	GLOBAL_DEF("rendering/volumetric_fog/positional_shadow_shrink", 512);
 	ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/positional_shadow_shrink", PropertyInfo(Variant::INT, "rendering/volumetric_fog/positional_shadow_shrink", PROPERTY_HINT_RANGE, "32,2048,1"));
 	ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/positional_shadow_shrink", PropertyInfo(Variant::INT, "rendering/volumetric_fog/positional_shadow_shrink", PROPERTY_HINT_RANGE, "32,2048,1"));
+
+	GLOBAL_DEF("rendering/spatial_indexer/update_iterations_per_frame", 10);
+	ProjectSettings::get_singleton()->set_custom_property_info("rendering/spatial_indexer/update_iterations_per_frame", PropertyInfo(Variant::INT, "rendering/spatial_indexer/update_iterations_per_frame", PROPERTY_HINT_RANGE, "0,1024,1"));
 }
 }
 
 
 RenderingServer::~RenderingServer() {
 RenderingServer::~RenderingServer() {

Some files were not shown because too many files changed in this diff