diff options
author | Axel Davy <[email protected]> | 2015-04-23 21:46:09 +0200 |
---|---|---|
committer | Axel Davy <[email protected]> | 2015-04-29 08:28:10 +0200 |
commit | 6e825b69bd4fb163cba0a565616ed966fb1a8929 (patch) | |
tree | 53a71d1e26160551677e044ca9202368873f5e63 /src/gallium | |
parent | f3fd06e94d29172a5de68594d3a6433f91a41362 (diff) |
st/nine: Workaround barycentrics issue on some cards
Signed-off-by: Axel Davy <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/state_trackers/nine/device9.c | 4 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/device9.h | 4 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_state.c | 24 |
3 files changed, 31 insertions, 1 deletions
diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c index 43eb7e6397c..9ca1bb93597 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 f412088ca08..d662f839d88 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 495cc862b2a..6c7eab3c25c 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); } |