[Mesa-dev] [PATCH 3/4] [rfc] gallivm/llvmpipe dynamic samplers support.

Dave Airlie airlied at gmail.com
Mon Apr 18 02:49:18 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
ones which g
---
 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 | 25 +++++++++++++----
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   |  4 +++
 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, 88 insertions(+), 21 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..5a3f9e4 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 d39fb60..fead4fd 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,29 @@ 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_vec(gallivm, lp_uint_type(params->type), params->sampler_index), "");
+      indirect_matches = LLVMBuildBitCast(builder, indirect_matches, LLVMIntTypeInContext(gallivm->context, params->type.length), "");
+      indirect_matches = LLVMBuildICmp(builder, LLVMIntNE,
+                                       indirect_matches, LLVMConstNull(LLVMIntTypeInContext(gallivm->context, params->type.length)), "");
+      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 +3422,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..2e8cf49 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -2335,6 +2335,10 @@ 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)
+       params.indirect_index = get_indirect_index(bld, inst->Src[sampler_reg].Register.File, inst->Src[sampler_reg].Register.Index, &inst->Src[sampler_reg].Indirect);
+
    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