[Mesa-dev] [PATCH 1/2] [rfc] gallivm/llvmpipe dynamic samplers support. (v2)

Dave Airlie airlied at gmail.com
Thu Apr 21 02:35:03 UTC 2016


From: Dave Airlie <airlied at redhat.com>

This is a first attempt at adding support for dynamic indexing
of samplers to llvmpipe. This is needed for ARB_gpu_shader5 support.

This uses the sampler function generator to generate functions
for all samplers, then uses if statements to pick which one to call.

This passes all the tests in piglit except a couple of non-uniform
tests.

v2: still doesn't pass non-uniform but attempts to get first active
unit in the exec mask and use the sampler index from it.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/gallium/auxiliary/draw/draw_llvm.c            |  4 +--
 src/gallium/auxiliary/draw/draw_llvm.h            |  2 +-
 src/gallium/auxiliary/draw/draw_llvm_sample.c     | 33 ++++++++++++++++++----
 src/gallium/auxiliary/gallivm/lp_bld_sample.h     |  2 ++
 src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c | 22 +++++++++++----
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   | 33 +++++++++++++++++++++-
 src/gallium/drivers/llvmpipe/lp_state_fs.c        |  2 +-
 src/gallium/drivers/llvmpipe/lp_tex_sample.c      | 34 +++++++++++++++++++----
 src/gallium/drivers/llvmpipe/lp_tex_sample.h      |  3 +-
 9 files changed, 113 insertions(+), 22 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 9c68d4f..d8418fc 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -1678,7 +1678,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
    LLVMBuildStore(builder, lp_build_zero(gallivm, lp_int_type(vs_type)), clipmask_bool_ptr);
 
    /* code generated texture sampling */
-   sampler = draw_llvm_sampler_soa_create(draw_llvm_variant_key_samplers(key));
+   sampler = draw_llvm_sampler_soa_create(draw_llvm_variant_key_samplers(key), key->nr_samplers);
 
    if (elts) {
       start = zero;
@@ -2210,7 +2210,7 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
       draw_gs_jit_context_num_constants(variant->gallivm, context_ptr);
 
    /* code generated texture sampling */
-   sampler = draw_llvm_sampler_soa_create(variant->key.samplers);
+   sampler = draw_llvm_sampler_soa_create(variant->key.samplers, variant->key.nr_samplers);
 
    mask_val = generate_mask_value(variant, gs_type);
    lp_build_mask_begin(&mask, gallivm, gs_type, mask_val);
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index 271433c..4231333 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -520,7 +520,7 @@ void
 draw_gs_llvm_dump_variant_key(struct draw_gs_llvm_variant_key *key);
 
 struct lp_build_sampler_soa *
-draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state);
+draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state, int num_samplers);
 
 void
 draw_llvm_set_sampler_state(struct draw_context *draw, unsigned shader_stage);
diff --git a/src/gallium/auxiliary/draw/draw_llvm_sample.c b/src/gallium/auxiliary/draw/draw_llvm_sample.c
index 7e25918..f482bf7 100644
--- a/src/gallium/auxiliary/draw/draw_llvm_sample.c
+++ b/src/gallium/auxiliary/draw/draw_llvm_sample.c
@@ -37,6 +37,7 @@
 #include "gallivm/lp_bld_type.h"
 #include "gallivm/lp_bld_sample.h"
 #include "gallivm/lp_bld_tgsi.h"
+#include "gallivm/lp_bld_flow.h"
 
 
 #include "util/u_debug.h"
@@ -58,6 +59,7 @@ struct draw_llvm_sampler_dynamic_state
 {
    struct lp_sampler_dynamic_state base;
 
+   int num_samplers;
    const struct draw_sampler_static_state *static_state;
 };
 
@@ -236,10 +238,29 @@ draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
    assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
    assert(sampler_index < PIPE_MAX_SAMPLERS);
 
-   lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state,
-                       &sampler->dynamic_state.static_state[sampler_index].sampler_state,
-                       &sampler->dynamic_state.base,
-                       gallivm, params);
+   if (!params->sampler_is_indirect) {
+      lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state,
+                          &sampler->dynamic_state.static_state[sampler_index].sampler_state,
+                          &sampler->dynamic_state.base,
+                          gallivm, params);
+   } else {
+      int i;
+      for (i = 0; i < 4; i++)
+         params->texel[i] = lp_build_alloca(gallivm, lp_build_vec_type(gallivm, params->type), "tex_store");
+
+      for (i = 0; i < sampler->dynamic_state.num_samplers; i++) {
+         struct lp_sampler_params unit_params = *params;
+
+         unit_params.texture_index = i;
+         unit_params.sampler_index = i;
+         lp_build_sample_soa(&sampler->dynamic_state.static_state[i].texture_state,
+                             &sampler->dynamic_state.static_state[i].sampler_state,
+                             &sampler->dynamic_state.base,
+                             gallivm, &unit_params);
+      }
+      for (i = 0; i < 4; i++)
+         params->texel[i] = LLVMBuildLoad(gallivm->builder, params->texel[i], "");
+   }
 }
 
 
