llvmpipe: add centroid interpolation support.
authorDave Airlie <airlied@redhat.com>
Thu, 19 Mar 2020 05:24:11 +0000 (15:24 +1000)
committerMarge Bot <eric+marge@anholt.net>
Wed, 6 May 2020 06:20:37 +0000 (06:20 +0000)
This just adds the implementation and API to the interpolation builders.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4122>

src/gallium/drivers/llvmpipe/lp_bld_interp.c
src/gallium/drivers/llvmpipe/lp_bld_interp.h
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 9f6b577a9ee25f443fb314a12f0598b6e5284561..6ca163f5a189c7d5c70e6ec1194d1d78e8042c26 100644 (file)
@@ -43,6 +43,8 @@
 #include "gallivm/lp_bld_arit.h"
 #include "gallivm/lp_bld_swizzle.h"
 #include "gallivm/lp_bld_flow.h"
+#include "gallivm/lp_bld_logic.h"
+#include "gallivm/lp_bld_struct.h"
 #include "lp_bld_interp.h"
 
 
@@ -238,6 +240,7 @@ static void
 attribs_update_simple(struct lp_build_interp_soa_context *bld,
                       struct gallivm_state *gallivm,
                       LLVMValueRef loop_iter,
+                      LLVMValueRef mask_store,
                       int start,
                       int end)
 {
@@ -266,6 +269,7 @@ attribs_update_simple(struct lp_build_interp_soa_context *bld,
    for (attrib = start; attrib < end; attrib++) {
       const unsigned mask = bld->mask[attrib];
       const unsigned interp = bld->interp[attrib];
+      const unsigned loc = bld->interp_loc[attrib];
       unsigned chan;
 
       for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
@@ -274,6 +278,7 @@ attribs_update_simple(struct lp_build_interp_soa_context *bld,
             LLVMValueRef dadx = coeff_bld->zero;
             LLVMValueRef dady = coeff_bld->zero;
             LLVMValueRef a = coeff_bld->zero;
+            LLVMValueRef chan_pixoffx = pixoffx, chan_pixoffy = pixoffy;
 
             index = lp_build_const_int32(gallivm, chan);
             switch (interp) {
@@ -303,12 +308,50 @@ attribs_update_simple(struct lp_build_interp_soa_context *bld,
                   a = lp_build_extract_broadcast(gallivm, setup_bld->type,
                                                  coeff_bld->type, bld->a0aos[attrib],
                                                  index);
+
+                  if (bld->coverage_samples > 1) {
+                     LLVMValueRef xoffset = lp_build_const_vec(gallivm, coeff_bld->type, bld->pos_offset);
+                     LLVMValueRef yoffset = lp_build_const_vec(gallivm, coeff_bld->type, bld->pos_offset);
+                     if (loc == TGSI_INTERPOLATE_LOC_CENTROID) {
+                        LLVMValueRef centroid_x_offset = lp_build_const_vec(gallivm, coeff_bld->type, bld->pos_offset);
+                        LLVMValueRef centroid_y_offset = lp_build_const_vec(gallivm, coeff_bld->type, bld->pos_offset);
+
+                        /* for centroid find covered samples for this quad. */
+                        /* if all samples are covered use pixel centers */
+                        LLVMValueRef s_mask_and = NULL;
+                        for (int s = bld->coverage_samples - 1; s >= 0; s--) {
+                           LLVMValueRef sample_cov;
+                           LLVMValueRef s_mask_idx = LLVMBuildMul(builder, bld->num_loop, lp_build_const_int32(gallivm, s), "");
+
+                           s_mask_idx = LLVMBuildAdd(builder, s_mask_idx, loop_iter, "");
+                           sample_cov = lp_build_pointer_get(builder, mask_store, s_mask_idx);
+                           if (s == bld->coverage_samples - 1)
+                              s_mask_and = sample_cov;
+                           else
+                              s_mask_and = LLVMBuildAnd(builder, s_mask_and, sample_cov, "");
+
+                           LLVMValueRef x_val_idx = lp_build_const_int32(gallivm, s * 2);
+                           LLVMValueRef y_val_idx = lp_build_const_int32(gallivm, s * 2 + 1);
+
+                           x_val_idx = LLVMBuildGEP(builder, bld->sample_pos_array, &x_val_idx, 1, "");
+                           y_val_idx = LLVMBuildGEP(builder, bld->sample_pos_array, &y_val_idx, 1, "");
+                           x_val_idx = lp_build_broadcast_scalar(coeff_bld, LLVMBuildLoad(builder, x_val_idx, ""));
+                           y_val_idx = lp_build_broadcast_scalar(coeff_bld, LLVMBuildLoad(builder, y_val_idx, ""));
+                           centroid_x_offset = lp_build_select(coeff_bld, sample_cov, x_val_idx, centroid_x_offset);
+                           centroid_y_offset = lp_build_select(coeff_bld, sample_cov, y_val_idx, centroid_y_offset);
+                        }
+                        xoffset = lp_build_select(coeff_bld, s_mask_and, xoffset, centroid_x_offset);
+                        yoffset = lp_build_select(coeff_bld, s_mask_and, yoffset, centroid_y_offset);
+                     }
+                     chan_pixoffx = lp_build_add(coeff_bld, chan_pixoffx, xoffset);
+                     chan_pixoffy = lp_build_add(coeff_bld, chan_pixoffy, yoffset);
+                  }
                }
                /*
                 * a = a0 + (x * dadx + y * dady)
                 */
-               a = lp_build_fmuladd(builder, dadx, pixoffx, a);
-               a = lp_build_fmuladd(builder, dady, pixoffy, a);
+               a = lp_build_fmuladd(builder, dadx, chan_pixoffx, a);
+               a = lp_build_fmuladd(builder, dady, chan_pixoffy, a);
 
                if (interp == LP_INTERP_PERSPECTIVE) {
                   if (oow == NULL) {
@@ -693,6 +736,9 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
                          unsigned num_inputs,
                          const struct lp_shader_input *inputs,
                          boolean pixel_center_integer,
+                         unsigned coverage_samples,
+                         LLVMValueRef sample_pos_array,
+                         LLVMValueRef num_loop,
                          boolean depth_clamp,
                          LLVMBuilderRef builder,
                          struct lp_type type,
@@ -758,6 +804,9 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
       bld->pos_offset = 0.5;
    }
    bld->depth_clamp = depth_clamp;
+   bld->coverage_samples = coverage_samples;
+   bld->num_loop = num_loop;
+   bld->sample_pos_array = sample_pos_array;
 
    pos_init(bld, x0, y0);
 
@@ -809,10 +858,11 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
 void
 lp_build_interp_soa_update_inputs_dyn(struct lp_build_interp_soa_context *bld,
                                       struct gallivm_state *gallivm,
-                                      LLVMValueRef quad_start_index)
+                                      LLVMValueRef quad_start_index,
+                                      LLVMValueRef mask_store)
 {
    if (bld->simple_interp) {
-      attribs_update_simple(bld, gallivm, quad_start_index, 1, bld->num_attribs);
+      attribs_update_simple(bld, gallivm, quad_start_index, mask_store, 1, bld->num_attribs);
    }
    else {
       attribs_update(bld, gallivm, quad_start_index, 1, bld->num_attribs);
@@ -825,7 +875,7 @@ lp_build_interp_soa_update_pos_dyn(struct lp_build_interp_soa_context *bld,
                                    LLVMValueRef quad_start_index)
 {
    if (bld->simple_interp) {
-      attribs_update_simple(bld, gallivm, quad_start_index, 0, 1);
+      attribs_update_simple(bld, gallivm, quad_start_index, NULL, 0, 1);
    }
    else {
       attribs_update(bld, gallivm, quad_start_index, 0, 1);
index 867a95e41d87930fc7262e37965b8917b2c55a90..d2efdef1f45b92eff6658dc9ad5e9e4353f1b60d 100644 (file)
@@ -90,6 +90,9 @@ struct lp_build_interp_soa_context
    boolean depth_clamp;
 
    double pos_offset;
+   unsigned coverage_samples;
+   LLVMValueRef num_loop;
+   LLVMValueRef sample_pos_array;
 
    LLVMValueRef x;
    LLVMValueRef y;
@@ -119,6 +122,9 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
                          unsigned num_inputs,
                          const struct lp_shader_input *inputs,
                          boolean pixel_center_integer,
+                         unsigned coverage_samples,
+                         LLVMValueRef sample_pos_array,
+                         LLVMValueRef num_loop,
                          boolean depth_clamp,
                          LLVMBuilderRef builder,
                          struct lp_type type,
@@ -131,7 +137,8 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
 void
 lp_build_interp_soa_update_inputs_dyn(struct lp_build_interp_soa_context *bld,
                                       struct gallivm_state *gallivm,
-                                      LLVMValueRef quad_start_index);
+                                      LLVMValueRef quad_start_index,
+                                      LLVMValueRef mask_store);
 
 void
 lp_build_interp_soa_update_pos_dyn(struct lp_build_interp_soa_context *bld,
index 93da53340e66e312cb7efc51462fa0c92f705f5e..aace89507ae71ac519b152b154326a2ff9c5df0c 100644 (file)
@@ -492,7 +492,7 @@ generate_fs_loop(struct gallivm_state *gallivm,
          lp_build_mask_check(&mask);
    }
 
-   lp_build_interp_soa_update_inputs_dyn(interp, gallivm, loop_state.counter);
+   lp_build_interp_soa_update_inputs_dyn(interp, gallivm, loop_state.counter, NULL);
 
    struct lp_build_tgsi_params params;
    memset(&params, 0, sizeof(params));
@@ -2653,6 +2653,7 @@ generate_fragment(struct llvmpipe_context *lp,
                                shader->info.base.num_inputs,
                                inputs,
                                pixel_center_integer,
+                               1, NULL, num_loop,
                                key->depth_clamp,
                                builder, fs_type,
                                a0_ptr, dadx_ptr, dady_ptr,