[Mesa-dev] [PATCH] llvmpipe: Implement TXQ.

Roland Scheidegger sroland at vmware.com
Tue May 15 16:51:14 PDT 2012


Wouldn't it be easier (and more efficient) if you could just reuse the
sampler code which does mipmap minification, i.e. get the texture sizes
from bld.int_size and do a lp_build_minify (followed by extract shuffles)?
Also, is it on purpose that the non-explicit lod path doesn't handle all
cases (using lp_build_minify would handle both cases equally if you pass
zero as the level)?
Otherwise looks like a good idea to me (well ok I'm not too sure why
this opcode is terribly useful in the first place but it exists...).

Roland




Am 15.05.2012 22:09, schrieb Olivier Galibert:
> Piglits test for fragment shaders pass, vertex shaders fail.  The
> actual failure seems to be in the interpolators, and not the
> textureSize query.
> 
> Signed-off-by: Olivier Galibert <galibert at pobox.com>
> ---
>  src/gallium/auxiliary/draw/draw_llvm_sample.c     |   23 +++++
>  src/gallium/auxiliary/gallivm/lp_bld_sample.h     |   10 +-
>  src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c |  112 +++++++++++++++++++++
>  src/gallium/auxiliary/gallivm/lp_bld_tgsi.h       |    7 ++
>  src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   |   86 ++++++++++++++++
>  src/gallium/drivers/llvmpipe/lp_tex_sample.c      |   23 +++++
>  6 files changed, 260 insertions(+), 1 deletion(-)
> 
> diff --git a/src/gallium/auxiliary/draw/draw_llvm_sample.c b/src/gallium/auxiliary/draw/draw_llvm_sample.c
> index 8af3461..a3f5197 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm_sample.c
> +++ b/src/gallium/auxiliary/draw/draw_llvm_sample.c
> @@ -195,6 +195,28 @@ draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
>  }
>  
>  
> +/**
> + * Fetch the texture size.
> + */
> +static void
> +draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
> +                                      struct gallivm_state *gallivm,
> +                                      unsigned unit,
> +                                      LLVMValueRef explicit_lod, /* optional */
> +                                      LLVMValueRef *sizes_out)
> +{
> +   struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
> +
> +   assert(unit < PIPE_MAX_VERTEX_SAMPLERS);
> +   
> +   lp_build_size_query_soa(gallivm,
> +			   &sampler->dynamic_state.static_state[unit],
> +			   &sampler->dynamic_state.base,
> +			   unit,
> +			   explicit_lod,
> +			   sizes_out);
> +}
> +
>  struct lp_build_sampler_soa *
>  draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
>                               LLVMValueRef context_ptr)
> @@ -207,6 +229,7 @@ draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
>  
>     sampler->base.destroy = draw_llvm_sampler_soa_destroy;
>     sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel;
> +   sampler->base.emit_size_query = draw_llvm_sampler_soa_emit_size_query;
>     sampler->dynamic_state.base.width = draw_llvm_texture_width;
>     sampler->dynamic_state.base.height = draw_llvm_texture_height;
>     sampler->dynamic_state.base.depth = draw_llvm_texture_depth;
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
> index a71e656..ec8aaf4 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
> @@ -67,7 +67,7 @@ struct lp_sampler_static_state
>     unsigned swizzle_a:3;
>  
>     /* pipe_texture's state */
> -   unsigned target:3;        /**< PIPE_TEXTURE_* */
> +   unsigned target:4;        /**< PIPE_TEXTURE_* */
>     unsigned pot_width:1;     /**< is the width a power of two? */
>     unsigned pot_height:1;
>     unsigned pot_depth:1;
> @@ -405,6 +405,14 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
>                      LLVMValueRef texel_out[4]);
>  
>  void
> +lp_build_size_query_soa(struct gallivm_state *gallivm,
> +                        const struct lp_sampler_static_state *static_state,
> +                        struct lp_sampler_dynamic_state *dynamic_state,
> +                        unsigned unit,
> +                        LLVMValueRef explicit_lod,
> +                        LLVMValueRef *sizes_out);
> +
> +void
>  lp_build_sample_nop(struct gallivm_state *gallivm, struct lp_type type,
>                      LLVMValueRef texel_out[4]);
>  
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
> index 4ea7b4b..926b626 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
> @@ -35,6 +35,7 @@
>  
>  #include "pipe/p_defines.h"
>  #include "pipe/p_state.h"
> +#include "pipe/p_shader_tokens.h"
>  #include "util/u_debug.h"
>  #include "util/u_dump.h"
>  #include "util/u_memory.h"
> @@ -1277,3 +1278,114 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
>  
>     apply_sampler_swizzle(&bld, texel_out);
>  }
> +
> +void
> +lp_build_size_query_soa(struct gallivm_state *gallivm,
> +                        const struct lp_sampler_static_state *static_state,
> +                        struct lp_sampler_dynamic_state *dynamic_state,
> +                        unsigned unit,
> +                        LLVMValueRef explicit_lod,
> +                        LLVMValueRef *sizes_out)
> +{
> +   if (explicit_lod) {
> +      LLVMValueRef first_level, zero, all_ones, lod, slot, shifter;
> +      int dims, array_size;
> +      struct lp_build_context bld_int_vec;
> +
> +      switch (static_state->target) {
> +      case TGSI_TEXTURE_1D:
> +      case TGSI_TEXTURE_SHADOW1D:
> +      case TGSI_TEXTURE_SHADOW2D:
> +      case TGSI_TEXTURE_SHADOWCUBE:
> +         dims = 1;
> +         array_size = 0;
> +         break;
> +      case TGSI_TEXTURE_1D_ARRAY:
> +      case TGSI_TEXTURE_SHADOW1D_ARRAY:
> +         dims = 1;
> +         array_size = 1;
> +         break;
> +      case TGSI_TEXTURE_2D:
> +      case TGSI_TEXTURE_CUBE:
> +         dims = 2;
> +         array_size = 0;
> +         break;
> +//    case TGSI_TEXTURE_CUBE_ARRAY:
> +//    case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
> +      case TGSI_TEXTURE_2D_ARRAY:
> +      case TGSI_TEXTURE_SHADOW2D_ARRAY:
> +         dims = 2;
> +         array_size = 1;
> +         break;
> +      case TGSI_TEXTURE_3D:
> +         dims = 3;
> +         array_size = 0;
> +         break;
> +
> +      default:
> +         assert(0);
> +         return;
> +      }
> +
> +      lp_build_context_init(&bld_int_vec, gallivm, lp_type_int_vec(32));
> +
> +      zero = lp_build_const_int32(gallivm, 0);
> +      all_ones = lp_build_one(gallivm, lp_type_int_vec(32));
> +      lod = LLVMBuildExtractElement(gallivm->builder, explicit_lod, zero, "");
> +      first_level = dynamic_state->first_level(dynamic_state, gallivm, unit);
> +      lod = LLVMBuildAdd(gallivm->builder, lod, first_level, "lod");
> +      shifter = lp_build_broadcast_scalar(&bld_int_vec, lod);
> +      
> +      slot = dynamic_state->width(dynamic_state, gallivm, unit);
> +      slot = lp_build_broadcast_scalar(&bld_int_vec, slot);
> +      slot = LLVMBuildLShr(gallivm->builder, slot, shifter, "minify_width");
> +      sizes_out[0] = lp_build_max(&bld_int_vec, slot, all_ones);
> +
> +      if (dims >= 2) {
> +         slot = dynamic_state->height(dynamic_state, gallivm, unit);
> +         slot = lp_build_broadcast_scalar(&bld_int_vec, slot);
> +         slot = LLVMBuildLShr(gallivm->builder, slot, shifter, "minify_height");
> +         sizes_out[1] = lp_build_max(&bld_int_vec, slot, all_ones);
> +      }
> +
> +      if (dims >= 3) {
> +         slot = dynamic_state->depth(dynamic_state, gallivm, unit);
> +         slot = lp_build_broadcast_scalar(&bld_int_vec, slot);
> +         slot = LLVMBuildLShr(gallivm->builder, slot, shifter, "minify_depth");
> +         sizes_out[2] = lp_build_max(&bld_int_vec, slot, all_ones);
> +      }
> +
> +//    GL_ext_texture_array not supported yet
> +//    if (array_size) ???
> +
> +   } else {
> +      int dims;
> +      LLVMValueRef slot;
> +      struct lp_build_context bld_int_vec;
> +      switch (static_state->target) {
> +//    case TGSI_TEXTURE_BUFFER:
> +//       dims = 1;
> +//       break;
> +
> +      case TGSI_TEXTURE_RECT:
> +      case TGSI_TEXTURE_SHADOWRECT:
> +//    case TGSI_TEXTURE_2D_MS:
> +         dims = 2;
> +         break;
> +
> +      default:
> +         assert(0);
> +         return;
> +      }
> +
> +      lp_build_context_init(&bld_int_vec, gallivm, lp_type_int_vec(32));
> +
> +      slot = dynamic_state->width(dynamic_state, gallivm, unit);
> +      sizes_out[0] = lp_build_broadcast_scalar(&bld_int_vec, slot);
> +
> +      if (dims >= 2) {
> +         slot = dynamic_state->height(dynamic_state, gallivm, unit);
> +         sizes_out[1] = lp_build_broadcast_scalar(&bld_int_vec, slot);
> +      }
> +   }
> +}
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> index 773c679..141e799 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> @@ -170,6 +170,13 @@ struct lp_build_sampler_soa
>                          LLVMValueRef lod_bias, /* optional */
>                          LLVMValueRef explicit_lod, /* optional */
>                          LLVMValueRef *texel);
> +
> +   void
> +   (*emit_size_query)( const struct lp_build_sampler_soa *sampler,
> +                       struct gallivm_state *gallivm,
> +                       unsigned unit,
> +                       LLVMValueRef explicit_lod, /* optional */
> +                       LLVMValueRef *sizes_out);
>  };
>  
>  
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> index cca7ef5..516ef08 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -1209,6 +1209,80 @@ emit_tex( struct lp_build_tgsi_soa_context *bld,
>                                    texel);
>  }
>  
> +static void
> +emit_txq( struct lp_build_tgsi_soa_context *bld,
> +          const struct tgsi_full_instruction *inst,
> +          LLVMValueRef *sizes_out)
> +{
> +   LLVMValueRef explicit_lod;
> +   unsigned num_coords, has_lod;
> +   unsigned i;
> +
> +   switch (inst->Texture.Texture) {
> +   case TGSI_TEXTURE_1D:
> +   case TGSI_TEXTURE_SHADOW1D:
> +   case TGSI_TEXTURE_SHADOW2D:
> +   case TGSI_TEXTURE_SHADOWCUBE:
> +      num_coords = 1;
> +      has_lod = 1;
> +      break;
> +   case TGSI_TEXTURE_2D:
> +   case TGSI_TEXTURE_CUBE:
> +   case TGSI_TEXTURE_1D_ARRAY:
> +   case TGSI_TEXTURE_SHADOW1D_ARRAY:
> +      num_coords = 2;
> +      has_lod = 1;
> +      break;
> +   case TGSI_TEXTURE_3D:
> +// case TGSI_TEXTURE_CUBE_ARRAY:
> +// case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
> +   case TGSI_TEXTURE_2D_ARRAY:
> +   case TGSI_TEXTURE_SHADOW2D_ARRAY:
> +      num_coords = 3;
> +      has_lod = 1;
> +      break;
> +
> +// case TGSI_TEXTURE_BUFFER:
> +//    num_coords = 1;
> +//    has_lod = 0;
> +//    break;
> +
> +   case TGSI_TEXTURE_RECT:
> +   case TGSI_TEXTURE_SHADOWRECT:
> +// case TGSI_TEXTURE_2D_MS:
> +      num_coords = 2;
> +      has_lod = 0;
> +      break;
> +
> +// case TGSI_TEXTURE_2D_MS_ARRAY:
> +//    num_coords = 3;
> +//    has_lod = 0;
> +//    break;
> +
> +   default:
> +      assert(0);
> +      return;
> +   }
> +
> +   if (!bld->sampler) {
> +      _debug_printf("warning: found texture query instruction but no sampler generator supplied\n");
> +      for (i = 0; i < num_coords; i++)
> +         sizes_out[i] = bld->bld_base.base.undef;
> +      return;
> +   }
> +
> +   if (has_lod)
> +      explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 2 );
> +   else
> +      explicit_lod = NULL;
> +
> +   bld->sampler->emit_size_query(bld->sampler,
> +                                 bld->bld_base.base.gallivm,
> +                                 inst->Src[1].Register.Index,
> +                                 explicit_lod,
> +                                 sizes_out);
> +}
> +
>  static boolean
>  near_end_of_shader(struct lp_build_tgsi_soa_context *bld,
>  		   int pc)
> @@ -1585,6 +1659,17 @@ txp_emit(
>  }
>  
>  static void
> +txq_emit(
> +   const struct lp_build_tgsi_action * action,
> +   struct lp_build_tgsi_context * bld_base,
> +   struct lp_build_emit_data * emit_data)
> +{
> +   struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
> +
> +   emit_txq(bld, emit_data->inst, emit_data->output);
> +}
> +
> +static void
>  cal_emit(
>     const struct lp_build_tgsi_action * action,
>     struct lp_build_tgsi_context * bld_base,
> @@ -1954,6 +2039,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
>     bld.bld_base.op_actions[TGSI_OPCODE_TXD].emit = txd_emit;
>     bld.bld_base.op_actions[TGSI_OPCODE_TXL].emit = txl_emit;
>     bld.bld_base.op_actions[TGSI_OPCODE_TXP].emit = txp_emit;
> +   bld.bld_base.op_actions[TGSI_OPCODE_TXQ].emit = txq_emit;
>  
>     lp_exec_mask_init(&bld.exec_mask, &bld.bld_base.base);
>  
> diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c
> index ccc1396..daa96f2 100644
> --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c
> +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c
> @@ -204,6 +204,28 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
>                         texel);
>  }
>  
> +/**
> + * Fetch the texture size.
> + */
> +static void
> +lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
> +                                    struct gallivm_state *gallivm,
> +                                    unsigned unit,
> +                                    LLVMValueRef explicit_lod, /* optional */
> +                                    LLVMValueRef *sizes_out)
> +{
> +   struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
> +
> +   assert(unit < PIPE_MAX_SAMPLERS);
> +   
> +   lp_build_size_query_soa(gallivm,
> +			   &sampler->dynamic_state.static_state[unit],
> +			   &sampler->dynamic_state.base,
> +			   unit,
> +			   explicit_lod,
> +			   sizes_out);
> +}
> +
>  
>  struct lp_build_sampler_soa *
>  lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
> @@ -217,6 +239,7 @@ lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
>  
>     sampler->base.destroy = lp_llvm_sampler_soa_destroy;
>     sampler->base.emit_fetch_texel = lp_llvm_sampler_soa_emit_fetch_texel;
> +   sampler->base.emit_size_query = lp_llvm_sampler_soa_emit_size_query;
>     sampler->dynamic_state.base.width = lp_llvm_texture_width;
>     sampler->dynamic_state.base.height = lp_llvm_texture_height;
>     sampler->dynamic_state.base.depth = lp_llvm_texture_depth;



More information about the mesa-dev mailing list