emilk / egui

egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native
https://www.egui.rs/
Apache License 2.0
22.15k stars 1.6k forks source link

Difference in rendering on windows, linux and macOS #5295

Open lucasmerlin opened 1 day ago

lucasmerlin commented 1 day ago

It seems like there are some minor rendering differences between the different egui_wgpu backends. I don't think this is a general problem and I doubt that it's possible to avoid these differences, but I want to document the findings somewhere. These differences currently cause the snapshots tests to fail on windows and linux, but we should be able to increase the dify threshold until the tests run through. Visually the images are the same, I couldn't spot any difference when flipping back and forth between snapshots rendered by the different platforms.

Here is an example diff (the snapshot was rendered on MacOS and the diff on linux):

widget_gallery diff

It seems like the difference is mostly on outlines of text and shapes, maybe related to anti aliasing or feathering?

More diffs

Bezier demo (snapshot on macos and diff on linux) ![image](https://github.com/user-attachments/assets/97a39917-59d6-48b9-ae55-a26af6fa3779) Widget gallery diff (this time the diff was rendered on windows): ![image](https://github.com/user-attachments/assets/bf62a9c7-8027-4f2a-b3b1-b2fb8a8e92e3) Widget gallery snapshot from windows: ![image](https://github.com/user-attachments/assets/1792ad45-4b2a-4195-9352-7bf00abf0b82) Widget gallery snapshot from macOS: ![widget_gallery new](https://github.com/user-attachments/assets/12dd59bc-ffc3-4562-a330-205de8c073e2)

Setting the threshold to 0.6 seems to fix all tests except for the bezier demo on linux which seems to need a threshold of 2.1.

Shoutout to @fluxxcode who helped me test this on the different platforms

Wumpf commented 23 hours ago

For texture sampling in particular this is pretty much expected since different hardware (sometimes even different via driver or driver settings) texture filtering is implemented subtly different. This is mostly due to differences in how they're optimized - texture units typically don't filter in f32 but in their origin format.

Afaik it used to be also a problem with rasterization itself, but with DX11 came more strict rasterization rules, although iirc that can still be a problem with mobile hardware sometimes and when dealing with old GL drivers.

Wumpf commented 23 hours ago

Failed to find an article on the general rendering difference between gpu - you'd think someone looked into this deeper at some point 🤔. It's mostly a thing I experienced when working with other screenshot comparision tests, tons of things are always subtly different between the vendors, sometimes even drivers.

However, I dug up this great article from iq where he describes the difference between manual and hardware bilinear filtering (which in his particular usecase makes a huge difference) https://iquilezles.org/articles/hwinterpolation/

Wumpf commented 23 hours ago

Since egui/eframes's gpu rendering portion is intentionally very limited, texture filtering might be close to the only source of discrepancies. But I'd be surprised if a manual filter would get rid of differences entirely