Bug 89012

Summary: Incorrect interpolation on R600 and SI
Product: Mesa Reporter: Axel Davy <davyaxel0>
Component: Drivers/Gallium/radeonsiAssignee: Default DRI bug account <dri-devel>
Status: RESOLVED WONTFIX QA Contact: Default DRI bug account <dri-devel>
Severity: normal    
Priority: medium CC: tizbac2
Version: git   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: result drawn by the test. The bottom triangle is wrong.
Image showing the expected triangle (top, drawn with nouveau), and the triangle got on R600/SI (bottom)
Xnine testcase that checks the output of fract on texcoord.x*16-1/256
Additionnal test
OpenGL version of the testcase

Description Axel Davy 2015-02-06 16:06:16 UTC
Created attachment 113228 [details]
result drawn by the test. The bottom triangle is wrong.

Tested on Evergreen and CAPE VERDE.

Nine uses the rasterize setting half_pixel_center = 0,
which means, as the docs puts it:
"the rasterizer should use (0, 0) pixel centers for determining pixel ownership". This is the mode needed for d3d9.

The hw has a state for that.
For example on SI, PA_SU_VTX_CNTL has PIX_CENTER set to 0 to get this rasterizer mode. The doc says that the hw implements it by adding 0.5. This is the same for R600.

But is seems it requires some other things to work, or that it is buggy, or something else we don't know.

We have some games having bugs because of off by 1 results for the drawing. This causes red shadows for example for Borderlands 2.
Nouveau and llvmpipe don't hit these bugs.

The problem is that the translation seems to suffer precision issue or something.
We tried play a lot with the states for IEEE-> fixed float prevision on the two cards and with FLOAT_ROUND, but that didn't solve the issue.

The problem can be reproduced with the attached demo, using Xnine (you need edit Xnine.c to fix the loading path of the nine module). This attached image show the visual result: on two triangles drawn, one gets off-by one pixels(the one of the bottom). These issues only happen with corner cases vertex positions.

The program also outputs some numbers, and the green ones should show 1,
but on R600 and radeonsi they will show 0.999998. the fact this result is below 1, will make floor result in the wrong number, and causes the off by one pixel issue of the demo.
Comment 1 Axel Davy 2015-02-06 16:07:31 UTC
Created attachment 113229 [details]
Image showing the expected triangle (top, drawn with nouveau), and the triangle got on R600/SI (bottom)
Comment 2 Tiziano Bacocco 2015-02-06 16:31:17 UTC
Created attachment 113231 [details]
Xnine testcase that checks the output of fract on texcoord.x*16-1/256

Beware that the part to d3dadapter9.so is hardcoded so you will need to change it
This testcase renders a quad of two triangles that cover the entire screen ( 256x16) , and outputs what happens with frac along the X axis on the 15th line, where the triangle that has problems lies
Comment 3 Marek Olšák 2015-02-24 18:30:31 UTC
It also seems to be incorrect with half_pixel_center = 1.
Comment 4 Axel Davy 2015-03-08 07:34:28 UTC
With additional tests, we found out the problem comes out from the barycentric coordinates. On one of the triangle, one barycentric coordinate is very slightly below the expected value. It's not just on some pixels, but on all the pixels of the triangle.

We also tested on an r600 card (hd3650), and the bug is the same. However for SI and R600, the handling of the barycentric interpolation seems to have evolved a lot.

Could it be some state that has been forgotten in the doc, that would specify barycentric coordinates rounding ?
Comment 5 Axel Davy 2015-03-21 14:26:55 UTC
Created attachment 114504 [details]
Additionnal test

Additional test that draws a square of size 256 * 24.

The pos coordinates of the square are (-1-(1/256), 1+(1/16)) and (1-(1/256), -1+(1/16))

the first texcoord a is 0 for the left of the square and 1 for the right
the second texcoord b is 0 at the top, 23 at the bottom.

the images shows the b-th bit of the mantisse of a.

On ilo, nouveau and llvmpipe, the image is black, except at the top, where we see some white pixels with a specific scheme.
On radeonsi and r600, the top right triangle is the same than for the others, but the bottom left triangle is almost full white.

This shows that the texcoord a has a value just below what it should have for this triangle. This is the root of the problem, as the game shader with the problem multiplies the texcoord value by a power of two, and then applies floor. Because of this bug, it gets off by one problem.

This 'little below expected value on one of the triangle' problem doesn't depend on the half_pixel_center = 0 parameter. It just happens that for what the game does, the texcoord value with half_pixel_center = 1 instead of 0 (which would be correct value for nine), is above what it should be, and then with the floor, the result is correct and not off by one.
Comment 6 Tiziano Bacocco 2015-03-24 13:32:58 UTC
Created attachment 114582 [details]
OpenGL version of the testcase

The red line at right and bottom is because coords are meant for dx9 raster rules and not opengl ones
To compile GL , GLU, GLEW and GLUT are needed
Comment 7 Marek Olšák 2015-03-31 21:59:56 UTC
This is how the hardware works. Even though it may lead to incorrect rendering sometimes, there is no workaround. This issue has been reported to hardware designers.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.