-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Throttle render assets #12622
Throttle render assets #12622
Conversation
Is this about saving CPU time, or GPU/PCIE transfers? For the former, we should move render asset preparation to background tasks (I wish we had a better way to mark systems as background instead of having to manually spawn tasks from a system). I have an issue open for this. For the latter, yeah I think we need separate hardware queues. But I can see the value of this until then. |
it's about transfers. currently if you load a bunch of large renderassets the whole app stalls in |
actually now you say that i'm not sure... |
I just tried upgrading this to main. It's pretty simple, just need to do the same trick used for asset_usage where the param is I tested it in a simple app that just spawns a bunch of helmets to see how it would behave and it doesn't seem to do anything. It still spawns every helmet at the same time with a major stutter. I never see the exhausted debug log. Maybe I broke something while porting it. The code seems like it should work though, so not sure what I'm missing. |
thanks for updating it - just making sure, you did add the resource as well? something like i definitely see the impact on 0.13 and can't see any reason it should have changed with the flip to implementing RenderAsset on targets ... although in my scenario images are by far the largest part of the problem, possibly i messed up the mesh size calculation. |
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
Yeah, I did insert the resource, but I did it in a separate branch where I copied code manually so I may have missed something |
I tested again based on the branch before the changes and it did work, so I probably messed up something when I was copying the code. With the fix I suggested all that will be needed is to merge main I think. |
ok cool, i'll go through properly at some point this weekend. |
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
i got a bit tangled up with the merge so i just applied the changes onto a new branch and merged it in (with a couple of tweaks). i can't really test very well since my project is not on main - i tried with 20 copies of the flight helmet and it seems to throttle correctly according to the debug output, but its not really enough data to see the impact visually. |
tried on a project I have that loads 65536 meshes with their textures, this works as expected. Bevy freezes without setting throttling.mp4 |
Co-authored-by: François Mockers <francois.mockers@vleue.com>
@mockersf can we add this as a cargo example? I may work on further asset loading perf improvements in the future, and it would be amazing to have this as a test bench. |
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.
LGTM
Would be nice to have a large_asset_loading example or something like that, but I don't want to block this PR on that.
I can do that in a few days, but it'll definitely never be merged in Bevy given how ugly it is 😄
I can try to get something prettier (and smaller) than what I currently have later |
let mut param = param.into_inner(); | ||
let queued_assets = std::mem::take(&mut prepare_next_frame.assets); | ||
for (id, extracted_asset) in queued_assets { | ||
if extracted_assets.removed.contains(&id) { | ||
if extracted_assets.removed.contains(&id) || extracted_assets.added.contains(&id) { |
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.
What is the purpose of skipping newly added assets here?
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.
This is the retry loop for assets that were previously extracted and were not ready in the previous frame. If the asset has been added again, there are now 2 versions and we don’t want to prepare the old one.
This was the source of the font bug I had where some characters would not render:
The code in prepare_sprites clears its cache on asset change events, then checks for presence in RenderAssets to repopulate the cache. If we prepare the old version then the code in the sprite module will see it as ready and will cache the previous version, resulting in the old asset being permanently bound for some glyphs.
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.
Ahhh, makes sense. Could you add a comment about this?
@@ -161,13 +170,15 @@ impl<A: RenderAsset> RenderAssetDependency for A { | |||
pub struct ExtractedAssets<A: RenderAsset> { | |||
extracted: Vec<(AssetId<A::SourceAsset>, A::SourceAsset)>, | |||
removed: Vec<AssetId<A::SourceAsset>>, | |||
added: Vec<AssetId<A::SourceAsset>>, |
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.
Should be a HashSet over a Vec.
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.
Good point, will change this and removed
as well
# Objective - Since #12622 example `compute_shader_game_of_life` crashes ``` thread 'Compute Task Pool (2)' panicked at examples/shader/compute_shader_game_of_life.rs:137:65: called `Option::unwrap()` on a `None` value note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Encountered a panic in system `compute_shader_game_of_life::prepare_bind_group`! thread '<unnamed>' panicked at examples/shader/compute_shader_game_of_life.rs:254:34: Requested resource compute_shader_game_of_life::GameOfLifeImageBindGroups does not exist in the `World`. Did you forget to add it using `app.insert_resource` / `app.init_resource`? Resources are also implicitly added via `app.add_event`, and can be added by plugins. Encountered a panic in system `bevy_render::renderer::render_system`! ``` ## Solution - `exhausted()` now checks that there is a limit
Objective
allow throttling of gpu uploads to prevent choppy framerate when many textures/meshes are loaded in.
Solution
RenderAsset
s can implementbyte_len()
which reports their size. implemented this forMesh
andImage
RenderAssetBytesPerFrame
which specifies max bytes to attempt to upload in a framerender_assets::<A>
checks how many bytes have been written before attempting to upload assets. the limit is a soft cap: assets will be written until the total has exceeded the cap, to ensure some forward progress every framenotes:
issues
fonts sometimes only partially upload. i have no clue why, needs to be fixedfixed now.RenderAssetBytesPerFrame
is explicitly used though