<div dir="ltr"><div><div>On Tue, May 9, 2017 at 2:13 PM, Nicolai Hähnle <<a href="mailto:nhaehnle@gmail.com" target="_blank">nhaehnle@gmail.com</a>> wrote:<br>> Hi all,<br>><br>> I'm seeing some very strange errors on Verde with CPU readback from GART,<br>> and am pretty much out of ideas. Some help would be very much appreciated.<br>><br>> The error manifests with the<br>> GL45-CTS.gtf32.GL3Tests.<wbr>packed_pixels.packed_pixels_<wbr>pbo test on amdgpu, but<br>> *not* on radeon. Here's what the test does:<br>><br>> 1. Upload a texture.<br>> 2. Read the texture back via a shader that uses shader buffer writes to<br>> write data to a buffer that is allocated in GART.<br>> 3. The CPU then reads from the buffer -- and sometimes gets stale data.<br>><br>> This sequence is repeated for many sub-tests. There are some sub-tests where<br>> the CPU reads stale data from the buffer, i.e. the shader writes simply<br>> don't make it to the CPU. The tests vary superficially, e.g. the first<br>> failing test is (almost?) always one where data is written in 16-bit words<br>> (but there are succeeding sub-tests with 16-bit writes as well).<br>><br>> The bug is *not* a timing issue. Adding even a 1sec delay (sleep(1);)<br>> between the fence wait and the return of glMapBuffer does not fix the<br>> problem. The data must be stuck in a cache somewhere.<br>><br>> Since the test runs okay with the radeon module, I tried some changes based<br>> on comparing the IB submit between radeon and amdgpu, and based on comparing<br>> register settings via scans obtained from umr. Some of the things I've<br>> tried:<br>><br>> - Set HDP_MISC_CNTL.FLUSH_<wbr>INVALIDATE_CACHE to 1 (both radeon and amdgpu/gfx9<br>> set this)<br>> - Add SURFACE_SYNC packets preceded by setting CP_COHER_CNTL2 to the vmid<br>> (radeon does this)<br>> - Change gfx_v6_0_ring_emit_hdp_<wbr>invalidate: select ME engine instead of PFP<br>> (which seems more logical, and is done by gfx7+), or remove the<br>> corresponding WRITE_DATA entirely<br>><br>> None of these changes helped.<br>><br>> What *does* help is adding an artificial wait. Specifically, I'm adding a<br>> sequence of<br>><br>> - WRITE_DATA<br>> - CACHE_FLUSH_AND_INV_TS_EVENT (BOTTOM_OF_PIPE_TS has same behavior)<br>> - WAIT_REG_MEM<br>><br>> as can be seen in the attached patch. This works around the problem, but it<br>> makes no sense:<br>><br>> Adding the wait sequence *before* the SURFACE_SYNC in ring_emit_fence works<br>> around the problem. However(!) it does not actually cause the UMD to wait<br>> any longer than before. Without this change, the UMD immediately sees a<br>> signaled user fence (and never uses an ioctl to wait), and with this change,<br>> it *still* sees a signaled user fence.<br>><br>> Also, note that the way I've hacked the change, the wait sequence is only<br>> added for the user fence emit (and I'm using a modified UMD to ensure that<br>> there is enough memory to be used by the added wait sequence).<br>><br>> Adding the wait sequence *after* the SURFACE_SYNC *doesn't* work around the<br>> problem.<br>><br>> So for whatever reason, the added wait sequence *before* the SURFACE_SYNC<br>> encourages some part of the GPU to flush the data from wherever it's stuck,<br>> and that's just really bizarre. There must be something really simple I'm<br>> missing, and any pointers would be appreciated.<br><br>Have you tried this?<br><br>diff --git a/src/gallium/drivers/<wbr>radeonsi/si_hw_context.c b/src/gallium/drivers/<wbr>radeonsi/si_hw_context.c<br>index 92c09cb..e6ac0ba 100644<br>--- a/src/gallium/drivers/<wbr>radeonsi/si_hw_context.c<br>+++ b/src/gallium/drivers/<wbr>radeonsi/si_hw_context.c<br>@@ -133,7 +133,8 @@ void si_context_gfx_flush(void *context, unsigned flags,<br>                        SI_CONTEXT_PS_PARTIAL_FLUSH;<br> <br>        /* DRM 3.1.0 doesn't flush TC for VI correctly. */<br>-       if (ctx->b.chip_class == VI && ctx->b.screen->info.drm_minor <= 1)<br>+       if ((ctx->b.chip_class == VI && ctx->b.screen->info.drm_minor <= 1) ||<br>+           (ctx->b.chip_class == SI && ctx->b.screen->info.drm_major == 3))<br>                ctx->b.flags |= SI_CONTEXT_INV_GLOBAL_L2 |<br>                                SI_CONTEXT_INV_VMEM_L1;<br><br></div>One more cache flush there shouldn't hurt.<br><br></div><div>Also, Mesa uses PFP_SYNC_ME. It shouldn't be necessary, but it's worth a try.<br></div><div><br></div>Marek<br></div>