-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Type safe retained render world #15756
Type safe retained render world #15756
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The approach used in the PR make sense to me. It's a bit unfortuante that we need to do all that but I think it's the easiest fix for now.
LGTM once CI is green
Blocked on #15755 |
The blocker is fixed so after a merge and a migration guide this should be ready |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would maybe be a bit nicer if it was harder to turn entities into MainEntity
/RenderEntity
incorrectly (trough .into()
s) and getting typed a typed RenderEntity
back in more places, but that's probably not worth blocking on since we probably want a nicer fix in the long term anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that this is substantially more error resistant. Thank you.
# Objective - Immediate mode gizmos don't have a main world entity but the phase items require `MainEntity` since #15756 ## Solution - Add a dummy `MainEntity` component. ## Testing Both the `3d_gizmos` and `2d_gizmos` examples show gizmos again
objects. PR bevyengine#15756 made us create temporary render entities for all visible objects, even if they had no render world counterpart. This regressed our `many_cubes` time from about 3.59 ms/frame to 4.66 ms/frame. This commit changes that behavior to use `Entity::PLACEHOLDER` instead of creating a temporary render entity. This improves our `many_cubes` time from 5.66 ms/frame to 3.96 ms/frame, a 43% speedup. I tested 3D, 2D gizmos, and UI and they seem to work.
…jects. (#16723) PR #15756 made us create temporary render entities for all visible objects, even if they had no render world counterpart. This regressed our `many_cubes` time from about 3.59 ms/frame to 4.66 ms/frame. This commit changes that behavior to use `Entity::PLACEHOLDER` instead of creating a temporary render entity. This improves our `many_cubes` time from 5.66 ms/frame to 3.96 ms/frame, a 43% speedup. I tested 3D, 2D gizmos, and UI and they seem to work. See the following graph of `many_cubes` frame time (lower is better). PR #15756 is the one in October. 
…jects. (bevyengine#16723) PR bevyengine#15756 made us create temporary render entities for all visible objects, even if they had no render world counterpart. This regressed our `many_cubes` time from about 3.59 ms/frame to 4.66 ms/frame. This commit changes that behavior to use `Entity::PLACEHOLDER` instead of creating a temporary render entity. This improves our `many_cubes` time from 5.66 ms/frame to 3.96 ms/frame, a 43% speedup. I tested 3D, 2D gizmos, and UI and they seem to work. See the following graph of `many_cubes` frame time (lower is better). PR bevyengine#15756 is the one in October. 
…jects. (bevyengine#16723) PR bevyengine#15756 made us create temporary render entities for all visible objects, even if they had no render world counterpart. This regressed our `many_cubes` time from about 3.59 ms/frame to 4.66 ms/frame. This commit changes that behavior to use `Entity::PLACEHOLDER` instead of creating a temporary render entity. This improves our `many_cubes` time from 5.66 ms/frame to 3.96 ms/frame, a 43% speedup. I tested 3D, 2D gizmos, and UI and they seem to work. See the following graph of `many_cubes` frame time (lower is better). PR bevyengine#15756 is the one in October. 
Objective
In the Render World, there are a number of collections that are derived from Main World entities and are used to drive rendering. The most notable are:
VisibleEntities
, which is generated in thecheck_visibility
system and contains visible entities for a view.ExtractedInstances
, which maps entity ids to asset ids.In the old model, these collections were trivially kept in sync -- any extracted phase item could look itself up because the render entity id was guaranteed to always match the corresponding main world id.
After #15320, this became much more complicated, and was leading to a number of subtle bugs in the Render World. The main rendering systems, i.e.
queue_material_meshes
andqueue_material2d_meshes
, follow a similar pattern:In this case,
visible_entities
andrender_mesh_instances
are both collections that are created and keyed by Main World entity ids, and so this lookup happens to work by coincidence. However, there is a major unintentional bug here: namely, becausevisible_entities
is a collection of Main World ids, the phase item being queued is created with a Main World id rather than its correct Render World id.This happens to not break mesh rendering because the render commands used for drawing meshes do not access the
ItemQuery
parameter, but demonstrates the confusion that is now possible: our UI phase items are correctly being queued with Render World ids while our meshes aren't.Additionally, this makes it very easy and error prone to use the wrong entity id to look up things like assets. For example, if instead we ignored visibility checks and queued our meshes via a query, we'd have to be extra careful to use
&MainEntity
instead of the naturalEntity
.Solution
Make all collections that are derived from Main World data use
MainEntity
as their key, to ensure type safety and avoid accidentally looking up data with the wrong entity id:Additionally, we make all
PhaseItem
be able to provide both their Main and Render World ids, to allow render phase implementors maximum flexibility as to what id should be used to look up data.You can think of this like tracking at the type level whether something in the Render World should use it's "primary key", i.e. entity id, or needs to use a foreign key, i.e.
MainEntity
.Testing
TODO:
This will require extensive testing to make sure things didn't break! Additionally, some extraction logic has become more complicated and needs to be checked for regressions.
Migration Guide
With the advent of the retained render world, collections that contain references to
Entity
that are extracted into the render world have been changed to containMainEntity
in order to prevent errors where a render world entity id is used to look up an item by accident. Custom rendering code may need to be changed to query for&MainEntity
in order to look up the correct item from such a collection. Additionally, users who implement their own extraction logic for collections of main world entity should strongly consider extracting into a different collection that usesMainEntity
as a key.Additionally, render phases now require specifying both the
Entity
andMainEntity
for a givenPhaseItem
. Custom render phases should ensureMainEntity
is available when queuing a phase item.