llvmpipe: Implement alpha_to_coverage for non-MSAA framebuffers.

Implement Alpha to Coverage by discarding a fragment alpha component is
less than 0.5.  This is a joint work of Jose and Si.

Reviewed-by: José Fonseca <jfonseca@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:
Si Chen 2013-12-18 02:17:55 -08:00 committed by José Fonseca
parent 2a0fb946e1
commit 72c6d0e506
3 changed files with 59 additions and 1 deletions

View file

@ -30,6 +30,11 @@
#include "gallivm/lp_bld_type.h"
#include "gallivm/lp_bld_arit.h"
#include "gallivm/lp_bld_const.h"
#include "gallivm/lp_bld_logic.h"
#include "gallivm/lp_bld_swizzle.h"
#include "gallivm/lp_bld_flow.h"
#include "gallivm/lp_bld_debug.h"
#include "lp_bld_blend.h"
@ -191,3 +196,28 @@ lp_build_blend(struct lp_build_context *bld,
dst_term = lp_build_mul(bld, dst, dst_factor);
return lp_build_blend_func(bld, func, src_term, dst_term);
}
void
lp_build_alpha_to_coverage(struct gallivm_state *gallivm,
struct lp_type type,
struct lp_build_mask_context *mask,
LLVMValueRef alpha,
boolean do_branch)
{
struct lp_build_context bld;
LLVMValueRef test;
LLVMValueRef alpha_ref_value;
lp_build_context_init(&bld, gallivm, type);
alpha_ref_value = lp_build_const_vec(gallivm, type, 0.5);
test = lp_build_cmp(&bld, PIPE_FUNC_GREATER, alpha, alpha_ref_value);
lp_build_name(test, "alpha_to_coverage");
lp_build_mask_update(mask, test);
if (do_branch)
lp_build_mask_check(mask);
}

View file

@ -38,6 +38,7 @@
struct pipe_blend_state;
struct lp_type;
struct lp_build_context;
struct lp_build_mask_context;
LLVMValueRef
@ -99,5 +100,11 @@ lp_build_blend_func_reverse(unsigned rgb_func,
boolean
lp_build_blend_func_commutative(unsigned func);
void
lp_build_alpha_to_coverage(struct gallivm_state *gallivm,
struct lp_type type,
struct lp_build_mask_context *mask,
LLVMValueRef alpha,
boolean do_branch);
#endif /* !LP_BLD_BLEND_H */

View file

@ -296,7 +296,9 @@ generate_fs_loop(struct gallivm_state *gallivm,
assert(zs_format_desc);
if (!shader->info.base.writes_z) {
if (key->alpha.enabled || shader->info.base.uses_kill) {
if (key->alpha.enabled ||
key->blend.alpha_to_coverage ||
shader->info.base.uses_kill) {
/* With alpha test and kill, can do the depth test early
* and hopefully eliminate some quads. But need to do a
* special deferred depth write once the final mask value
@ -438,6 +440,21 @@ generate_fs_loop(struct gallivm_state *gallivm,
}
}
/* Emulate Alpha to Coverage with Alpha test */
if (key->blend.alpha_to_coverage) {
int color0 = find_output_by_semantic(&shader->info.base,
TGSI_SEMANTIC_COLOR,
0);
if (color0 != -1 && outputs[color0][3]) {
LLVMValueRef alpha = LLVMBuildLoad(builder, outputs[color0][3], "alpha");
lp_build_alpha_to_coverage(gallivm, type,
&mask, alpha,
(depth_mode & LATE_DEPTH_TEST) != 0);
}
}
/* Late Z test */
if (depth_mode & LATE_DEPTH_TEST) {
int pos0 = find_output_by_semantic(&shader->info.base,
@ -2426,6 +2443,9 @@ dump_fs_variant_key(const struct lp_fragment_shader_variant_key *key)
debug_printf("blend.alpha_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_dst_factor, TRUE));
}
debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask);
if (key->blend.alpha_to_coverage) {
debug_printf("blend.alpha_to_coverage is enabled\n");
}
for (i = 0; i < key->nr_samplers; ++i) {
const struct lp_static_sampler_state *sampler = &key->state[i].sampler_state;
debug_printf("sampler[%u] = \n", i);
@ -2521,6 +2541,7 @@ generate_variant(struct llvmpipe_context *lp,
fullcolormask &&
!key->stencil[0].enabled &&
!key->alpha.enabled &&
!key->blend.alpha_to_coverage &&
!key->depth.enabled &&
!shader->info.base.uses_kill
? TRUE : FALSE;