radeonsi: add shader code for smoothing
authorMarek Olšák <marek.olsak@amd.com>
Sun, 15 Mar 2015 17:11:19 +0000 (18:11 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 16 Mar 2015 11:54:19 +0000 (12:54 +0100)
The fragment shader multiplies the alpha channel with gl_SampleMaskIn.
If blending is enabled, it looks like MSAA.

Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader.h

index 1496d5fedd7f516e0e1cb251c2ce8af9fc1b95b0..1bc664a50ec4f37e4c16bc5ee01f9737bb608025 100644 (file)
@@ -41,6 +41,7 @@
  * the number shouldn't be a commonly-used one. */
 #define SI_BASE_VERTEX_UNKNOWN INT_MIN
 #define SI_RESTART_INDEX_UNKNOWN INT_MIN
+#define SI_NUM_SMOOTH_AA_SAMPLES 8
 
 #define SI_TRACE_CS 0
 #define SI_TRACE_CS_DWORDS             6
index a57fdf4e1bdd506ae40dd2e803ba2f9c7f82dba8..2703704a7fe9027db9b431ffc4d3d488541532ee 100644 (file)
@@ -644,7 +644,12 @@ static void declare_system_value(
        }
 
        case TGSI_SEMANTIC_SAMPLEMASK:
-               value = LLVMGetParam(radeon_bld->main_fn, SI_PARAM_SAMPLE_COVERAGE);
+               /* Smoothing isn't MSAA in GL, but it's MSAA in hardware.
+                * Therefore, force gl_SampleMaskIn to 1 for GL. */
+               if (si_shader_ctx->shader->key.ps.poly_line_smoothing)
+                       value = uint_bld->one;
+               else
+                       value = LLVMGetParam(radeon_bld->main_fn, SI_PARAM_SAMPLE_COVERAGE);
                break;
 
        default:
@@ -828,6 +833,34 @@ static void si_alpha_test(struct lp_build_tgsi_context *bld_base,
        si_shader_ctx->shader->db_shader_control |= S_02880C_KILL_ENABLE(1);
 }
 
+static void si_scale_alpha_by_sample_mask(struct lp_build_tgsi_context *bld_base,
+                                         LLVMValueRef alpha_ptr)
+{
+       struct si_shader_context *si_shader_ctx = si_shader_context(bld_base);
+       struct gallivm_state *gallivm = bld_base->base.gallivm;
+       LLVMValueRef coverage, alpha;
+
+       /* alpha = alpha * popcount(coverage) / SI_NUM_SMOOTH_AA_SAMPLES */
+       coverage = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn,
+                               SI_PARAM_SAMPLE_COVERAGE);
+       coverage = bitcast(bld_base, TGSI_TYPE_SIGNED, coverage);
+
+       coverage = build_intrinsic(gallivm->builder, "llvm.ctpop.i32",
+                                  bld_base->int_bld.elem_type,
+                                  &coverage, 1, LLVMReadNoneAttribute);
+
+       coverage = LLVMBuildUIToFP(gallivm->builder, coverage,
+                                  bld_base->base.elem_type, "");
+
+       coverage = LLVMBuildFMul(gallivm->builder, coverage,
+                                lp_build_const_float(gallivm,
+                                       1.0 / SI_NUM_SMOOTH_AA_SAMPLES), "");
+
+       alpha = LLVMBuildLoad(gallivm->builder, alpha_ptr, "");
+       alpha = LLVMBuildFMul(gallivm->builder, alpha, coverage, "");
+       LLVMBuildStore(gallivm->builder, alpha, alpha_ptr);
+}
+
 static void si_llvm_emit_clipvertex(struct lp_build_tgsi_context * bld_base,
                                    LLVMValueRef (*pos)[9], LLVMValueRef *out_elts)
 {
@@ -1361,6 +1394,9 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base)
                        if (semantic_index == 0 &&
                            si_shader_ctx->shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS)
                                si_alpha_test(bld_base, alpha_ptr);
+
+                       if (si_shader_ctx->shader->key.ps.poly_line_smoothing)
+                               si_scale_alpha_by_sample_mask(bld_base, alpha_ptr);
                        break;
                default:
                        target = 0;
index 4f2bb9111600be556167fd5d00bb2fd9136a93ab..5b602ac342801ed985f22801ae95d33a38799117 100644 (file)
@@ -126,6 +126,7 @@ union si_shader_key {
                unsigned        alpha_func:3;
                unsigned        alpha_to_one:1;
                unsigned        poly_stipple:1;
+               unsigned        poly_line_smoothing:1;
        } ps;
        struct {
                unsigned        instance_divisors[SI_NUM_VERTEX_BUFFERS];