Writing the sync down in code
Last week was the design. This week is less talk, more code. I worked out that the copy and the render need to take turns over one shared counter, and drew the handshake on paper. This week I wrote it.
Most of the work was small and mechanical once the shape was clear. The interop now gets a little struct with two numbers in it: the value the copy should wait for, and the value it signals when it is done. The display side owns the counter. Each frame it holds the plane images back from libplacebo to raise the counter to N, passes N into the copy, the interop waits for N, copies, and signals N+1, then the display releases the images to wait on N+1. That is the whole loop, and it is the same six steps from last week, just in real code now.
Making sure it is actually correct
A sync bug is invisible when it goes your way, and on my machine it went my way every time. So I did not trust "the video looks fine." I turned on the validation layer with synchronization checking, which watches every semaphore and complains the moment two operations touch the same image without an ordering between them. I ran a 4K NVDEC file through the whole path with it on. It printed nothing.
To be sure the counter was doing real work and not just sitting at zero, I read it back each frame. It increaed the way it should.
The first time each slot is used, its image is brand new and libplacebo hands it over already held, so there is no hold to do and the frame only bumps the counter by one. That happens four times, once per slot. After that every frame is a reuse, with two holds plus the signal, so the counter climbs by three. Seeing that shape in the numbers was a nice confirmation that the ring and the fences were both behaving.
Here is the MR with all my work (if you are reading this later, some of this week's commits may be force-pushed and reordered, so the exact history might look different): here
Did you enjoy this article?
Comments(0)
Leave a comment
No comments yet. Be the first to share your thoughts!