@@ -262,7 +283,7 @@ draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
 }
 
 struct lp_build_sampler_soa *
-draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state)
+draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state, int num_samplers)
 {
    struct draw_llvm_sampler_soa *sampler;
 
@@ -287,7 +308,7 @@ draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_stat
    sampler->dynamic_state.base.lod_bias = draw_llvm_sampler_lod_bias;
    sampler->dynamic_state.base.border_color = draw_llvm_sampler_border_color;
    sampler->dynamic_state.static_state = static_state;
-
+   sampler->dynamic_state.num_samplers = num_samplers;
    return &sampler->base;
 }
 
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
index aecce14..010e985 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
@@ -108,6 +108,8 @@ struct lp_sampler_params
    LLVMValueRef lod;
    const struct lp_derivatives *derivs;
    LLVMValueRef *texel;
+   LLVMValueRef indirect_index;
+   bool sampler_is_indirect;
 };
 
 struct lp_sampler_size_query_params
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index 70d977d..3ef278f 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -3185,7 +3185,6 @@ lp_build_sample_gen_func(struct gallivm_state *gallivm,
    gallivm_verify_function(gallivm, function);
 }
 
-
 /**
  * Call the matching function for texture sampling.
  * If there's no match, generate a new one.
@@ -3215,6 +3214,7 @@ lp_build_sample_soa_func(struct gallivm_state *gallivm,
    const struct lp_derivatives *derivs = params->derivs;
    enum lp_sampler_lod_control lod_control;
    boolean need_cache = FALSE;
+   struct lp_build_if_state call_if;
 
    lod_control = (sample_key & LP_SAMPLER_LOD_CONTROL_MASK) >>
                     LP_SAMPLER_LOD_CONTROL_SHIFT;
@@ -3317,7 +3317,6 @@ lp_build_sample_soa_func(struct gallivm_state *gallivm,
                                num_param,
                                sample_key);
    }
-
    num_args = 0;
    args[num_args++] = params->context_ptr;
    if (need_cache) {
@@ -3350,13 +3349,26 @@ lp_build_sample_soa_func(struct gallivm_state *gallivm,
 
    assert(num_args <= LP_MAX_TEX_FUNC_ARGS);
 
+   if (params->sampler_is_indirect) {
+      LLVMValueRef indirect_matches;
+
+      indirect_matches = LLVMBuildICmp(builder, LLVMIntEQ,
+                                       params->indirect_index, lp_build_const_int32(gallivm, params->sampler_index), "");
+      lp_build_if(&call_if, gallivm, indirect_matches);
+   }
    tex_ret = LLVMBuildCall(builder, function, args, num_args, "");
    bb = LLVMGetInsertBlock(builder);
    inst = LLVMGetLastInstruction(bb);
    LLVMSetInstructionCallConv(inst, LLVMFastCallConv);
 
-   for (i = 0; i < 4; i++) {
-      params->texel[i] = LLVMBuildExtractValue(gallivm->builder, tex_ret, i, "");
+   if (params->sampler_is_indirect) {
+      for (i = 0; i < 4; i++)
+         LLVMBuildStore(builder, LLVMBuildExtractValue(builder, tex_ret, i, ""), params->texel[i]);
+      lp_build_endif(&call_if);
+   } else {
+      for (i = 0; i < 4; i++) {
+         params->texel[i] = LLVMBuildExtractValue(gallivm->builder, tex_ret, i, "");
+      }
    }
 }
 
@@ -3407,7 +3419,7 @@ lp_build_sample_soa(const struct lp_static_texture_state *static_texture_state,
              static_texture_state->level_zero_only == TRUE) &&
             static_sampler_state->min_img_filter == static_sampler_state->mag_img_filter);
 
-      use_tex_func = format_desc && !(simple_format && simple_tex);
+      use_tex_func = (format_desc && !(simple_format && simple_tex)) || params->sampler_is_indirect;
    }
 
    if (use_tex_func) {
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index 13fd877..fdba47f 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -65,7 +65,7 @@
 #include "lp_bld_printf.h"
 #include "lp_bld_sample.h"
 #include "lp_bld_struct.h"
-
+#include "lp_bld_intr.h"
 /* SM 4.0 says that subroutines can nest 32 deep and 
  * we need one more for our main function */
 #define LP_MAX_NUM_FUNCS 33
@@ -629,6 +629,29 @@ static void lp_exec_case(struct lp_exec_mask *mask,
    }
 }
 
