When I started using my new M1 Max MacBook Pro in December, a bunch of vpype’s tests started to fail. The failing tests were all image-based: an image is rendered and then compared to a previously-generated, reference image. This process is made easy thanks to this Pytest fixture.
In this case, the reference images were generated long ago on my previous, Intel/AMD-based MacBook Pro. This GIF highlights the discrepancy I’d get with images generated on my new computer (notice how the ruler’s thickness varies):
As I’m currently working on this viewer again, I finally spent two days tracking this issue – and finally found its cause.
Without giving it a thought, I first used integer coordinates for those ruler lines. However, coordinates refer to pixel boundaries – not pixel centres. This means than an horizontal line with integer coordinates (e.g.
[(2, 2), (7, 2)]) sits halfway between two consecutive rows of pixel:
Which of the 2nd or 3rd row of pixel eventually gets drawn is up to a coin toss – or rather the rounding strategy of your particular OpenGL driver/GPU/OS combination.
By offsetting the coordinates by half a pixel (e.g.
[(2, 2.5), (7, 2.5)]), one can force the line on a specific pixel row and avoid any rounding:
This makes the rendering more predictable across platforms.
Ultimately, the fix was very simple (I just changed the ruler thickness from
19.5), but figuring it out was tricky (relevant discussions on ModernGL’s Discord server). Hopefully I wont forget about it after writing this TIL.