[Mesa-dev] [PATCH 05/16] st/nine: Workaround barycentrics issue on some cards

Axel Davy axel.davy at ens.fr
Fri Apr 24 13:09:34 PDT 2015


Signed-off-by: Axel Davy <axel.davy at ens.fr>
---
 src/gallium/state_trackers/nine/device9.c    |  4 +++-
 src/gallium/state_trackers/nine/device9.h    |  4 ++++
 src/gallium/state_trackers/nine/nine_state.c | 24 ++++++++++++++++++++++++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c
index 43eb7e6..9ca1bb9 100644
--- a/src/gallium/state_trackers/nine/device9.c
+++ b/src/gallium/state_trackers/nine/device9.c
@@ -310,8 +310,10 @@ NineDevice9_ctor( struct NineDevice9 *This,
             return E_OUTOFMEMORY;
 
         if (strstr(pScreen->get_name(pScreen), "AMD") ||
-            strstr(pScreen->get_name(pScreen), "ATI"))
+            strstr(pScreen->get_name(pScreen), "ATI")) {
             This->prefer_user_constbuf = TRUE;
+            This->driver_bugs.buggy_barycentrics = TRUE;
+        }
 
         tmpl.target = PIPE_BUFFER;
         tmpl.format = PIPE_FORMAT_R8_UNORM;
diff --git a/src/gallium/state_trackers/nine/device9.h b/src/gallium/state_trackers/nine/device9.h
index f412088..d662f83 100644
--- a/src/gallium/state_trackers/nine/device9.h
+++ b/src/gallium/state_trackers/nine/device9.h
@@ -118,6 +118,10 @@ struct NineDevice9
         boolean ps_integer;
     } driver_caps;
 
+    struct {
+        boolean buggy_barycentrics;
+    } driver_bugs;
+
     struct u_upload_mgr *upload;
 
     struct nine_range_pool range_pool;
diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c
index 495cc86..6c7eab3 100644
--- a/src/gallium/state_trackers/nine/nine_state.c
+++ b/src/gallium/state_trackers/nine/nine_state.c
@@ -150,6 +150,30 @@ update_viewport(struct NineDevice9 *device)
     pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y;
     pvport.translate[2] = vport->MinZ;
 
+    /* We found R600 and SI cards have some imprecision
+     * on the barycentric coordinates used for interpolation.
+     * Some shaders rely on having something precise.
+     * We found that the proprietary driver has the imprecision issue,
+     * except when the render target width and height are powers of two.
+     * It is using some sort of workaround for these cases
+     * which covers likely all the cases the applications rely
+     * on something precise.
+     * We haven't found the workaround, but it seems like it's better
+     * for applications if the imprecision is biased towards infinity
+     * instead of -infinity (which is what measured). So shift slightly
+     * the viewport: not enough to change rasterization result (in particular
+     * for multisampling), but enough to make the imprecision biased
+     * towards infinity. We do this shift only if render target width and
+     * height are powers of two.
+     * Solves 'red shadows' bug on UE3 games.
+     */
+    if (device->driver_bugs.buggy_barycentrics &&
+        ((vport->Width & (vport->Width-1)) == 0) &&
+        ((vport->Height & (vport->Height-1)) == 0)) {
+        pvport.translate[0] -= 1.0f / 128.0f;
+        pvport.translate[1] -= 1.0f / 128.0f;
+    }
+
     pipe->set_viewport_states(pipe, 0, 1, &pvport);
 }
 
-- 
2.1.0



More information about the mesa-dev mailing list