mirror of
https://github.com/par274/sharpemu.git
synced 2026-08-06 01:49:47 +08:00
4b5ea6a793
On GFX10 a colour clear is not a packet. The driver programs CB_COLORn_CLEAR_WORD0/1 and draws a covering quad which the colour block turns into DCC clear codes, discarding whatever the pixel shader exported. We executed that quad as an ordinary draw, so the shaded output landed in the surface instead of a clear. That alone would be a wrong-pixels bug, but the blend those quads use makes it compound. Every draw into the target blends src=ONE, dst=ONE_MINUS_SRC_ALPHA, so alpha follows a <- a_src + a_dst*(1 - a_src), whose fixed point is 1. A guest colour attachment is cleared once on first use and loaded on every pass after, so nothing ever resets it and the channel climbs until it saturates. Where such a surface is a compositing layer, the final image is ui.rgb + scene.rgb*(1 - ui.a) and a saturated alpha multiplies the scene away entirely - the scene renders correctly the whole time and is then masked to black. Recognise the clear and perform it: the attachment is reset and the quad is dropped, which reproduces the observable effect without modelling DCC block state. The reset drops the image's Initialized flag so the next render pass clears via AttachmentLoadOp.Clear, rather than enqueuing a CmdClearColorImage - the latter lands outside the following render pass, and a target cleared that way was still observed reading back its previous contents. Restricted to clear-to-zero: the reset clears to zero, so a nonzero CLEAR_WORD would be cleared to the wrong colour and is left to be drawn. Zero is zero under every encoding the register pair can carry, so the test needs no format handling. The clip-space span test is load-bearing rather than defensive. Fills sharing the vertex count, topology and blend outnumber the clears by two orders of magnitude and sit well outside the frame; treating those as clears erases the UI and blanks video surfaces.