diff options
author | Ilia Mirkin <imirkin@alum.mit.edu> | 2016-06-19 16:57:50 -0400 |
---|---|---|
committer | Ilia Mirkin <imirkin@alum.mit.edu> | 2016-07-16 11:45:30 -0400 |
commit | 062c6b8e54c14adcc1ec603fad524f38fe058e67 (patch) | |
tree | bcb4774e8d9225d7f8bf557f299061f310f6f85f /src/gallium/drivers/nouveau/nv50/nv50_shader_state.c | |
parent | cc46fc3c0921c86baa0fbe25ba6a9c4858f04ab3 (diff) | |
download | external_mesa3d-062c6b8e54c14adcc1ec603fad524f38fe058e67.zip external_mesa3d-062c6b8e54c14adcc1ec603fad524f38fe058e67.tar.gz external_mesa3d-062c6b8e54c14adcc1ec603fad524f38fe058e67.tar.bz2 |
nv50: fix alphatest for non-blendable formats
The hardware can only do alphatest when using a blendable format. This
means that the various *16 norm formats didn't work with alphatest. It
appears that Talos Principle uses such formats, as well as alpha tests,
for some internal renders, which made them be incorrect. However this
does not appear to affect the final renders, but in a different game it
easily could.
The approach we take is that when alphatests are enabled and a suitable
format is used (which we anticipate is the vast minority of the time),
we insert code into the shader to perform the comparison and discard.
Once inserted, that code lives in the shader forever, and we re-upload
it each time the function changes with a fixed-up compare. To avoid
re-uploading too often, if we switch back to a blendable format, the
test is (effectively) disabled and the hw alphatest functionality is
used.
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Diffstat (limited to 'src/gallium/drivers/nouveau/nv50/nv50_shader_state.c')
-rw-r--r-- | src/gallium/drivers/nouveau/nv50/nv50_shader_state.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c index 2326394..d234748 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c @@ -174,6 +174,42 @@ nv50_fragprog_validate(struct nv50_context *nv50) struct nv50_program *fp = nv50->fragprog; struct pipe_rasterizer_state *rast = &nv50->rast->pipe; + if (nv50->zsa && nv50->zsa->pipe.alpha.enabled) { + struct pipe_framebuffer_state *fb = &nv50->framebuffer; + bool blendable = fb->nr_cbufs == 0 || !fb->cbufs[0] || + nv50->screen->base.base.is_format_supported( + &nv50->screen->base.base, + fb->cbufs[0]->format, + fb->cbufs[0]->texture->target, + fb->cbufs[0]->texture->nr_samples, + PIPE_BIND_BLENDABLE); + /* If we already have alphatest code, we have to keep updating + * it. However we only have to have different code if the current RT0 is + * non-blendable. Otherwise we just set it to always pass and use the + * hardware alpha test. + */ + if (fp->fp.alphatest || !blendable) { + uint8_t alphatest = PIPE_FUNC_ALWAYS + 1; + if (!blendable) + alphatest = nv50->zsa->pipe.alpha.func + 1; + if (!fp->fp.alphatest) + nv50_program_destroy(nv50, fp); + else if (fp->mem && fp->fp.alphatest != alphatest) + nouveau_heap_free(&fp->mem); + + fp->fp.alphatest = alphatest; + } + } else if (fp->fp.alphatest && fp->fp.alphatest != PIPE_FUNC_ALWAYS + 1) { + /* Alpha test is disabled but we have a shader where it's filled + * in. Make sure to reset the function to 'always', otherwise it'll end + * up discarding fragments incorrectly. + */ + if (fp->mem) + nouveau_heap_free(&fp->mem); + + fp->fp.alphatest = PIPE_FUNC_ALWAYS + 1; + } + if (fp->fp.force_persample_interp != rast->force_persample_interp) { /* Force the program to be reuploaded, which will trigger interp fixups * to get applied |