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

OOM with large font size #58

Closed
elbaro opened this issue Oct 15, 2023 · 7 comments
Closed

OOM with large font size #58

elbaro opened this issue Oct 15, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@elbaro
Copy link

elbaro commented Oct 15, 2023

Rendering a short string with a large font size and large TextArea.scale (still small in 4k monitors) causes AtlasFull.

Relaxing the texture limit to x4, TextAtlas keeps growing until OOM.

let mut limits = wgpu::Limits::default();
limits.max_texture_dimension_2d = 8192 * 4;
let mut buffer =
    glyphon::Buffer::new(&mut font_system, glyphon::Metrics::new(30.0, 42.0));
buffer.set_size(&mut font_system, 600.0, 500.0);
buffer.set_text(
    &mut font_system,
    " 🦅 glyphon 🦁\nThe text x y z",
    glyphon::Attrs::new().family(glyphon::Family::SansSerif),
    glyphon::Shaping::Advanced,
);
buffer.shape_until_scroll(&mut font_system);
text_renderer.prepare(
    device,
    queue,
    &mut font_system,
    &mut atlas,
    glyphon::Resolution {
        width: 800,
        height: 600,
    },
    [glyphon::TextArea {
        buffer: &buffer,
        left: 100.0,
        top: 100.0,
        scale: 10.0,
        bounds: glyphon::TextBounds {
            left: 100,
            top: 100,
            right: 600,
            bottom: 600,
        },
        default_color: glyphon::Color::rgb(0, 0, 0),
    }],
    &mut cache,
)
.unwrap();
text_renderer.render(&atlas, &mut render_pass).unwrap();
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:474] content_type = Color
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:475] did_grow = true
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:130] self.size = 26880
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:131] self.max_texture_dimension_2d = 32768

[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:474] content_type = Color
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:475] did_grow = true
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:130] self.size = 27136
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:131] self.max_texture_dimension_2d = 32768

[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:474] content_type = Color
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:475] did_grow = true
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:130] self.size = 27392
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:131] self.max_texture_dimension_2d = 32768

thread 'main' panicked at .cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.17.1/src/backend/direct.rs:3056:5:
wgpu error: Validation Error

Caused by:
    In Device::create_texture
      note: label = `glyphon atlas`
    Not enough memory left

But then reducing TextArea.scale from 10 to 5 renders fine with only size=256.
Why does scale=10 use x100 more memory than scale=5?

[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:130] self.size = 256
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:131] self.max_texture_dimension_2d = 32768
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:474] content_type = Color
[.cargo/git/checkouts/glyphon-bce1d8fb6a1f7cb1/9e25714/src/text_atlas.rs:475] did_grow = true
@grovesNL
Copy link
Owner

For individual glyph memory allocation scale is basically a multiplier on the font size for rasterization, so switching between 5 and 10 requires more space in both width and height. Happy to look into this to see if we're trying to reserve more space in the atlas than necessary though. We could also look at using multiple atlas textures or an atlas with multiple layers if necessary, but really large fonts are going to be tricky to handle in general.

Just curious, but what's the reason you're trying to use a large scale like 10 instead of changing the font size (through Metrics)?

@grovesNL grovesNL added the question Further information is requested label Oct 15, 2023
@elbaro
Copy link
Author

elbaro commented Oct 15, 2023

Nothing special about scale, I get the same OOM with scale=1 and glyphon::Metrics::new(30.0 * 10.0, 42.0 * 10.0), while Metrics::new(30.0 * 5.0, 42.0 * 5.0) uses very small memory.

The former uses more than 10GiB VRAM and the latter uses only 20MiB.

Here is a code: https://github.com/elbaro/glyphon-58

@grovesNL
Copy link
Owner

Thanks for the test case! There seems to be a problem somewhere when we're growing the atlas for large glyphs. It might have something to do with not being able to fit any glyphs into INITIAL_SIZE but I need to look into this some more.

It looks like you can work around this for now by changing the atlas INITIAL_SIZE to some higher value at

const INITIAL_SIZE: u32 = 256;

@grovesNL
Copy link
Owner

grovesNL commented Oct 16, 2023

This seems like a problem in etagere when we grow the atlas. etagere ends up using multiple columns of the original width of 256, so anything wider than 256 will always fail to allocate.

Specifically the allocation fails during https://github.com/nical/etagere/blob/95d6f376fa85a265fd4493a0bf371777196b33b4/src/bucketed.rs#L172 because requested_size.width is 299 for one of the emojis, while self.column_width is 256.

I'll try to get this fixed upstream soon but you should be able to use the INITIAL_SIZE work around for now. The out-of-memory happens because we keep trying to grow the atlas until the allocation succeeds, but it never does.

@grovesNL
Copy link
Owner

Opened nical/etagere#26 upstream to track this

@grovesNL grovesNL added bug Something isn't working and removed question Further information is requested labels Oct 16, 2023
@grovesNL
Copy link
Owner

grovesNL commented Nov 6, 2023

I've fixed nical/etagere#26 upstream but it will need a new release before we see those changes (or you could use a patch to use the git version).

I'll keep this open for now though, because I also want to slightly change the growth strategy to reduce the amount of resizes we have to do to support bigger glyphs (probably just multiplying dimensions by a factor instead resizing by a constant amount each time).

@grovesNL
Copy link
Owner

grovesNL commented Jan 16, 2024

The growth strategy has also been changed in #74 so we can close this now. A new release with these changes has been released (0.4.1).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants