https://bugs.freedesktop.org/show_bug.cgi?id=108824
Bug ID: 108824 Summary: Invalid handling when GL buffer is bound on one context and invalidated on another Product: Mesa Version: git Hardware: x86-64 (AMD64) OS: Linux (All) Status: NEW Severity: normal Priority: medium Component: Drivers/Gallium/radeonsi Assignee: dri-devel@lists.freedesktop.org Reporter: baldurk@baldurk.org QA Contact: dri-devel@lists.freedesktop.org
Created attachment 142556 --> https://bugs.freedesktop.org/attachment.cgi?id=142556&action=edit piglit test showing broken behaviour
I found some odd behaviour that I think I've tracked down to some incorrect handling of buffer invalidation in radeonsi.
The rough order of events is:
1. Create a buffer that's shared between two contexts. Ensure it's bound as a UBO on both. 2. Invalidate the buffer with e.g. glMapBufferRange(GL_MAP_INVALIDATE_BUFFER_BIT) on context A. 3. Context B's buffer bind is now in a bad state. Rendering will have unpredictable results, and invalidating the buffer again on context B may fail.
That's a bit vague but that's the general repro that I know for sure. This will then result in unpredictable reads/garbage data, and quite likely you'll eventually hit the assert on src/gallium/drivers/radeonsi/si_descriptors.c:1489 - assert(old_buf_va <= old_desc_va);
My understanding is that the radeonsi code will look through all bound buffers whenever an invalidate happens, fixup the descriptors by subtracting the descriptor's VA from the outgoing VA for the old buffer to get the offset, then add it onto the incoming VA and update the descriptor.
The problem seems to be that when this happens for a buffer invalidate it only checks the current context's bound buffers - so other contexts don't have their descriptors updated. That means the old VA is still being pointed at, and if an invalidate happens again on the second thread the descriptor is referring to an even older VA than the outgoing VA so there's no longer any sense in the subtract call.
I've attached a piglit test which hopefully should drop right in, it runs through the steps above and does a pixel readback to ensure the rendering went correctly. If you remove the readback you can see flickering output. It runs fine with both the readback and the rendering if I switch to swrast.
I'm on an RX 480 and tested the bug with both git-61b535437e and 18.2.4 from padoka's PPA.