hakolao / egui_winit_vulkano

Egui gui integration with winit and vulkano
Apache License 2.0
79 stars 40 forks source link

Dynamic font format to minimize mem/work #54

Closed Fuzzyzilla closed 9 months ago

Fuzzyzilla commented 9 months ago

Egui Font textures are single-channel images representing linear coverage of white. This PR takes advantage of this to reduce texture and staging memory usage by 4x on supporting devices (~90% coverage according to gpuinfo.org) while providing fallbacks for non-supporting devices and portability subset devices, as well as reducing the work required to upload these images (elides a sqrt per pixel on the host side).

Comparing all four possible image formats implemented here, which prioritize memory footprint and then prioritize work reduction, the visual differences are subtle. This is because egui's font_image.srgba_pixels(None) is an approximation of Linear->sRGB so the new implementation is likely strictly more correct by skipping this and using the linear coverage directly. Notably, R8_SRGB/R8G8B8A8_SRG are in perfect parity with each other and current master, and R8_UNORM/R8G8B8A8_UNORM are in perfect parity with each other providing a slightly higher contrast which I believe is a more correct result.

I have more work I would like to contribute to the image uploading process which could reduce temporary host memory allocation by an extra ~2x and elide a number of copies, if that would be appreciated! ^^ To avoid conflicts though, I would like to receive feedback on this before setting off on that journey.

Fuzzyzilla commented 9 months ago

Immediately after posting this I noticed a regression in the subpass example :sweat_smile: Will work on that!

hakolao commented 9 months ago

I have more work I would like to contribute to the image uploading process Sounds good! I'd do that in a separate PR.

This pr also looks fine, I'll test it at some point this week. But do let me know when it should be ready!

Fuzzyzilla commented 9 months ago

After noticing the regression and learning a lot about how egui wants color management to be done, I have managed to emulate the expected behavior using a larger format. Cuts the savings in half, but better than nothing I suppose! In the shader, egui expects the RGB to be linear but the alpha to be nonlinear strangely. Using RG_UNORM I have emulated this using linear R, nonlinear G, and swizzling up to RRRG.

It now looks correct in transparent contexts.

The small contrast disparity between the original sRGB and smaller swizzled format due to the approximate behavior of srgba_pixels is still visible but I still believe that is expected behavior.

hakolao commented 9 months ago

Seems that the old transparent was wrong to begin with.