From 6e825b69bd4fb163cba0a565616ed966fb1a8929 Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Thu, 23 Apr 2015 21:46:09 +0200 Subject: [PATCH] st/nine: Workaround barycentrics issue on some cards Signed-off-by: Axel Davy --- 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.7.4