-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Error loading two different texture atlases back to back #1056
Comments
Just wanted to chime in that I have the exact same problem on Bevy 0.4.0 on Arch Linux. I have nearly exactly the same code, 2 sprite texture atlases and not much more. I'm trying to learn Bevy so I'm just playing with the examples. |
Same issue here, Bevy 0.4.0/master on wasm after adding a second sprite atlas to the mix. |
couldn't reproduce on macOS with master adapting example sprite_sheet.rs, either with using the same sprite sheet or using two different Code used```rust use bevy::prelude::*;fn main() { fn animate_sprite_system( fn setup(
|
I tried for a minimal reproduction but failed. But I managed to get my project back into a state where the intermittent panic is happening again. Sometime in the wee hours last night I moved one of the sprite sheet loads into a different system and it just stopped happening for whatever reason. https:/rparrett/taipo/tree/spritesheet-panic
Also using rust 1.49.0 on a mac to compile the thing in case that makes a difference. |
Here is another example, I think I got it down to as minimal as it get 😄 Here is the main.rs use bevy::prelude::*;
fn setup(
asset_server: Res<AssetServer>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
) {
let texture_handle = asset_server.load("hero.png");
let texture_atlas = TextureAtlas::from_grid(texture_handle, Vec2::new(16.0, 16.0), 2, 4);
let _texture_atlas_handle = texture_atlases.add(texture_atlas);
let tiles_handle = asset_server.load("alltiles.png");
let tiles_texture_atlas = TextureAtlas::from_grid(tiles_handle, Vec2::new(16.0, 16.0), 3, 59);
let _tiles_atlas_handle = texture_atlases.add(tiles_texture_atlas);
}
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.run();
} Running it with Rust 1.49.0 on Arch Linux. |
I'm currently seeing this error again despite
after introducing several new texture atlases. So #1208 may not be fixing the problem entirely. It's possible that I'm doing something silly with the atlases or Cargo.toml, but as far as I can tell, the patch is working.
I threw the code online at https:/rparrett/taipo/tree/spritesheet-panic-two but I'm finding the panic to be stubbornly resisting my attempts to create an easier/faster way to reproduce it. It panics pretty reliably, but only as I am actively playing the game and building towers while enemies are moving/spawning. So that's probably not useful to anybody.
|
This really just defies reproduction. Curiously, in my case, maybe high dpi text is a factor? Or something else related to scaling. I wrote quick puppeteer script to play the game a bit, and absolutely could not reproduce this until I added Without that, puppeteer runs the game in an 800x600 viewport, so it is not scaled. This currently reproduces the issue on my system shortly after the third crab starts taking damage, about 120 seconds into play. https:/rparrett/taipo-puppeteer/blob/main/index.js Again, probably not useful to anyone, but might get me closer to producing a real test case of some sort. |
I'm leaving this open until we are sure the issue is actually resolved. |
I won't be able to dig back into this for a little while, but I rebuilt with c434f57 and re-ran my puppeteer script and saw a panic in the same spot, at the same time. Only new insight is that there's probably a small non-spritesheet sprite (shuriken) being despawned at that exact time or very close to it. |
Managed to capture a big ol' stack trace, in case that's helpful. Curiously, the panic occurs in debug builds, but 20 seconds further into the game well after the last crab in the first wave has died. |
Got the game running natively to confirm that it's not wasm-only. Here's a log with tracing included. This consistently seems to happen immediately after pressing enter to complete a "typing target," but nothing interesting should be happening with sprites or spritesheets at that time. 3 text fields get updated and presumably some flex layout stuff might be going on. I can't really make sense of the bevy_render traces, but maybe there's something interesting in there. edit: swapped pastebin link for one with the entire frame (but this frame is pretty much only processing that one event though, I think) |
The one interesting thing I am doing with fonts, which isn't very interesting is that I am using two fonts. There's one small font that gets loaded for some text on the loading screen. And another 4mb thing with all the JP glyphs that's used for literally everything else. After the game is loaded, the loading screen is despawned and that first font is never used again. (But the handle is held onto forever) However, as a quick test, I just swapped that small font's name for the big one in its load call, and the panic doesn't seem to happen anymore. So that'll be the avenue I explore if I'm able to later tonight. |
I plowed into Where we seem to be creating new larger buffers for resources with non-aligned buffer sizes, but maybe not making space in the staging buffer for them? I'm 98% sure though that the above sentence is nonsense because I have no idea what's going on in there. I attempted a few fixes based on that theory, but was unsuccessful. Instead I de-wasmed my game and wrote a new plugin that makes it automatically play itself until it panics. I hope someone with better rendering credentials might take pity on me and check it out. I do think this might have something to do with UI text as well. It seems like the various text fields actually getting updated/turned green is important to reproducing the panic. |
Here is a much more minimal reproduction of this (or a very similar) panic using text only. |
I pushed a commit to the branch above that reproduces the same panic in a very simple system. The gist is that I render a bunch of different glyphs in a single text bundle, one at a time. 14 seconds in (on my system) it panics. If I understand text rendering properly, this may still be some sort of a "multiple texture atlases" issue. |
The required staging buffer size is already properly calculated in prepare_staging_buffers(). Whenever a resize was needed, this value got overwritten by set_required_staging_buffer_size_to_max(), which computed the wrong (smaller) size. This in turn prevented the staging buffers from being resized in resize_staging_buffer(). By removing set_required_staging_buffer_size_to_max() entiery, the value from prepare_staging_buffers() is used.
This should be fixed by #1509, could you please try it out and see if the problem disappears for good? |
The required_staging_buffer_size is currently calculated differently in two places, each will be correct in different situations: * prepare_staging_buffers() based on actual buffer_byte_len() * set_required_staging_buffer_size_to_max() based on item_size Up to this commit, and in case of a resize, the latter always took precedence, even if the resulting buffer size would be smaller than calculated by the former. This commit always uses the largest calculated size.
* prepare_uniform_buffers() now computes the required uniform buffer size over all assets, rather than just changed ones. * set_required_staging_buffer_size_to_max() now doesn't overwrite the value computed by prepare_uniform_buffers() if the resulting size would be smaller.
* when doing a full asset copy (resize), prepare_uniform_buffers() is now called on all assets rather than just changed ones. This makes sure the staging buffer is large enough. * set_required_staging_buffer_size_to_max() now doesn't overwrite the value computed by prepare_uniform_buffers() if the resulting size would be smaller. Co-authored-by: François <[email protected]>
* when doing a full asset copy (resize), prepare_uniform_buffers() is now called on all assets rather than just changed ones. This makes sure the staging buffer is large enough. * set_required_staging_buffer_size_to_max() now doesn't overwrite the value computed by prepare_uniform_buffers() if the resulting size would be smaller. Co-authored-by: François <[email protected]>
* when doing a full asset copy (resize), prepare_uniform_buffers() is now called on all assets rather than just changed ones. This makes sure the staging buffer is large enough. * set_required_staging_buffer_size_to_max() now doesn't overwrite the value computed by prepare_uniform_buffers() if the resulting size would be smaller. Co-authored-by: Renato Caldas <[email protected]> Co-authored-by: François <[email protected]>
Bevy version
0.3.0 509b138
Operating system & version
Windows 10
What you did
Load 2 sprite texture atlas back to back in the setup like so... (This is a modified version of the sprite_sheet.rs example that is not animated and loads an additional and different sprite sheet.)
I am not sure if a specific sprite sheet is required to trigger the error.
Note: The error can be inconsistent to trigger.
use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.run();
}
fn setup(
commands: &mut Commands,
asset_server: Res,
mut texture_atlases: ResMut<Assets>,
) {
}
What you expected to happen
No crash
What actually happened
An error occurred.
thread 'main' panicked at 'range end index 1768 out of range for slice of length 1024', ...\bevy\crates\bevy_render\src\render_graph\nodes\render_resources_node.rs:336:26
Additional information
Error occurs in render_resources_node.rs file
I am not too familiar with rendering code, but after doing some investigating, the first part of the problem occurs in the loop in (lines 681-687). In the loop, when the prepare_uniform_buffers() function is called, it updates the field required_staging_buffer_size field with the size required determined by the byte len of the buffer. The problem is that if one of the render_resource buffer byte len differs from the buffer_array's item size then if the buffer array needs to be resized then it will resize the buffer to a value less than what is needed because the buffer_arrays item size is not correct.
The second part of the issue seems to be caused by the set_required_staging_buffer_size_to_max() function in the render_resources_node.rs file called from line ~692 in the same file. The required_staging_buffer_size field is updated/resized with a size that is less than what the buffer requires. This is because the item_size field is incorrect and so when the new_size is calculated (by multiplying the buffer len), it is less than what is required by the buffer.
For example, the prepare_uniform_buffers() is called and the required_staging_buffer_size is set to a new size of 8 + 1760 to get a value of 1768 for the buffer. The buffer_array.item_size = 256. Then when the set_required_staging_buffer_size_to_max() is called, it will update/resize the required_staging_buffer_size to item_size(256) * buffer_len(4) = 1024. The error will happen because of this, 1768 > 1024 and an index out of range will occur down the line.
Seems to me that the item_size for the buffer_array needs to be updated properly.
The text was updated successfully, but these errors were encountered: