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

Roland Scheidegger sroland at vmware.com
Mon Apr 18 17:40:48 UTC 2016


Am 18.04.2016 um 04:49 schrieb Dave Airlie:
> 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
I can't quite parse this fully ;-).



> ---
>  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++) {
Indentation.
And I think this should really make an effort to only do this for
samplers which are actually dyanmically indexed, for the possible
range(s) (as they need to be declared as an array if I'm not mistaken).
I'm not entirely sure, but I believe this could even crash otherwise
potentially, due to trying to construct lookup functions with
incompatible combinations of parameters.

> +         struct lp_sampler_params unit_params = *params;
> +
> +         unit_params.texture_index = i;
> +         unit_params.sampler_index = i;
Of course, the need to actually override texture and sampler index is
why I never even tried to implement it - for d3d10 sample opcodes, it
looked simply unfeasible as you'd have to generate the product of
num_samplers/num_textures. So I figured this needed way more work...
Though actually thinking about this, only need to be able to index into
resources, not samplers, there, so it should work as well...
I can't really make sense out of the msdn docs though.
But with d3d12 you actually could have legitimate per-pixel resource
indices (yuck!!!) - with the usual caveat about calculated lods.
But I can't actually find anything that says dynamic indexing into
resources even works at all for d3d11 now.

> +         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);
And I think really all of this should move to the actual sample code.

> +      }
> +      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)), "");
> 
This isn't quite right (I suppose that's what the commit message wanted
to say but was cut short...).
>From what I understand, you really need to examine the exec mask (not
sure if the alive pixel mask is also needed) and pick your (scalar)
index from a element which is in the current exec mask. I guess that's
another parameter for the sampler params...
And fwiw I think doing that with a switch statement in the end instead
of if ladders would make far more sense.


+      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);
Does this ensure that the index doesn't exceed max sampler index?
Hopefully yes, but if not you need to add some MIN here.

>     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 */
> 

Otherwise the idea looks sane.

Roland



More information about the mesa-dev mailing list