[Mesa-dev] Bugs in fbo-sys-blit (problems with fake front and missing invalidates)
Paul Berry
stereotype441 at gmail.com
Wed May 29 13:39:00 PDT 2013
I started this discussion with just some of the Intel folks, and Eric
suggested I bring it to the mesa-dev list.
The short version is: in my efforts to implement fast color clears on Intel
hardware, I've uncovered some problems with the fbo-sys-blit piglit test,
which I've traced to 3 bugs. I could use some help with bug (2) below,
which I suspect is a bug in the X server.
---------- Forwarded message (footnotes added) ----------
First of all, a brief summary of what fbo-sys-blit's piglit_display() does:
a. Clear the back buffer to green.
b. Copy the back buffer to the front buffer using a blit.
c. Clear the back buffer to red.
d. Read the contents of the front buffer to verify that it's green.
I've found three bugs:
1. Background: when a fake front buffer is in use, if Mesa requests the
front buffer (using screen->dri2.loader->getBuffersWithFormat()), the X
server copies the real front buffer to the fake front buffer and returns
the fake front buffer. Mesa sometimes makes redundant requests for the
front buffer (due to using a single counter to track invalidates for both
the front and back buffers), so there's a danger of pending front buffer
rendering getting overwritten when the redundant front buffer request
occurs. To work around this problem, intel_update_renderbuffers()
sometimes does intel_flush() and intel_flush_front() before calling
intel_query_dri2_buffers(). The problem is, it only does the workaround
when the front buffer is bound for drawing; it doesn't do it when the front
buffer is bound for reading. As a result, in step (d) above, the fake
front buffer gets overwritten with the contents of the real front buffer
(which contains garbage). This is why fbo-sys-blit fails sporadically
during automated piglit runs; frequently the garbage happens to be green,
but sometimes it doesn't.
2. Normally the way intel_prepare_render() finds out whether it needs to
call intel_update_renderbuffers() is that it gets an "invalidate" signal
from the X server (this is processed by DRI2WireToEvent()). This happens
whenever the window is resized or a buffer swap occurs, but it doesn't
consistently happen when the window gets exposed on the screen for the
first time (even though this causes new front and back buffers to be
allocated*). Currently, when running in non-"auto" mode, the piglit
framework calls piglit_display() once before the window gets exposed, and
then again in response to the Expose event.** Therefore, when running
fbo-sys-blit, on the second call to piglit_display(), Mesa sometimes
doesn't get the message that there are new buffers, so the clear in step
(a) goes to an old garbage buffer. Mesa decides to query the buffers
before executing step (b), so garbage data gets copied from back to front.
This causes fbo-sys-blit to fail sporadically when run manually, even if I
fix bug (1) above.***
3. intelClear() and brw_clear() set intel->front_buffer_dirty before
calling intel_prepare_render(). This is wrong: if intel_prepare_render()
gets a fresh front buffer from the X server, it will reset
front_buffer_dirty to false, so the front buffer won't get properly marked
as dirty. Fortunately intel_prepare_render() also sets front_buffer_dirty
to true if the front buffer is bound for drawing, which means that this bug
will only manifest when using glClearBuffer() to clear the front buffer
while the back buffer is bound (probably very rare). I found this bug by
code inspection; I haven't verified it yet.
I'll submit patches to the list to fix bugs (1) and (3). I don't know how
to tackle bug (2) and I'm hoping someone more knowledgeable about X server
internals can have a look.
*I don't know what code is allocating the new front and back buffers; I
just know from examining data in the debugger that it's happened (since the
buffer names have changed). Note that I'm running my tests with a
compositing desktop (Gnome 3), so it's possible that this is the
compositor's doing.
**Eric pointed out that this is a bug in Piglit, since on non-compositing
desktops the front buffer isn't guaranteed to exist until after the Expose
event. I'm hoping to send out patches to fix this Piglit bug soon. Note:
I believe that even on non-compositing desktops, the back buffer is still
guaranteed to exist before the Expose event, so the only Piglit tests that
need to be fixed to wait for the Expose event are those that access the
front buffer, for example fbo-sys-blit. Please correct me if I have this
wrong.
***Note that fixing the above Piglit bug won't make bug (2) go away. In
fact it will make bug (2) affect both "-auto" and manual testing (currently
it only affects manual testing). The reason for this is that Mesa queries
the back buffer during intelMakeCurrent() (which happens before the Expose
event). So step (a) will always clear the old (defunct) back buffer, and
then Mesa will receive the new back buffer just before doing the blit in
step (b), and will blit garbage to the front buffer.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20130529/1e3a9495/attachment.html>
More information about the mesa-dev
mailing list