Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow changing the maximum renderable elements in the scene. #35447

Closed
wants to merge 1 commit into from

Conversation

haasanen
Copy link
Contributor

@haasanen haasanen commented Jan 22, 2020

Edit: Godot 4.0 no longer has this problem since this commit.

Old PR:

Fixes #30597

The problem:

Setting a value in the project settings for: rendering/limits/rendering/max_renderable_elements does not lift the maximum number of elements that can be drawn. For example when loading 50,000 objects to the scene the total number of objects is loaded fine, but only a fixed number is drawn (see screenshot below). This prevents rendering/showing large numbers of e.g. people in a city or a building. Altering the max_renderable_elements value to 1,000,000 makes no difference.

godot_cull_limitation

There is a hard-coded value MAX_INSTANCE_CULL in visual_server_scene.h file that cannot be edited through the editor or through code at runtime. It is used to allocate a fixed size array for storing drawable elements. It is related to the DEFAULT_MAX_ELEMENTS value that was exposed in a previous pull request: #1339. For large scenes it is necessary to increase both values.

The solution:

This commit exposes (and renames) the MAX_INSTANCE_CULL, DEFAULT_MAX_LIGHTS_CULLED and DEFAULT_MAX_REFLECTION_PROBES_CULLED to match the previously exposed and related values DEFAULT_MAX_ELEMENTS, DEFAULT_MAX_LIGHTS and DEFAULT_MAX_REFLECTIONS.

These are the enum values in visual_server_scene.h:

  • MAX_INSTANCE_CULL = 65536
  • MAX_LIGHTS_CULLED = 4096
  • MAX_REFLECTION_PROBES_CULLED = 4096
  • MAX_ROOM_CULL = 32
  • MAX_EXTERIOR_PORTALS = 128

The last two are never used (now removed) and the first three could not be previously edited through the editor or through code.

Note: the tooltip texts for the ProjectSettings.xml may need rewording. The tooltips from the related values were re-used with an extra explanation.

TL;DR:

Allow changing some hard-coded limits (values) through the editor. No default values have been changed. No difference to anyone who can already work within the hard limits. However, anyone who needs to render large numbers of objects needs this patch (we are using this in-house).

…_CULLED values to the editor as settings.

Removed unused MAX_ROOM_CULL and MAX_EXTERIOR_PORTALS enums.
@haasanen haasanen requested a review from a team as a code owner January 22, 2020 20:15
@Chaosus Chaosus added this to the 4.0 milestone Jan 23, 2020
@clayjohn clayjohn requested a review from reduz February 5, 2020 04:44
@clayjohn
Copy link
Member

clayjohn commented Feb 7, 2020

From my understanding the octree implementation is limited to 2^16 (65536) unique objects which is where the limit came from. The rendering/limits/rendering/max_renderable_elements is actually there to allow users to reduce the maximum number of elements in the scene. This can lead to a substantially faster load times on Web and Mobile platforms.

As it stands now, I'm not sure your changes will actually work without breaking culling. That being said, I agree with the intention behind the changes. We shouldn't arbitrarily be limited users to 65536 objects. However, I think a proper implementation is going to require more than resizing the current arrays.

Further, this is a large change that can't be considered for 3.2.x. It needs to wait until 4.0 (which is why I haven't reviewed it until now). I will leave this open until Vulkan is merged into master (should be soon now) and then we can figure out how to make these changes properly with the Vulkan renderer.

@Calinou
Copy link
Member

Calinou commented Dec 16, 2020

Superseded by #44435 (see the above comment). Thanks for the contribution nonetheless!

@haasanen
Copy link
Contributor Author

Superseded by #44435 (see the above comment). Thanks for the contribution nonetheless!

I believe that is incorrectly marked. #44435 only replaces a hard-coded value with a different hard-coded value, which is exactly the problem this PR is aiming to remove (i.e. hard-coding the value is the problem this PR is fixing).

@Calinou
Copy link
Member

Calinou commented Dec 17, 2020

I believe that is incorrectly marked. #44435 only replaces a hard-coded value with a different hard-coded value, which is exactly the problem this PR is aiming to remove (i.e. hard-coding the value is the problem this PR is fixing).

Increasing the values above the defaults most likely won't work in all cases as pointed out by #35447 (comment). It might work in a few specific cases, but we'd prefer to have something that's guaranteed to work when it's increased (provided the hardware supports it).

If you can prove that increasing max_renderable_elements above 65535 does work without breaking culling, then it might be worth opening a new pull request based on the 3.2 branch (see why). You can distribute a minimal reproduction project for this. See #43606 where a similar process was followed.

The master branch will likely receive changes that allow rendering more than 65,536 elements. It uses a completely new Vulkan-based renderer 🙂

@Calinou
Copy link
Member

Calinou commented Dec 17, 2020

I made a minimal reproduction project with 100,000 meshes: test_huge_amt_elements.zip

Here's how it renders on Godot 3.2.4 + GLES3 + GeForce GTX 1080: https://www.youtube.com/watch?v=qcbCFRAR5Nc
(watch in the highest resolution possible to improve compression quality)

Right now, meshes are culled when you have 65,536 of them, which is expected. We need to test this with an updated version of your pull request (against the current 3.2 branch) to see whether increasing the value works here.

Directional shadows were made red so that you can spot which parts of the octree are effectively shaded more easily.

You can change the number of meshes created in test.gd.

@haasanen
Copy link
Contributor Author

I made a minimal reproduction project with 100,000 meshes: test_huge_amt_elements.zip

Here's how it renders on Godot 3.2.4 + GLES3 + GeForce GTX 1080: https://www.youtube.com/watch?v=qcbCFRAR5Nc
(watch in the highest resolution possible to improve compression quality)

Right now, meshes are culled when you have 65,536 of them, which is expected. We need to test this with an updated version of your pull request (against the current 3.2 branch) to see whether increasing the value works here.

Directional shadows were made red so that you can spot which parts of the octree are effectively shaded more easily.

You can change the number of meshes created in test.gd.

Thank you so much for the effort of putting together a test case! It definitely demonstrates the problem in 3.x.

I went digging for the code to create a new PR. I'm happy to say that this problem no longer exists in 4.0 (more specifically I tested this in commit 380bb2d...).

More info:
The MAX_INSTANCE_CULL constant still exists in ./servers/rendering/rendering_server_default.h, but it is not being used anywhere in the code. It is not exposed to the editor either. However, there is a new variable (introduced in this commit) called max_renderable_elements :

render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000);

The new variable is not hard-coded, and it is exposed to the editor and it works. It defaults to 128,000, which is about double the previous maximum of 65,536 (in 3.x). The test case has to be increased to above the default limit as 100,000 meshes render just fine in 4.0. Increasing the quantity to 150,000 meshes with the default limit manifests the same problem as in 3.x. However, when increasing the limit through the editor to e.g. 200,000, then all 150,000 cubes are rendered, including shadows. It seems that the problem this PR was attempting to solve has already been solved for 4.0. Therefore, I don't see the need to create a new PR for the current version as the next major version of Godot no longer has this problem.

For anyone who reads this: the max_renderable_elements setting can be found in Project -> Project Settings... -> General -> Rendering -> Limits -> Rendering -> Max Renderable Elements.

Here is the same test case but with 150,000 meshes for Godot 4.0:
test_huge_amt_elements_4-0.zip

@haasanen haasanen deleted the master branch October 20, 2022 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cull limit is set to 65556 - is this intentional?
4 participants