st/nine: Workaround barycentrics issue on some cards
Signed-off-by: Axel Davy <axel.davy@ens.fr>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user