+static LLVMValueRef lp_exec_mask_get_first_active(struct lp_exec_mask *mask)
+{
+   LLVMBuilderRef builder = mask->bld->gallivm->builder;
+   LLVMValueRef tmps[2];
+
+   /* compare exec_mask against all 1s exec_mask */
+   tmps[0] = LLVMConstAllOnes(mask->int_vec_type);
+   tmps[0] = LLVMBuildICmp(builder, LLVMIntEQ,
+                           mask->exec_mask, tmps[0], "");
+   /* tmp is now 8 x i1 with bits for which exec_mask are active
+    * bitcast to i8
+    */
+   tmps[0] = LLVMBuildBitCast(builder, tmps[0],
+                              lp_build_int_elem_type(mask->bld->gallivm, lp_type_int(8)), "");
+
+   /* get number of trailing zeros which equal bit of first active exec */
+   tmps[1] = lp_build_zero(mask->bld->gallivm, lp_type_int(1));
+   tmps[0] = lp_build_intrinsic(builder, "llvm.cttz.i8",
+                                lp_build_int_elem_type(mask->bld->gallivm, lp_type_int(8)),
+                                tmps, 2, LLVMReadNoneAttribute);
+   return tmps[0];
+}
+
 /*
  * Analyse default statement in a switch.
  * \return true if default is last statement, false otherwise
@@ -2335,6 +2358,14 @@ emit_tex( struct lp_build_tgsi_soa_context *bld,
    params.lod = lod;
    params.texel = texel;
 
+   params.sampler_is_indirect = inst->Src[sampler_reg].Register.Indirect;
+   if (params.sampler_is_indirect) {
+      LLVMValueRef tmp = lp_exec_mask_get_first_active(&bld->exec_mask);
+
+      params.indirect_index = get_indirect_index(bld, inst->Src[sampler_reg].Register.File, inst->Src[sampler_reg].Register.Index, &inst->Src[sampler_reg].Indirect);
+       params.indirect_index = LLVMBuildExtractElement(bld->bld_base.base.gallivm->builder, params.indirect_index, tmp, "");
+   }
+
    bld->sampler->emit_tex_sample(bld->sampler,
                                  bld->bld_base.base.gallivm,
                                  &params);
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 93460a3..f8acd7b 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -2318,7 +2318,7 @@ generate_fragment(struct llvmpipe_context *lp,
    LLVMPositionBuilderAtEnd(builder, block);
 
    /* code generated texture sampling */
-   sampler = lp_llvm_sampler_soa_create(key->state);
+   sampler = lp_llvm_sampler_soa_create(key->state, key->nr_samplers);
 
    num_fs = 16 / fs_type.length; /* number of loops per 4x4 stamp */
    /* for 1d resources only run "upper half" of stamp */
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c
index f002347..e3027a2 100644
--- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c
+++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c
@@ -47,6 +47,7 @@
 #include "gallivm/lp_bld_type.h"
 #include "gallivm/lp_bld_sample.h"
 #include "gallivm/lp_bld_tgsi.h"
+#include "gallivm/lp_bld_flow.h"
 #include "lp_jit.h"
 #include "lp_tex_sample.h"
 #include "lp_state_fs.h"
@@ -64,6 +65,7 @@ struct llvmpipe_sampler_dynamic_state
 {
    struct lp_sampler_dynamic_state base;
 
+   int num_samplers;
    const struct lp_sampler_static_state *static_state;
 };
 
@@ -264,10 +266,30 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
       return;
    }
 
-   lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state,
-                       &sampler->dynamic_state.static_state[sampler_index].sampler_state,
-                       &sampler->dynamic_state.base,
-                       gallivm, params);
+   if (!params->sampler_is_indirect) {
+      lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state,
+                          &sampler->dynamic_state.static_state[sampler_index].sampler_state,
+                          &sampler->dynamic_state.base,
+                          gallivm, params);
+      return;
+   } else {
+      int i;
+      for (i = 0; i < 4; i++)
+         params->texel[i] = lp_build_alloca(gallivm, lp_build_vec_type(gallivm, params->type), "tex_store");
+
+      for (i = 0; i < sampler->dynamic_state.num_samplers; i++) {
+         struct lp_sampler_params unit_params = *params;
+
+         unit_params.texture_index = i;
+         unit_params.sampler_index = i;
+         lp_build_sample_soa(&sampler->dynamic_state.static_state[i].texture_state,
+                             &sampler->dynamic_state.static_state[i].sampler_state,
+                             &sampler->dynamic_state.base,
+                             gallivm, &unit_params);
+      }
+      for (i = 0; i < 4; i++)
+         params->texel[i] = LLVMBuildLoad(gallivm->builder, params->texel[i], "");
+   }
 }
 
 /**
@@ -290,7 +312,8 @@ lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
 
 
 struct lp_build_sampler_soa *
-lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state)
+lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
+                           int num_samplers)
 {
    struct lp_llvm_sampler_soa *sampler;
 
@@ -319,6 +342,7 @@ lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state)
    sampler->dynamic_state.base.cache_ptr = lp_llvm_texture_cache_ptr;
 #endif
 
+   sampler->dynamic_state.num_samplers = num_samplers;
    sampler->dynamic_state.static_state = static_state;
 
    return &sampler->base;
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.h b/src/gallium/drivers/llvmpipe/lp_tex_sample.h
index e26d608..0d4bcac 100644
--- a/src/gallium/drivers/llvmpipe/lp_tex_sample.h
+++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.h
@@ -44,6 +44,7 @@ struct lp_sampler_static_state;
  *
  */
 struct lp_build_sampler_soa *
-lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *key);
+lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *key,
+                           int num_samplers);
 
 #endif /* LP_TEX_SAMPLE_H */
-- 
2.5.5



More information about the mesa-dev mailing list