[Mesa-dev] [PATCH 1/2] gallivm: split sampler and texture state

Jose Fonseca jfonseca at vmware.com
Mon Jan 28 04:19:16 PST 2013


Reviewed-by: Jose Fonseca <jfonseca at vmware.com>

Looks good to me.

Minor nit: there is some spurious white space change (removal of trailing white-space on untouched pieces of code). Due to the wide variety of editors it's hard to enforce this (ie a recurring problem), and this can cause merge conflicts, so I'd prefer to leave these untouched (and disable editor's auto-trim feature if enabled).

Jose

----- Original Message -----
> From: Roland Scheidegger <sroland at vmware.com>
> 
> Split the sampler interface to use separate sampler and texture
> (sampler_view)
> state. This is needed to support dx10-style sampling instructions.
> This is not quite complete since both draw/llvmpipe don't really
> track
> textures/samplers independently yet, as well as the gallivm code not
> quite
> using the right sampler or texture index respectively (but it should
> work
> for the sampling codes used by opengl).
> We are however losing some optimizations in the process,
> apply_max_lod will
> no longer work, and we potentially could end up with more
> (unnecessary)
> recompiles (if switching textures with/without mipmaps only so it
> shouldn't
> be too bad).
> 
> v2: don't use different callback structs for sampler/sampler view
> functions
> (which just complicates things), fix up sampling code to actually use
> the
> right texture or sampler index, and similar for llvmpipe/draw
> actually
> distinguish between samplers and sampler views.
> 
> v3: fix more of PIPE_MAX_SAMPLER / PIPE_MAX_SHADER_SAMPLER_VIEWS
> mismatches
> (both in draw and llvmpipe), based on feedback from José get rid of
> unneeded
> static sampler derived state.(which also fixes the only 2 piglit
> regressions
> due to a forgotten assignment), fix comments based on Brian's
> feedback.
> ---
>  src/gallium/auxiliary/draw/draw_context.c         |    4 +-
>  src/gallium/auxiliary/draw/draw_llvm.c            |  131
>  ++++++++++-----
>  src/gallium/auxiliary/draw/draw_llvm.h            |   66 ++++++--
>  src/gallium/auxiliary/draw/draw_llvm_sample.c     |   96 +++++++++--
>  src/gallium/auxiliary/draw/draw_private.h         |    2 +-
>  src/gallium/auxiliary/gallivm/lp_bld_sample.c     |  108
>  +++++++-----
>  src/gallium/auxiliary/gallivm/lp_bld_sample.h     |   58 +++++--
>  src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c |  104
>  ++++++------
>  src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c |  185
>  +++++++++++----------
>  src/gallium/auxiliary/gallivm/lp_bld_tgsi.h       |    3 +-
>  src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   |    6 +-
>  src/gallium/drivers/llvmpipe/lp_context.h         |    4 +-
>  src/gallium/drivers/llvmpipe/lp_jit.c             |   54 ++++--
>  src/gallium/drivers/llvmpipe/lp_jit.h             |   24 ++-
>  src/gallium/drivers/llvmpipe/lp_setup.c           |   16 +-
>  src/gallium/drivers/llvmpipe/lp_setup_context.h   |    2 +-
>  src/gallium/drivers/llvmpipe/lp_state_fs.c        |   84 +++++++---
>  src/gallium/drivers/llvmpipe/lp_state_fs.h        |   17 +-
>  src/gallium/drivers/llvmpipe/lp_state_sampler.c   |    6 +-
>  src/gallium/drivers/llvmpipe/lp_state_setup.c     |   16 +-
>  src/gallium/drivers/llvmpipe/lp_tex_sample.c      |  102
>  +++++++++---
>  21 files changed, 720 insertions(+), 368 deletions(-)
> 
> diff --git a/src/gallium/auxiliary/draw/draw_context.c
> b/src/gallium/auxiliary/draw/draw_context.c
> index bc2f0e1..dfa8927 100644
> --- a/src/gallium/auxiliary/draw/draw_context.c
> +++ b/src/gallium/auxiliary/draw/draw_context.c
> @@ -762,11 +762,11 @@ draw_set_sampler_views(struct draw_context
> *draw,
>     unsigned i;
>  
>     debug_assert(shader_stage < PIPE_SHADER_TYPES);
> -   debug_assert(num <= PIPE_MAX_SAMPLERS);
> +   debug_assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
>  
>     for (i = 0; i < num; ++i)
>        draw->sampler_views[shader_stage][i] = views[i];
> -   for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
> +   for (i = num; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; ++i)
>        draw->sampler_views[shader_stage][i] = NULL;
>  
>     draw->num_sampler_views[shader_stage] = num;
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.c
> b/src/gallium/auxiliary/draw/draw_llvm.c
> index a3a3bbf..7a2418a 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm.c
> +++ b/src/gallium/auxiliary/draw/draw_llvm.c
> @@ -85,11 +85,6 @@ create_jit_texture_type(struct gallivm_state
> *gallivm, const char *struct_name)
>     elem_types[DRAW_JIT_TEXTURE_IMG_STRIDE] =
>     elem_types[DRAW_JIT_TEXTURE_MIP_OFFSETS] =
>        LLVMArrayType(int32_type, PIPE_MAX_TEXTURE_LEVELS);
> -   elem_types[DRAW_JIT_TEXTURE_MIN_LOD] =
> -   elem_types[DRAW_JIT_TEXTURE_MAX_LOD] =
> -   elem_types[DRAW_JIT_TEXTURE_LOD_BIAS] =
> LLVMFloatTypeInContext(gallivm->context);
> -   elem_types[DRAW_JIT_TEXTURE_BORDER_COLOR] =
> -      LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
>  
>     texture_type = LLVMStructTypeInContext(gallivm->context,
>     elem_types,
>                                            Elements(elem_types), 0);
> @@ -130,18 +125,6 @@ create_jit_texture_type(struct gallivm_state
> *gallivm, const char *struct_name)
>     LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, mip_offsets,
>                            target, texture_type,
>                            DRAW_JIT_TEXTURE_MIP_OFFSETS);
> -   LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, min_lod,
> -                          target, texture_type,
> -                          DRAW_JIT_TEXTURE_MIN_LOD);
> -   LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, max_lod,
> -                          target, texture_type,
> -                          DRAW_JIT_TEXTURE_MAX_LOD);
> -   LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, lod_bias,
> -                          target, texture_type,
> -                          DRAW_JIT_TEXTURE_LOD_BIAS);
> -   LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, border_color,
> -                          target, texture_type,
> -                          DRAW_JIT_TEXTURE_BORDER_COLOR);
>  
>     LP_CHECK_STRUCT_SIZE(struct draw_jit_texture, target,
>     texture_type);
>  
> @@ -150,15 +133,63 @@ create_jit_texture_type(struct gallivm_state
> *gallivm, const char *struct_name)
>  
>  
>  /**
> - * Create LLVM type for struct draw_jit_texture
> + * Create LLVM type for struct draw_jit_sampler
> + */
> +static LLVMTypeRef
> +create_jit_sampler_type(struct gallivm_state *gallivm, const char
> *struct_name)
> +{
> +   LLVMTargetDataRef target = gallivm->target;
> +   LLVMTypeRef sampler_type;
> +   LLVMTypeRef elem_types[DRAW_JIT_SAMPLER_NUM_FIELDS];
> +
> +   elem_types[DRAW_JIT_SAMPLER_MIN_LOD] =
> +   elem_types[DRAW_JIT_SAMPLER_MAX_LOD] =
> +   elem_types[DRAW_JIT_SAMPLER_LOD_BIAS] =
> LLVMFloatTypeInContext(gallivm->context);
> +   elem_types[DRAW_JIT_SAMPLER_BORDER_COLOR] =
> +      LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
> +
> +   sampler_type = LLVMStructTypeInContext(gallivm->context,
> elem_types,
> +                                          Elements(elem_types), 0);
> +
> +#if HAVE_LLVM < 0x0300
> +   LLVMAddTypeName(gallivm->module, struct_name, sampler_type);
> +
> +   /* Make sure the target's struct layout cache doesn't return
> +    * stale/invalid data.
> +    */
> +   LLVMInvalidateStructLayout(gallivm->target, sampler_type);
> +#endif
> +
> +   LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, min_lod,
> +                          target, sampler_type,
> +                          DRAW_JIT_SAMPLER_MIN_LOD);
> +   LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, max_lod,
> +                          target, sampler_type,
> +                          DRAW_JIT_SAMPLER_MAX_LOD);
> +   LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, lod_bias,
> +                          target, sampler_type,
> +                          DRAW_JIT_SAMPLER_LOD_BIAS);
> +   LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, border_color,
> +                          target, sampler_type,
> +                          DRAW_JIT_SAMPLER_BORDER_COLOR);
> +
> +   LP_CHECK_STRUCT_SIZE(struct draw_jit_sampler, target,
> sampler_type);
> +
> +   return sampler_type;
> +}
> +
> +
> +/**
> + * Create LLVM type for struct draw_jit_context
>   */
>  static LLVMTypeRef
>  create_jit_context_type(struct gallivm_state *gallivm,
> -                        LLVMTypeRef texture_type, const char
> *struct_name)
> +                        LLVMTypeRef texture_type, LLVMTypeRef
> sampler_type,
> +                        const char *struct_name)
>  {
>     LLVMTargetDataRef target = gallivm->target;
>     LLVMTypeRef float_type =
>     LLVMFloatTypeInContext(gallivm->context);
> -   LLVMTypeRef elem_types[5];
> +   LLVMTypeRef elem_types[6];
>     LLVMTypeRef context_type;
>  
>     elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /*
>     vs_constants */
> @@ -168,7 +199,9 @@ create_jit_context_type(struct gallivm_state
> *gallivm,
>                                                   DRAW_TOTAL_CLIP_PLANES),
>                                                   0);
>     elem_types[3] = LLVMPointerType(float_type, 0); /* viewport */
>     elem_types[4] = LLVMArrayType(texture_type,
> -                                 PIPE_MAX_SAMPLERS); /* textures */
> +                                 PIPE_MAX_SHADER_SAMPLER_VIEWS); /*
> textures */
> +   elem_types[5] = LLVMArrayType(sampler_type,
> +                                 PIPE_MAX_SAMPLERS); /* samplers */
>     context_type = LLVMStructTypeInContext(gallivm->context,
>     elem_types,
>                                            Elements(elem_types), 0);
>  #if HAVE_LLVM < 0x0300
> @@ -183,9 +216,14 @@ create_jit_context_type(struct gallivm_state
> *gallivm,
>                            target, context_type, 1);
>     LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, planes,
>                            target, context_type, 2);
> +   LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, viewport,
> +                          target, context_type, 3);
>     LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, textures,
>                            target, context_type,
>                            DRAW_JIT_CTX_TEXTURES);
> +   LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, samplers,
> +                          target, context_type,
> +                          DRAW_JIT_CTX_SAMPLERS);
>     LP_CHECK_STRUCT_SIZE(struct draw_jit_context,
>                          target, context_type);
>  
> @@ -291,11 +329,13 @@ static void
>  create_jit_types(struct draw_llvm_variant *variant)
>  {
>     struct gallivm_state *gallivm = variant->gallivm;
> -   LLVMTypeRef texture_type, context_type, buffer_type, vb_type;
> +   LLVMTypeRef texture_type, sampler_type, context_type,
> buffer_type, vb_type;
>  
>     texture_type = create_jit_texture_type(gallivm, "texture");
> +   sampler_type = create_jit_sampler_type(gallivm, "sampler");
>  
> -   context_type = create_jit_context_type(gallivm, texture_type,
> "draw_jit_context");
> +   context_type = create_jit_context_type(gallivm, texture_type,
> sampler_type,
> +                                          "draw_jit_context");
>     variant->context_ptr_type = LLVMPointerType(context_type, 0);
>  
>     buffer_type =
>     LLVMPointerType(LLVMIntTypeInContext(gallivm->context, 8), 0);
> @@ -1182,8 +1222,8 @@ draw_llvm_generate(struct draw_llvm *llvm,
> struct draw_llvm_variant *variant,
>  
>     /* code generated texture sampling */
>     sampler = draw_llvm_sampler_soa_create(
> -      draw_llvm_variant_key_samplers(&variant->key),
> -      context_ptr);
> +                draw_llvm_variant_key_samplers(&variant->key),
> +                context_ptr);
>  
>     if (elts) {
>        start = zero;
> @@ -1319,7 +1359,7 @@ draw_llvm_make_variant_key(struct draw_llvm
> *llvm, char *store)
>  {
>     unsigned i;
>     struct draw_llvm_variant_key *key;
> -   struct lp_sampler_static_state *sampler;
> +   struct draw_sampler_static_state *draw_sampler;
>  
>     key = (struct draw_llvm_variant_key *)store;
>  
> @@ -1345,19 +1385,29 @@ draw_llvm_make_variant_key(struct draw_llvm
> *llvm, char *store)
>      * sampler array.
>      */
>     key->nr_samplers =
>     llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER] +
>     1;
> +   if
> (llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW]
> != -1) {
> +      key->nr_sampler_views =
> +
>         llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW]
> + 1;
> +   }
> +   else {
> +      key->nr_sampler_views = key->nr_samplers;
> +   }
>  
> -   sampler = draw_llvm_variant_key_samplers(key);
> +   draw_sampler = draw_llvm_variant_key_samplers(key);
>  
>     memcpy(key->vertex_element,
>            llvm->draw->pt.vertex_element,
>            sizeof(struct pipe_vertex_element) *
>            key->nr_vertex_elements);
> -
> -   memset(sampler, 0, key->nr_samplers * sizeof *sampler);
> +
> +   memset(draw_sampler, 0, MAX2(key->nr_samplers,
> key->nr_sampler_views) * sizeof *draw_sampler);
>  
>     for (i = 0 ; i < key->nr_samplers; i++) {
> -      lp_sampler_static_state(&sampler[i],
> -			      llvm->draw->sampler_views[PIPE_SHADER_VERTEX][i],
> -			      llvm->draw->samplers[PIPE_SHADER_VERTEX][i]);
> +
>      lp_sampler_static_sampler_state(&draw_sampler[i].sampler_state,
> +
>                                      llvm->draw->samplers[PIPE_SHADER_VERTEX][i]);
> +   }
> +   for (i = 0 ; i < key->nr_sampler_views; i++) {
> +
>      lp_sampler_static_texture_state(&draw_sampler[i].texture_state,
> +
>                                      llvm->draw->sampler_views[PIPE_SHADER_VERTEX][i]);
>     }
>  
>     return key;
> @@ -1368,7 +1418,7 @@ void
>  draw_llvm_dump_variant_key(struct draw_llvm_variant_key *key)
>  {
>     unsigned i;
> -   struct lp_sampler_static_state *sampler =
> draw_llvm_variant_key_samplers(key);
> +   struct draw_sampler_static_state *sampler =
> draw_llvm_variant_key_samplers(key);
>  
>     debug_printf("clamp_vertex_color = %u\n",
>     key->clamp_vertex_color);
>     debug_printf("clip_xy = %u\n", key->clip_xy);
> @@ -1386,8 +1436,8 @@ draw_llvm_dump_variant_key(struct
> draw_llvm_variant_key *key)
>        debug_printf("vertex_element[%i].src_format = %s\n", i,
>        util_format_name(key->vertex_element[i].src_format));
>     }
>  
> -   for (i = 0 ; i < key->nr_samplers; i++) {
> -      debug_printf("sampler[%i].src_format = %s\n", i,
> util_format_name(sampler[i].format));
> +   for (i = 0 ; i < key->nr_sampler_views; i++) {
> +      debug_printf("sampler[%i].src_format = %s\n", i,
> util_format_name(sampler[i].texture_state.format));
>     }
>  }
>  
> @@ -1428,17 +1478,16 @@ void
>  draw_llvm_set_sampler_state(struct draw_context *draw)
>  {
>     unsigned i;
> -
>     for (i = 0; i < draw->num_samplers[PIPE_SHADER_VERTEX]; i++) {
> -      struct draw_jit_texture *jit_tex =
> &draw->llvm->jit_context.textures[i];
> +      struct draw_jit_sampler *jit_sam =
> &draw->llvm->jit_context.samplers[i];
>  
>        if (draw->samplers[i]) {
>           const struct pipe_sampler_state *s
>              = draw->samplers[PIPE_SHADER_VERTEX][i];
> -         jit_tex->min_lod = s->min_lod;
> -         jit_tex->max_lod = s->max_lod;
> -         jit_tex->lod_bias = s->lod_bias;
> -         COPY_4V(jit_tex->border_color, s->border_color.f);
> +         jit_sam->min_lod = s->min_lod;
> +         jit_sam->max_lod = s->max_lod;
> +         jit_sam->lod_bias = s->lod_bias;
> +         COPY_4V(jit_sam->border_color, s->border_color.f);
>        }
>     }
>  }
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.h
> b/src/gallium/auxiliary/draw/draw_llvm.h
> index 892973c..a664857 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm.h
> +++ b/src/gallium/auxiliary/draw/draw_llvm.h
> @@ -52,12 +52,30 @@ struct draw_jit_texture
>     uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
>     uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
>     uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
> +};
> +
> +
> +struct draw_sampler_static_state
> +{
> +   /*
> +    * These attributes are effectively interleaved for more sane key
> handling.
> +    * However, there might be lots of null space if the amount of
> samplers and
> +    * textures isn't the same.
> +    */
> +   struct lp_static_sampler_state sampler_state;
> +   struct lp_static_texture_state texture_state;
> +};
> +
> +
> +struct draw_jit_sampler
> +{
>     float min_lod;
>     float max_lod;
>     float lod_bias;
>     float border_color[4];
>  };
>  
> +
>  enum {
>     DRAW_JIT_TEXTURE_WIDTH = 0,
>     DRAW_JIT_TEXTURE_HEIGHT,
> @@ -68,13 +86,19 @@ enum {
>     DRAW_JIT_TEXTURE_ROW_STRIDE,
>     DRAW_JIT_TEXTURE_IMG_STRIDE,
>     DRAW_JIT_TEXTURE_MIP_OFFSETS,
> -   DRAW_JIT_TEXTURE_MIN_LOD,
> -   DRAW_JIT_TEXTURE_MAX_LOD,
> -   DRAW_JIT_TEXTURE_LOD_BIAS,
> -   DRAW_JIT_TEXTURE_BORDER_COLOR,
>     DRAW_JIT_TEXTURE_NUM_FIELDS  /* number of fields above */
>  };
>  
> +
> +enum {
> +   DRAW_JIT_SAMPLER_MIN_LOD,
> +   DRAW_JIT_SAMPLER_MAX_LOD,
> +   DRAW_JIT_SAMPLER_LOD_BIAS,
> +   DRAW_JIT_SAMPLER_BORDER_COLOR,
> +   DRAW_JIT_SAMPLER_NUM_FIELDS  /* number of fields above */
> +};
> +
> +
>  enum {
>     DRAW_JIT_VERTEX_VERTEX_ID = 0,
>     DRAW_JIT_VERTEX_CLIP,
> @@ -82,6 +106,9 @@ enum {
>     DRAW_JIT_VERTEX_DATA
>  };
>  
> +#define DRAW_JIT_CTX_TEXTURES 4
> +#define DRAW_JIT_CTX_SAMPLERS 5
> +
>  /**
>   * This structure is passed directly to the generated vertex shader.
>   *
> @@ -100,7 +127,8 @@ struct draw_jit_context
>     float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
>     float *viewport;
>  
> -   struct draw_jit_texture textures[PIPE_MAX_SAMPLERS];
> +   struct draw_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
> +   struct draw_jit_sampler samplers[PIPE_MAX_SAMPLERS];
>  };
>  
>  
> @@ -117,10 +145,14 @@ struct draw_jit_context
>     lp_build_struct_get(_gallivm, _ptr, 3, "viewport")
>  
>  #define DRAW_JIT_CTX_TEXTURES 4
> +#define DRAW_JIT_CTX_SAMPLERS 5
>  
>  #define draw_jit_context_textures(_gallivm, _ptr) \
>     lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_TEXTURES,
>     "textures")
>  
> +#define draw_jit_context_samplers(_gallivm, _ptr) \
> +   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_SAMPLERS,
> "samplers")
> +
>  #define draw_jit_header_id(_gallivm, _ptr)              \
>     lp_build_struct_get_ptr(_gallivm, _ptr,
>     DRAW_JIT_VERTEX_VERTEX_ID, "id")
>  
> @@ -166,6 +198,7 @@ struct draw_llvm_variant_key
>  {
>     unsigned nr_vertex_elements:8;
>     unsigned nr_samplers:8;
> +   unsigned nr_sampler_views:8;
>     unsigned clamp_vertex_color:1;
>     unsigned clip_xy:1;
>     unsigned clip_z:1;
> @@ -174,7 +207,7 @@ struct draw_llvm_variant_key
>     unsigned bypass_viewport:1;
>     unsigned need_edgeflags:1;
>     unsigned ucp_enable:PIPE_MAX_CLIP_PLANES;
> -   unsigned pad:9-PIPE_MAX_CLIP_PLANES;
> +   unsigned pad:33-PIPE_MAX_CLIP_PLANES;
>  
>     /* Variable number of vertex elements:
>      */
> @@ -182,34 +215,33 @@ struct draw_llvm_variant_key
>  
>     /* Followed by variable number of samplers:
>      */
> -/*   struct lp_sampler_static_state sampler; */
> +/*   struct draw_sampler_static_state sampler; */
>  };
>  
>  #define DRAW_LLVM_MAX_VARIANT_KEY_SIZE \
>     (sizeof(struct draw_llvm_variant_key) +	\
> -    PIPE_MAX_SAMPLERS * sizeof(struct lp_sampler_static_state) +	\
> +    PIPE_MAX_SHADER_SAMPLER_VIEWS * sizeof(struct
> draw_sampler_static_state) +	\
>      (PIPE_MAX_ATTRIBS-1) * sizeof(struct pipe_vertex_element))
>  
>  
>  static INLINE size_t
>  draw_llvm_variant_key_size(unsigned nr_vertex_elements,
> -			   unsigned nr_samplers)
> +                           unsigned nr_samplers)
>  {
>     return (sizeof(struct draw_llvm_variant_key) +
> -	   nr_samplers * sizeof(struct lp_sampler_static_state) +
> -	   (nr_vertex_elements - 1) * sizeof(struct pipe_vertex_element));
> +           nr_samplers * sizeof(struct draw_sampler_static_state) +
> +           (nr_vertex_elements - 1) * sizeof(struct
> pipe_vertex_element));
>  }
>  
>  
> -static INLINE struct lp_sampler_static_state *
> +static INLINE struct draw_sampler_static_state *
>  draw_llvm_variant_key_samplers(struct draw_llvm_variant_key *key)
>  {
> -   return (struct lp_sampler_static_state *)
> +   return (struct draw_sampler_static_state *)
>        &key->vertex_element[key->nr_vertex_elements];
>  }
>  
>  
> -
>  struct draw_llvm_variant_list_item
>  {
>     struct draw_llvm_variant *base;
> @@ -275,8 +307,8 @@ draw_llvm_destroy(struct draw_llvm *llvm);
>  
>  struct draw_llvm_variant *
>  draw_llvm_create_variant(struct draw_llvm *llvm,
> -			 unsigned num_vertex_header_attribs,
> -			 const struct draw_llvm_variant_key *key);
> +                         unsigned num_vertex_header_attribs,
> +                         const struct draw_llvm_variant_key *key);
>  
>  void
>  draw_llvm_destroy_variant(struct draw_llvm_variant *variant);
> @@ -288,7 +320,7 @@ void
>  draw_llvm_dump_variant_key(struct draw_llvm_variant_key *key);
>  
>  struct lp_build_sampler_soa *
> -draw_llvm_sampler_soa_create(const struct lp_sampler_static_state
> *static_state,
> +draw_llvm_sampler_soa_create(const struct draw_sampler_static_state
> *static_state,
>                               LLVMValueRef context_ptr);
>  
>  void
> diff --git a/src/gallium/auxiliary/draw/draw_llvm_sample.c
> b/src/gallium/auxiliary/draw/draw_llvm_sample.c
> index 67d4e93..ac1c031 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm_sample.c
> +++ b/src/gallium/auxiliary/draw/draw_llvm_sample.c
> @@ -58,7 +58,7 @@ struct draw_llvm_sampler_dynamic_state
>  {
>     struct lp_sampler_dynamic_state base;
>  
> -   const struct lp_sampler_static_state *static_state;
> +   const struct draw_sampler_static_state *static_state;
>  
>     LLVMValueRef context_ptr;
>  };
> @@ -98,7 +98,7 @@ draw_llvm_texture_member(const struct
> lp_sampler_dynamic_state *base,
>     LLVMValueRef ptr;
>     LLVMValueRef res;
>  
> -   debug_assert(unit < PIPE_MAX_SAMPLERS);
> +   debug_assert(unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
>  
>     /* context[0] */
>     indices[0] = lp_build_const_int32(gallivm, 0);
> @@ -123,6 +123,53 @@ draw_llvm_texture_member(const struct
> lp_sampler_dynamic_state *base,
>  
>  
>  /**
> + * Fetch the specified member of the lp_jit_sampler structure.
> + * \param emit_load  if TRUE, emit the LLVM load instruction to
> actually
> + *                   fetch the field's value.  Otherwise, just emit
> the
> + *                   GEP code to address the field.
> + *
> + * @sa http://llvm.org/docs/GetElementPtr.html
> + */
> +static LLVMValueRef
> +draw_llvm_sampler_member(const struct lp_sampler_dynamic_state
> *base,
> +                         struct gallivm_state *gallivm,
> +                         unsigned unit,
> +                         unsigned member_index,
> +                         const char *member_name,
> +                         boolean emit_load)
> +{
> +   LLVMBuilderRef builder = gallivm->builder;
> +   struct draw_llvm_sampler_dynamic_state *state =
> +      (struct draw_llvm_sampler_dynamic_state *)base;
> +   LLVMValueRef indices[4];
> +   LLVMValueRef ptr;
> +   LLVMValueRef res;
> +
> +   debug_assert(unit < PIPE_MAX_SAMPLERS);
> +
> +   /* context[0] */
> +   indices[0] = lp_build_const_int32(gallivm, 0);
> +   /* context[0].samplers */
> +   indices[1] = lp_build_const_int32(gallivm,
> DRAW_JIT_CTX_SAMPLERS);
> +   /* context[0].samplers[unit] */
> +   indices[2] = lp_build_const_int32(gallivm, unit);
> +   /* context[0].samplers[unit].member */
> +   indices[3] = lp_build_const_int32(gallivm, member_index);
> +
> +   ptr = LLVMBuildGEP(builder, state->context_ptr, indices,
> Elements(indices), "");
> +
> +   if (emit_load)
> +      res = LLVMBuildLoad(builder, ptr, "");
> +   else
> +      res = ptr;
> +
> +   lp_build_name(res, "context.sampler%u.%s", unit, member_name);
> +
> +   return res;
> +}
> +
> +
> +/**
>   * Helper macro to instantiate the functions that generate the code
>   to
>   * fetch the members of lp_jit_texture to fulfill the sampler code
>   * generator requests.
> @@ -150,10 +197,23 @@ DRAW_LLVM_TEXTURE_MEMBER(base_ptr,
>   DRAW_JIT_TEXTURE_BASE, TRUE)
>  DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE,
>  FALSE)
>  DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE,
>  FALSE)
>  DRAW_LLVM_TEXTURE_MEMBER(mip_offsets, DRAW_JIT_TEXTURE_MIP_OFFSETS,
>  FALSE)
> -DRAW_LLVM_TEXTURE_MEMBER(min_lod,    DRAW_JIT_TEXTURE_MIN_LOD, TRUE)
> -DRAW_LLVM_TEXTURE_MEMBER(max_lod,    DRAW_JIT_TEXTURE_MAX_LOD, TRUE)
> -DRAW_LLVM_TEXTURE_MEMBER(lod_bias,   DRAW_JIT_TEXTURE_LOD_BIAS,
> TRUE)
> -DRAW_LLVM_TEXTURE_MEMBER(border_color,
> DRAW_JIT_TEXTURE_BORDER_COLOR, FALSE)
> +
> +
> +#define DRAW_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load)  \
> +   static LLVMValueRef \
> +   draw_llvm_sampler_##_name( const struct lp_sampler_dynamic_state
> *base, \
> +                              struct gallivm_state *gallivm,
>               \
> +                              unsigned unit)
>                            \
> +   { \
> +      return draw_llvm_sampler_member(base, gallivm, unit, _index,
> #_name, _emit_load ); \
> +   }
> +
> +
> +DRAW_LLVM_SAMPLER_MEMBER(min_lod,    DRAW_JIT_SAMPLER_MIN_LOD, TRUE)
> +DRAW_LLVM_SAMPLER_MEMBER(max_lod,    DRAW_JIT_SAMPLER_MAX_LOD, TRUE)
> +DRAW_LLVM_SAMPLER_MEMBER(lod_bias,   DRAW_JIT_SAMPLER_LOD_BIAS,
> TRUE)
> +DRAW_LLVM_SAMPLER_MEMBER(border_color,
> DRAW_JIT_SAMPLER_BORDER_COLOR, FALSE)
> +
>  
>  
>  static void
> @@ -172,7 +232,8 @@ draw_llvm_sampler_soa_emit_fetch_texel(const
> struct lp_build_sampler_soa *base,
>                                         struct gallivm_state
>                                         *gallivm,
>                                         struct lp_type type,
>                                         boolean is_fetch,
> -                                       unsigned unit,
> +                                       unsigned texture_index,
> +                                       unsigned sampler_index,
>                                         const LLVMValueRef *coords,
>                                         const LLVMValueRef *offsets,
>                                         const struct lp_derivatives
>                                         *derivs,
> @@ -182,14 +243,17 @@ draw_llvm_sampler_soa_emit_fetch_texel(const
> struct lp_build_sampler_soa *base,
>  {
>     struct draw_llvm_sampler_soa *sampler = (struct
>     draw_llvm_sampler_soa *)base;
>  
> -   assert(unit < PIPE_MAX_SAMPLERS);
> +   assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
> +   assert(sampler_index < PIPE_MAX_SAMPLERS);
>  
>     lp_build_sample_soa(gallivm,
> -                       &sampler->dynamic_state.static_state[unit],
> +
>                       &sampler->dynamic_state.static_state[texture_index].texture_state,
> +
>                       &sampler->dynamic_state.static_state[sampler_index].sampler_state,
>                         &sampler->dynamic_state.base,
>                         type,
>                         is_fetch,
> -                       unit,
> +                       texture_index,
> +                       sampler_index,
>                         coords,
>                         offsets,
>                         derivs,
> @@ -214,7 +278,7 @@ draw_llvm_sampler_soa_emit_size_query(const
> struct lp_build_sampler_soa *base,
>     assert(unit < PIPE_MAX_SAMPLERS);
>  
>     lp_build_size_query_soa(gallivm,
> -
>                           &sampler->dynamic_state.static_state[unit],
> +
>                           &sampler->dynamic_state.static_state[unit].texture_state,
>                             &sampler->dynamic_state.base,
>                             type,
>                             unit,
> @@ -223,7 +287,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 lp_sampler_static_state
> *static_state,
> +draw_llvm_sampler_soa_create(const struct draw_sampler_static_state
> *static_state,
>                               LLVMValueRef context_ptr)
>  {
>     struct draw_llvm_sampler_soa *sampler;
> @@ -244,10 +308,10 @@ draw_llvm_sampler_soa_create(const struct
> lp_sampler_static_state *static_state,
>     sampler->dynamic_state.base.img_stride =
>     draw_llvm_texture_img_stride;
>     sampler->dynamic_state.base.base_ptr =
>     draw_llvm_texture_base_ptr;
>     sampler->dynamic_state.base.mip_offsets =
>     draw_llvm_texture_mip_offsets;
> -   sampler->dynamic_state.base.min_lod = draw_llvm_texture_min_lod;
> -   sampler->dynamic_state.base.max_lod = draw_llvm_texture_max_lod;
> -   sampler->dynamic_state.base.lod_bias =
> draw_llvm_texture_lod_bias;
> -   sampler->dynamic_state.base.border_color =
> draw_llvm_texture_border_color;
> +   sampler->dynamic_state.base.min_lod = draw_llvm_sampler_min_lod;
> +   sampler->dynamic_state.base.max_lod = draw_llvm_sampler_max_lod;
> +   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.context_ptr = context_ptr;
>  
> diff --git a/src/gallium/auxiliary/draw/draw_private.h
> b/src/gallium/auxiliary/draw/draw_private.h
> index 2223fcb..ec5791c 100644
> --- a/src/gallium/auxiliary/draw/draw_private.h
> +++ b/src/gallium/auxiliary/draw/draw_private.h
> @@ -310,7 +310,7 @@ struct draw_context
>      * we only handle vertex and geometry shaders in the draw module,
>      but
>      * there may be more in the future (ex: hull and tessellation).
>      */
> -   struct pipe_sampler_view
> *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
> +   struct pipe_sampler_view
> *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
>     unsigned num_sampler_views[PIPE_SHADER_TYPES];
>     const struct pipe_sampler_state
>     *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
>     unsigned num_samplers[PIPE_SHADER_TYPES];
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
> b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
> index 04f4135..4e4bca3 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
> @@ -87,24 +87,54 @@ lp_sampler_wrap_mode_uses_border_color(unsigned
> mode,
>  
>  
>  /**
> - * Initialize lp_sampler_static_state object with the gallium
> sampler
> - * and texture state.
> - * The former is considered to be static and the later dynamic.
> + * Initialize lp_sampler_static_texture_state object with the
> gallium
> + * texture/sampler_view state (this contains the parts which are
> + * considered static).
>   */
>  void
> -lp_sampler_static_state(struct lp_sampler_static_state *state,
> -                        const struct pipe_sampler_view *view,
> -                        const struct pipe_sampler_state *sampler)
> +lp_sampler_static_texture_state(struct lp_static_texture_state
> *state,
> +                                const struct pipe_sampler_view
> *view)
>  {
>     const struct pipe_resource *texture;
>  
>     memset(state, 0, sizeof *state);
>  
> -   if (!sampler || !view || !view->texture)
> +   if (!view || !view->texture)
>        return;
>  
>     texture = view->texture;
>  
> +   state->format            = view->format;
> +   state->swizzle_r         = view->swizzle_r;
> +   state->swizzle_g         = view->swizzle_g;
> +   state->swizzle_b         = view->swizzle_b;
> +   state->swizzle_a         = view->swizzle_a;
> +
> +   state->target            = texture->target;
> +   state->pot_width         = util_is_power_of_two(texture->width0);
> +   state->pot_height        =
> util_is_power_of_two(texture->height0);
> +   state->pot_depth         = util_is_power_of_two(texture->depth0);
> +   state->level_zero_only   = !view->u.tex.last_level;
> +
> +   /*
> +    * FIXME: Handle the remainder of pipe_sampler_view.
> +    */
> +}
> +
> +
> +/**
> + * Initialize lp_sampler_static_sampler_state object with the
> gallium sampler
> + * state (this contains the parts which are considered static).
> + */
> +void
> +lp_sampler_static_sampler_state(struct lp_static_sampler_state
> *state,
> +                                const struct pipe_sampler_state
> *sampler)
> +{
> +   memset(state, 0, sizeof *state);
> +
> +   if (!sampler)
> +      return;
> +
>     /*
>      * We don't copy sampler state over unless it is actually
>      enabled, to avoid
>      * spurious recompiles, as the sampler static state is part of
>      the shader
> @@ -117,24 +147,13 @@ lp_sampler_static_state(struct
> lp_sampler_static_state *state,
>      * regarding 1D/2D/3D/CUBE textures, wrap modes, etc.
>      */
>  
> -   state->format            = view->format;
> -   state->swizzle_r         = view->swizzle_r;
> -   state->swizzle_g         = view->swizzle_g;
> -   state->swizzle_b         = view->swizzle_b;
> -   state->swizzle_a         = view->swizzle_a;
> -
> -   state->target            = texture->target;
> -   state->pot_width         = util_is_power_of_two(texture->width0);
> -   state->pot_height        =
> util_is_power_of_two(texture->height0);
> -   state->pot_depth         = util_is_power_of_two(texture->depth0);
> -
>     state->wrap_s            = sampler->wrap_s;
>     state->wrap_t            = sampler->wrap_t;
>     state->wrap_r            = sampler->wrap_r;
>     state->min_img_filter    = sampler->min_img_filter;
>     state->mag_img_filter    = sampler->mag_img_filter;
>  
> -   if (view->u.tex.last_level && sampler->max_lod > 0.0f) {
> +   if (sampler->max_lod > 0.0f) {
>        state->min_mip_filter = sampler->min_mip_filter;
>     } else {
>        state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
> @@ -155,7 +174,11 @@ lp_sampler_static_state(struct
> lp_sampler_static_state *state,
>              state->apply_min_lod = 1;
>           }
>  
> -         if (sampler->max_lod < (float)view->u.tex.last_level) {
> +         /*
> +          * XXX this won't do anything with the mesa state tracker
> which always
> +          * sets max_lod to not more than actually present mip
> maps...
> +          */
> +         if (sampler->max_lod < (PIPE_MAX_TEXTURE_LEVELS - 1)) {
>              state->apply_max_lod = 1;
>           }
>        }
> @@ -167,10 +190,6 @@ lp_sampler_static_state(struct
> lp_sampler_static_state *state,
>     }
>  
>     state->normalized_coords = sampler->normalized_coords;
> -
> -   /*
> -    * FIXME: Handle the remainder of pipe_sampler_view.
> -    */
>  }
>  
>  
> @@ -182,7 +201,7 @@ lp_sampler_static_state(struct
> lp_sampler_static_state *state,
>   */
>  static LLVMValueRef
>  lp_build_rho(struct lp_build_sample_context *bld,
> -             unsigned unit,
> +             unsigned texture_unit,
>               const struct lp_derivatives *derivs)
>  {
>     struct gallivm_state *gallivm = bld->gallivm;
> @@ -264,7 +283,7 @@ lp_build_rho(struct lp_build_sample_context *bld,
>     rho_vec = lp_build_max(coord_bld, rho_xvec, rho_yvec);
>  
>     first_level = bld->dynamic_state->first_level(bld->dynamic_state,
> -                                                 bld->gallivm,
> unit);
> +                                                 bld->gallivm,
> texture_unit);
>     first_level_vec = lp_build_broadcast_scalar(int_size_bld,
>     first_level);
>     int_size = lp_build_minify(int_size_bld, bld->int_size,
>     first_level_vec);
>     float_size = lp_build_int_to_float(float_size_bld, int_size);
> @@ -489,7 +508,8 @@ lp_build_brilinear_rho(struct lp_build_context
> *bld,
>   */
>  void
>  lp_build_lod_selector(struct lp_build_sample_context *bld,
> -                      unsigned unit,
> +                      unsigned texture_unit,
> +                      unsigned sampler_unit,
>                        const struct lp_derivatives *derivs,
>                        LLVMValueRef lod_bias, /* optional */
>                        LLVMValueRef explicit_lod, /* optional */
> @@ -505,12 +525,13 @@ lp_build_lod_selector(struct
> lp_build_sample_context *bld,
>     *out_lod_ipart = bld->perquadi_bld.zero;
>     *out_lod_fpart = perquadf_bld->zero;
>  
> -   if (bld->static_state->min_max_lod_equal) {
> +   if (bld->static_sampler_state->min_max_lod_equal) {
>        /* User is forcing sampling from a particular mipmap level.
>         * This is hit during mipmap generation.
>         */
>        LLVMValueRef min_lod =
> -         bld->dynamic_state->min_lod(bld->dynamic_state,
> bld->gallivm, unit);
> +         bld->dynamic_state->min_lod(bld->dynamic_state,
> +                                     bld->gallivm, sampler_unit);
>  
>        lod = lp_build_broadcast_scalar(perquadf_bld, min_lod);
>     }
> @@ -522,16 +543,16 @@ lp_build_lod_selector(struct
> lp_build_sample_context *bld,
>        else {
>           LLVMValueRef rho;
>  
> -         rho = lp_build_rho(bld, unit, derivs);
> +         rho = lp_build_rho(bld, texture_unit, derivs);
>  
>           /*
>            * Compute lod = log2(rho)
>            */
>  
>           if (!lod_bias &&
> -             !bld->static_state->lod_bias_non_zero &&
> -             !bld->static_state->apply_max_lod &&
> -             !bld->static_state->apply_min_lod) {
> +             !bld->static_sampler_state->lod_bias_non_zero &&
> +             !bld->static_sampler_state->apply_max_lod &&
> +             !bld->static_sampler_state->apply_min_lod) {
>              /*
>               * Special case when there are no post-log2 adjustments,
>               which
>               * saves instructions but keeping the integer and
>               fractional lod
> @@ -568,25 +589,28 @@ lp_build_lod_selector(struct
> lp_build_sample_context *bld,
>        }
>  
>        /* add sampler lod bias */
> -      if (bld->static_state->lod_bias_non_zero) {
> +      if (bld->static_sampler_state->lod_bias_non_zero) {
>           LLVMValueRef sampler_lod_bias =
> -            bld->dynamic_state->lod_bias(bld->dynamic_state,
> bld->gallivm, unit);
> +            bld->dynamic_state->lod_bias(bld->dynamic_state,
> +                                         bld->gallivm,
> sampler_unit);
>           sampler_lod_bias = lp_build_broadcast_scalar(perquadf_bld,
>                                                        sampler_lod_bias);
>           lod = LLVMBuildFAdd(builder, lod, sampler_lod_bias,
>           "sampler_lod_bias");
>        }
>  
>        /* clamp lod */
> -      if (bld->static_state->apply_max_lod) {
> +      if (bld->static_sampler_state->apply_max_lod) {
>           LLVMValueRef max_lod =
> -            bld->dynamic_state->max_lod(bld->dynamic_state,
> bld->gallivm, unit);
> +            bld->dynamic_state->max_lod(bld->dynamic_state,
> +                                        bld->gallivm, sampler_unit);
>           max_lod = lp_build_broadcast_scalar(perquadf_bld, max_lod);
>  
>           lod = lp_build_min(perquadf_bld, lod, max_lod);
>        }
> -      if (bld->static_state->apply_min_lod) {
> +      if (bld->static_sampler_state->apply_min_lod) {
>           LLVMValueRef min_lod =
> -            bld->dynamic_state->min_lod(bld->dynamic_state,
> bld->gallivm, unit);
> +            bld->dynamic_state->min_lod(bld->dynamic_state,
> +                                        bld->gallivm, sampler_unit);
>           min_lod = lp_build_broadcast_scalar(perquadf_bld, min_lod);
>  
>           lod = lp_build_max(perquadf_bld, lod, min_lod);
> @@ -988,9 +1012,9 @@ lp_build_mipmap_level_sizes(struct
> lp_build_sample_context *bld,
>                                                        ilevel);
>     }
>     if (dims == 3 ||
> -       bld->static_state->target == PIPE_TEXTURE_CUBE ||
> -       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
> -       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
> +       bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>        *img_stride_vec = lp_build_get_level_stride_vec(bld,
>                                                        bld->img_stride_array,
>                                                        ilevel);
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
> b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
> index 87bf556..d0207aa 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
> @@ -61,12 +61,12 @@ struct lp_derivatives
>  
>  
>  /**
> - * Sampler static state.
> + * Texture static state.
>   *
> - * These are the bits of state from pipe_resource and
> pipe_sampler_state that
> + * These are the bits of state from pipe_resource/pipe_sampler_view
> that
>   * are embedded in the generated code.
>   */
> -struct lp_sampler_static_state
> +struct lp_static_texture_state
>  {
>     /* pipe_sampler_view's state */
>     enum pipe_format format;
> @@ -80,7 +80,18 @@ struct lp_sampler_static_state
>     unsigned pot_width:1;     /**< is the width a power of two? */
>     unsigned pot_height:1;
>     unsigned pot_depth:1;
> +   unsigned level_zero_only:1;
> +};
>  
> +
> +/**
> + * Sampler static state.
> + *
> + * These are the bits of state from pipe_sampler_state that
> + * are embedded in the generated code.
> + */
> +struct lp_static_sampler_state
> +{
>     /* pipe_sampler_state's state */
>     unsigned wrap_s:3;
>     unsigned wrap_t:3;
> @@ -105,8 +116,8 @@ struct lp_sampler_static_state
>  /**
>   * Sampler dynamic state.
>   *
> - * These are the bits of state from pipe_resource and
> pipe_sampler_state that
> - * are computed in runtime.
> + * These are the bits of state from pipe_resource/pipe_sampler_view
> + * as well as from sampler state that are computed at runtime.
>   *
>   * There are obtained through callbacks, as we don't want to tie the
>   texture
>   * sampling code generation logic to any particular texture layout
>   or pipe
> @@ -114,6 +125,7 @@ struct lp_sampler_static_state
>   */
>  struct lp_sampler_dynamic_state
>  {
> +   /* First callbacks for sampler view state */
>  
>     /** Obtain the base texture width (returns int32) */
>     LLVMValueRef
> @@ -169,6 +181,8 @@ struct lp_sampler_dynamic_state
>                     struct gallivm_state *gallivm,
>                     unsigned unit);
>  
> +   /* These are callbacks for sampler state */
> +
>     /** Obtain texture min lod (returns float) */
>     LLVMValueRef
>     (*min_lod)(const struct lp_sampler_dynamic_state *state,
> @@ -198,7 +212,8 @@ struct lp_build_sample_context
>  {
>     struct gallivm_state *gallivm;
>  
> -   const struct lp_sampler_static_state *static_state;
> +   const struct lp_static_texture_state *static_texture_state;
> +   const struct lp_static_sampler_state *static_sampler_state;
>  
>     struct lp_sampler_dynamic_state *dynamic_state;
>  
> @@ -295,10 +310,10 @@ apply_sampler_swizzle(struct
> lp_build_sample_context *bld,
>  {
>     unsigned char swizzles[4];
>  
> -   swizzles[0] = bld->static_state->swizzle_r;
> -   swizzles[1] = bld->static_state->swizzle_g;
> -   swizzles[2] = bld->static_state->swizzle_b;
> -   swizzles[3] = bld->static_state->swizzle_a;
> +   swizzles[0] = bld->static_texture_state->swizzle_r;
> +   swizzles[1] = bld->static_texture_state->swizzle_g;
> +   swizzles[2] = bld->static_texture_state->swizzle_b;
> +   swizzles[3] = bld->static_texture_state->swizzle_a;
>  
>     lp_build_swizzle_soa_inplace(&bld->texel_bld, texel, swizzles);
>  }
> @@ -338,14 +353,19 @@ lp_sampler_wrap_mode_uses_border_color(unsigned
> mode,
>   * Derive the sampler static state.
>   */
>  void
> -lp_sampler_static_state(struct lp_sampler_static_state *state,
> -                        const struct pipe_sampler_view *view,
> -                        const struct pipe_sampler_state *sampler);
> +lp_sampler_static_sampler_state(struct lp_static_sampler_state
> *state,
> +                                const struct pipe_sampler_state
> *sampler);
> +
> +
> +void
> +lp_sampler_static_texture_state(struct lp_static_texture_state
> *state,
> +                                const struct pipe_sampler_view
> *view);
>  
>  
>  void
>  lp_build_lod_selector(struct lp_build_sample_context *bld,
> -                      unsigned unit,
> +                      unsigned texture_index,
> +                      unsigned sampler_index,
>                        const struct lp_derivatives *derivs,
>                        LLVMValueRef lod_bias, /* optional */
>                        LLVMValueRef explicit_lod, /* optional */
> @@ -437,11 +457,13 @@ lp_build_sample_offset(struct lp_build_context
> *bld,
>  
>  void
>  lp_build_sample_soa(struct gallivm_state *gallivm,
> -                    const struct lp_sampler_static_state
> *static_state,
> -                    struct lp_sampler_dynamic_state *dynamic_state,
> +                    const struct lp_static_texture_state
> *static_texture_state,
> +                    const struct lp_static_sampler_state
> *static_sampler_state,
> +                    struct lp_sampler_dynamic_state
> *dynamic_texture_state,
>                      struct lp_type fp_type,
>                      boolean is_fetch,
> -                    unsigned unit,
> +                    unsigned texture_index,
> +                    unsigned sampler_index,
>                      const LLVMValueRef *coords,
>                      const LLVMValueRef *offsets,
>                      const struct lp_derivatives *derivs,
> @@ -461,7 +483,7 @@ lp_build_coord_repeat_npot_linear(struct
> lp_build_sample_context *bld,
>  
>  void
>  lp_build_size_query_soa(struct gallivm_state *gallivm,
> -                        const struct lp_sampler_static_state
> *static_state,
> +                        const struct lp_static_texture_state
> *static_state,
>                          struct lp_sampler_dynamic_state
>                          *dynamic_state,
>                          struct lp_type int_type,
>                          unsigned unit,
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
> b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
> index 9371e1c..b9c8446 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
> @@ -152,7 +152,7 @@ lp_build_sample_wrap_nearest_float(struct
> lp_build_sample_context *bld,
>        break;
>     case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
>        length_minus_one = lp_build_sub(coord_bld, length,
>        coord_bld->one);
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* scale coord to length */
>           coord = lp_build_mul(coord_bld, coord, length);
>        }
> @@ -407,7 +407,7 @@ lp_build_sample_wrap_linear_float(struct
> lp_build_sample_context *bld,
>        }
>        break;
>     case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* mul by tex size */
>           coord = lp_build_mul(coord_bld, coord, length);
>        }
> @@ -549,7 +549,7 @@ lp_build_sample_image_nearest(struct
> lp_build_sample_context *bld,
>  
>     s_float = s; t_float = t; r_float = r;
>  
> -   if (bld->static_state->normalized_coords) {
> +   if (bld->static_sampler_state->normalized_coords) {
>        LLVMValueRef scaled_size;
>        LLVMValueRef flt_size;
>  
> @@ -594,8 +594,8 @@ lp_build_sample_image_nearest(struct
> lp_build_sample_context *bld,
>                                      bld->format_desc->block.width,
>                                      s_ipart, s_float,
>                                      width_vec, x_stride,
> -                                    bld->static_state->pot_width,
> -                                    bld->static_state->wrap_s,
> +
>                                    bld->static_texture_state->pot_width,
> +
>                                    bld->static_sampler_state->wrap_s,
>                                      &x_offset, &x_subcoord);
>     offset = x_offset;
>     if (dims >= 2) {
> @@ -604,8 +604,8 @@ lp_build_sample_image_nearest(struct
> lp_build_sample_context *bld,
>                                         bld->format_desc->block.height,
>                                         t_ipart, t_float,
>                                         height_vec, row_stride_vec,
> -
>                                       bld->static_state->pot_height,
> -                                       bld->static_state->wrap_t,
> +
>                                       bld->static_texture_state->pot_height,
> +
>                                       bld->static_sampler_state->wrap_t,
>                                         &y_offset, &y_subcoord);
>        offset = lp_build_add(&bld->int_coord_bld, offset, y_offset);
>        if (dims >= 3) {
> @@ -614,15 +614,15 @@ lp_build_sample_image_nearest(struct
> lp_build_sample_context *bld,
>                                            1, /* block length (depth)
>                                            */
>                                            r_ipart, r_float,
>                                            depth_vec, img_stride_vec,
> -
>                                          bld->static_state->pot_depth,
> -                                          bld->static_state->wrap_r,
> +
>                                          bld->static_texture_state->pot_depth,
> +
>                                          bld->static_sampler_state->wrap_r,
>                                            &z_offset, &z_subcoord);
>           offset = lp_build_add(&bld->int_coord_bld, offset,
>           z_offset);
>        }
>     }
> -   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
> -       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
> -       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
> +   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>        LLVMValueRef z_offset;
>        /* The r coord is the cube face in [0,5] or array layer */
>        z_offset = lp_build_mul(&bld->int_coord_bld, r,
>        img_stride_vec);
> @@ -678,28 +678,28 @@ lp_build_sample_image_nearest_afloat(struct
> lp_build_sample_context *bld,
>     /* Do texcoord wrapping */
>     lp_build_sample_wrap_nearest_float(bld,
>                                        s, width_vec,
> -                                      bld->static_state->pot_width,
> -                                      bld->static_state->wrap_s,
> +
>                                      bld->static_texture_state->pot_width,
> +
>                                      bld->static_sampler_state->wrap_s,
>                                        &x_icoord);
>  
>     if (dims >= 2) {
>        lp_build_sample_wrap_nearest_float(bld,
>                                           t, height_vec,
> -
>                                         bld->static_state->pot_height,
> -                                         bld->static_state->wrap_t,
> +
>                                         bld->static_texture_state->pot_height,
> +
>                                         bld->static_sampler_state->wrap_t,
>                                           &y_icoord);
>  
>        if (dims >= 3) {
>           lp_build_sample_wrap_nearest_float(bld,
>                                              r, depth_vec,
> -
>                                            bld->static_state->pot_depth,
> -
>                                            bld->static_state->wrap_r,
> +
>                                            bld->static_texture_state->pot_depth,
> +
>                                            bld->static_sampler_state->wrap_r,
>                                              &z_icoord);
>        }
>     }
> -   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
> -       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
> -       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
> +   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>        z_icoord = r;
>     }
>  
> @@ -885,7 +885,7 @@ lp_build_sample_fetch_image_linear(struct
> lp_build_sample_context *bld,
>     /*
>      * Linear interpolation with 8.8 fixed point.
>      */
> -   if (bld->static_state->force_nearest_s) {
> +   if (bld->static_sampler_state->force_nearest_s) {
>        /* special case 1-D lerp */
>        packed_lo = lp_build_lerp(&h16,
>                                  t_fpart_lo,
> @@ -897,7 +897,7 @@ lp_build_sample_fetch_image_linear(struct
> lp_build_sample_context *bld,
>                                  neighbors_hi[0][1][0],
>                                  neighbors_hi[0][1][0]);
>     }
> -   else if (bld->static_state->force_nearest_t) {
> +   else if (bld->static_sampler_state->force_nearest_t) {
>        /* special case 1-D lerp */
>        packed_lo = lp_build_lerp(&h16,
>                                  s_fpart_lo,
> @@ -1016,7 +1016,7 @@ lp_build_sample_image_linear(struct
> lp_build_sample_context *bld,
>  
>     s_float = s; t_float = t; r_float = r;
>  
> -   if (bld->static_state->normalized_coords) {
> +   if (bld->static_sampler_state->normalized_coords) {
>        LLVMValueRef scaled_size;
>        LLVMValueRef flt_size;
>  
> @@ -1045,10 +1045,10 @@ lp_build_sample_image_linear(struct
> lp_build_sample_context *bld,
>  
>     /* subtract 0.5 (add -128) */
>     i32_c128 = lp_build_const_int_vec(bld->gallivm, i32.type, -128);
> -   if (!bld->static_state->force_nearest_s) {
> +   if (!bld->static_sampler_state->force_nearest_s) {
>        s = LLVMBuildAdd(builder, s, i32_c128, "");
>     }
> -   if (dims >= 2 && !bld->static_state->force_nearest_t) {
> +   if (dims >= 2 && !bld->static_sampler_state->force_nearest_t) {
>        t = LLVMBuildAdd(builder, t, i32_c128, "");
>     }
>     if (dims >= 3) {
> @@ -1082,15 +1082,15 @@ lp_build_sample_image_linear(struct
> lp_build_sample_context *bld,
>                                     bld->format_desc->block.width,
>                                     s_ipart, &s_fpart, s_float,
>                                     width_vec, x_stride,
> -                                   bld->static_state->pot_width,
> -                                   bld->static_state->wrap_s,
> +
>                                   bld->static_texture_state->pot_width,
> +
>                                   bld->static_sampler_state->wrap_s,
>                                     &x_offset0, &x_offset1,
>                                     &x_subcoord[0], &x_subcoord[1]);
>  
>     /* add potential cube/array/mip offsets now as they are constant
>     per pixel */
> -   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
> -       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
> -       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
> +   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>        LLVMValueRef z_offset;
>        z_offset = lp_build_mul(&bld->int_coord_bld, r,
>        img_stride_vec);
>        /* The r coord is the cube face in [0,5] or array layer */
> @@ -1114,8 +1114,8 @@ lp_build_sample_image_linear(struct
> lp_build_sample_context *bld,
>                                        bld->format_desc->block.height,
>                                        t_ipart, &t_fpart, t_float,
>                                        height_vec, y_stride,
> -                                      bld->static_state->pot_height,
> -                                      bld->static_state->wrap_t,
> +
>                                      bld->static_texture_state->pot_height,
> +
>                                      bld->static_sampler_state->wrap_t,
>                                        &y_offset0, &y_offset1,
>                                        &y_subcoord[0],
>                                        &y_subcoord[1]);
>  
> @@ -1134,8 +1134,8 @@ lp_build_sample_image_linear(struct
> lp_build_sample_context *bld,
>                                        bld->format_desc->block.height,
>                                        r_ipart, &r_fpart, r_float,
>                                        depth_vec, z_stride,
> -                                      bld->static_state->pot_depth,
> -                                      bld->static_state->wrap_r,
> +
>                                      bld->static_texture_state->pot_depth,
> +
>                                      bld->static_sampler_state->wrap_r,
>                                        &z_offset0, &z_offset1,
>                                        &z_subcoord[0],
>                                        &z_subcoord[1]);
>        for (y = 0; y < 2; y++) {
> @@ -1205,28 +1205,28 @@ lp_build_sample_image_linear_afloat(struct
> lp_build_sample_context *bld,
>     lp_build_sample_wrap_linear_float(bld,
>                                       bld->format_desc->block.width,
>                                       s, width_vec,
> -                                     bld->static_state->pot_width,
> -                                     bld->static_state->wrap_s,
> +
>                                     bld->static_texture_state->pot_width,
> +
>                                     bld->static_sampler_state->wrap_s,
>                                       &x_icoord0, &x_icoord1,
>                                       &s_fpart,
> -
>                                     bld->static_state->force_nearest_s);
> +
>                                     bld->static_sampler_state->force_nearest_s);
>  
>     if (dims >= 2) {
>        lp_build_sample_wrap_linear_float(bld,
>                                          bld->format_desc->block.height,
>                                          t, height_vec,
> -
>                                        bld->static_state->pot_height,
> -                                        bld->static_state->wrap_t,
> +
>                                        bld->static_texture_state->pot_height,
> +
>                                        bld->static_sampler_state->wrap_t,
>                                          &y_icoord0, &y_icoord1,
>                                          &t_fpart,
> -
>                                        bld->static_state->force_nearest_t);
> +
>                                        bld->static_sampler_state->force_nearest_t);
>  
>        if (dims >= 3) {
>           lp_build_sample_wrap_linear_float(bld,
>                                             bld->format_desc->block.height,
>                                             r, depth_vec,
> -
>                                           bld->static_state->pot_depth,
> -
>                                           bld->static_state->wrap_r,
> +
>                                           bld->static_texture_state->pot_depth,
> +
>                                           bld->static_sampler_state->wrap_r,
>                                             &z_icoord0, &z_icoord1,
>                                             &r_fpart, 0);
>        }
> @@ -1259,9 +1259,9 @@ lp_build_sample_image_linear_afloat(struct
> lp_build_sample_context *bld,
>                                    &x_offset1, &x_subcoord[1]);
>  
>     /* add potential cube/array/mip offsets now as they are constant
>     per pixel */
> -   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
> -       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
> -       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
> +   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>        LLVMValueRef z_offset;
>        z_offset = lp_build_mul(&bld->int_coord_bld, r,
>        img_stride_vec);
>        /* The r coord is the cube face in [0,5] or array layer */
> @@ -1582,20 +1582,20 @@ lp_build_sample_aos(struct
> lp_build_sample_context *bld,
>  {
>     struct lp_build_context *int_bld = &bld->int_bld;
>     LLVMBuilderRef builder = bld->gallivm->builder;
> -   const unsigned mip_filter = bld->static_state->min_mip_filter;
> -   const unsigned min_filter = bld->static_state->min_img_filter;
> -   const unsigned mag_filter = bld->static_state->mag_img_filter;
> +   const unsigned mip_filter =
> bld->static_sampler_state->min_mip_filter;
> +   const unsigned min_filter =
> bld->static_sampler_state->min_img_filter;
> +   const unsigned mag_filter =
> bld->static_sampler_state->mag_img_filter;
>     const unsigned dims = bld->dims;
>     LLVMValueRef packed, packed_lo, packed_hi;
>     LLVMValueRef unswizzled[4];
>     struct lp_build_context h16_bld;
>  
>     /* we only support the common/simple wrap modes at this time */
> -   assert(lp_is_simple_wrap_mode(bld->static_state->wrap_s));
> +
>   assert(lp_is_simple_wrap_mode(bld->static_sampler_state->wrap_s));
>     if (dims >= 2)
> -      assert(lp_is_simple_wrap_mode(bld->static_state->wrap_t));
> +
>      assert(lp_is_simple_wrap_mode(bld->static_sampler_state->wrap_t));
>     if (dims >= 3)
> -      assert(lp_is_simple_wrap_mode(bld->static_state->wrap_r));
> +
>      assert(lp_is_simple_wrap_mode(bld->static_sampler_state->wrap_r));
>  
>  
>     /* make 16-bit fixed-pt builder context */
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
> b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
> index 918dd36..0e90194 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
> @@ -85,7 +85,7 @@ lp_build_sample_texel_soa(struct
> lp_build_sample_context *bld,
>                            LLVMValueRef mipoffsets,
>                            LLVMValueRef texel_out[4])
>  {
> -   const struct lp_sampler_static_state *static_state =
> bld->static_state;
> +   const struct lp_static_sampler_state *static_state =
> bld->static_sampler_state;
>     const unsigned dims = bld->dims;
>     struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
>     LLVMBuilderRef builder = bld->gallivm->builder;
> @@ -317,7 +317,7 @@ lp_build_sample_wrap_linear(struct
> lp_build_sample_context *bld,
>        break;
>  
>     case PIPE_TEX_WRAP_CLAMP:
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* scale coord to length */
>           coord = lp_build_mul(coord_bld, coord, length_f);
>        }
> @@ -337,7 +337,7 @@ lp_build_sample_wrap_linear(struct
> lp_build_sample_context *bld,
>           struct lp_build_context abs_coord_bld = bld->coord_bld;
>           abs_coord_bld.type.sign = FALSE;
>  
> -         if (bld->static_state->normalized_coords) {
> +         if (bld->static_sampler_state->normalized_coords) {
>              /* mul by tex size */
>              coord = lp_build_mul(coord_bld, coord, length_f);
>           }
> @@ -356,7 +356,7 @@ lp_build_sample_wrap_linear(struct
> lp_build_sample_context *bld,
>        }
>  
>     case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* scale coord to length */
>           coord = lp_build_mul(coord_bld, coord, length_f);
>        }
> @@ -389,7 +389,7 @@ lp_build_sample_wrap_linear(struct
> lp_build_sample_context *bld,
>     case PIPE_TEX_WRAP_MIRROR_CLAMP:
>        coord = lp_build_abs(coord_bld, coord);
>  
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* scale coord to length */
>           coord = lp_build_mul(coord_bld, coord, length_f);
>        }
> @@ -411,7 +411,7 @@ lp_build_sample_wrap_linear(struct
> lp_build_sample_context *bld,
>           abs_coord_bld.type.sign = FALSE;
>           coord = lp_build_abs(coord_bld, coord);
>  
> -         if (bld->static_state->normalized_coords) {
> +         if (bld->static_sampler_state->normalized_coords) {
>              /* scale coord to length */
>              coord = lp_build_mul(coord_bld, coord, length_f);
>           }
> @@ -433,7 +433,7 @@ lp_build_sample_wrap_linear(struct
> lp_build_sample_context *bld,
>        {
>           coord = lp_build_abs(coord_bld, coord);
>  
> -         if (bld->static_state->normalized_coords) {
> +         if (bld->static_sampler_state->normalized_coords) {
>              /* scale coord to length */
>              coord = lp_build_mul(coord_bld, coord, length_f);
>           }
> @@ -500,7 +500,7 @@ lp_build_sample_wrap_nearest(struct
> lp_build_sample_context *bld,
>  
>     case PIPE_TEX_WRAP_CLAMP:
>     case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* scale coord to length */
>           coord = lp_build_mul(coord_bld, coord, length_f);
>        }
> @@ -515,7 +515,7 @@ lp_build_sample_wrap_nearest(struct
> lp_build_sample_context *bld,
>        break;
>  
>     case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* scale coord to length */
>           coord = lp_build_mul(coord_bld, coord, length_f);
>        }
> @@ -528,7 +528,7 @@ lp_build_sample_wrap_nearest(struct
> lp_build_sample_context *bld,
>        coord = lp_build_coord_mirror(bld, coord);
>  
>        /* scale coord to length */
> -      assert(bld->static_state->normalized_coords);
> +      assert(bld->static_sampler_state->normalized_coords);
>        coord = lp_build_mul(coord_bld, coord, length_f);
>  
>        /* itrunc == ifloor here */
> @@ -542,7 +542,7 @@ lp_build_sample_wrap_nearest(struct
> lp_build_sample_context *bld,
>     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
>        coord = lp_build_abs(coord_bld, coord);
>  
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* scale coord to length */
>           coord = lp_build_mul(coord_bld, coord, length_f);
>        }
> @@ -557,7 +557,7 @@ lp_build_sample_wrap_nearest(struct
> lp_build_sample_context *bld,
>     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
>        coord = lp_build_abs(coord_bld, coord);
>  
> -      if (bld->static_state->normalized_coords) {
> +      if (bld->static_sampler_state->normalized_coords) {
>           /* scale coord to length */
>           coord = lp_build_mul(coord_bld, coord, length_f);
>        }
> @@ -620,26 +620,26 @@ lp_build_sample_image_nearest(struct
> lp_build_sample_context *bld,
>      * Compute integer texcoords.
>      */
>     x = lp_build_sample_wrap_nearest(bld, s, width_vec,
>     flt_width_vec,
> -                                    bld->static_state->pot_width,
> -                                    bld->static_state->wrap_s);
> +
>                                    bld->static_texture_state->pot_width,
> +
>                                    bld->static_sampler_state->wrap_s);
>     lp_build_name(x, "tex.x.wrapped");
>  
>     if (dims >= 2) {
>        y = lp_build_sample_wrap_nearest(bld, t, height_vec,
>        flt_height_vec,
> -
>                                       bld->static_state->pot_height,
> -                                       bld->static_state->wrap_t);
> +
>                                       bld->static_texture_state->pot_height,
> +
>                                       bld->static_sampler_state->wrap_t);
>        lp_build_name(y, "tex.y.wrapped");
>  
>        if (dims == 3) {
>           z = lp_build_sample_wrap_nearest(bld, r, depth_vec,
>           flt_depth_vec,
> -
>                                          bld->static_state->pot_depth,
> -
>                                          bld->static_state->wrap_r);
> +
>                                          bld->static_texture_state->pot_depth,
> +
>                                          bld->static_sampler_state->wrap_r);
>           lp_build_name(z, "tex.z.wrapped");
>        }
>     }
> -   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
> -       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
> -       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
> +   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>        z = r;
>        lp_build_name(z, "tex.z.layer");
>     }
> @@ -703,32 +703,32 @@ lp_build_sample_image_linear(struct
> lp_build_sample_context *bld,
>      * Compute integer texcoords.
>      */
>     lp_build_sample_wrap_linear(bld, s, width_vec, flt_width_vec,
> -                               bld->static_state->pot_width,
> -                               bld->static_state->wrap_s,
> +                               bld->static_texture_state->pot_width,
> +                               bld->static_sampler_state->wrap_s,
>                                 &x0, &x1, &s_fpart);
>     lp_build_name(x0, "tex.x0.wrapped");
>     lp_build_name(x1, "tex.x1.wrapped");
>  
>     if (dims >= 2) {
>        lp_build_sample_wrap_linear(bld, t, height_vec,
>        flt_height_vec,
> -                                  bld->static_state->pot_height,
> -                                  bld->static_state->wrap_t,
> +
>                                  bld->static_texture_state->pot_height,
> +                                  bld->static_sampler_state->wrap_t,
>                                    &y0, &y1, &t_fpart);
>        lp_build_name(y0, "tex.y0.wrapped");
>        lp_build_name(y1, "tex.y1.wrapped");
>  
>        if (dims == 3) {
>           lp_build_sample_wrap_linear(bld, r, depth_vec,
>           flt_depth_vec,
> -                                     bld->static_state->pot_depth,
> -                                     bld->static_state->wrap_r,
> +
>                                     bld->static_texture_state->pot_depth,
> +
>                                     bld->static_sampler_state->wrap_r,
>                                       &z0, &z1, &r_fpart);
>           lp_build_name(z0, "tex.z0.wrapped");
>           lp_build_name(z1, "tex.z1.wrapped");
>        }
>     }
> -   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
> -       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
> -       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
> +   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>        z0 = z1 = r;  /* cube face or array layer */
>        lp_build_name(z0, "tex.z0.layer");
>        lp_build_name(z1, "tex.z1.layer");
> @@ -1004,7 +1004,8 @@ lp_build_layer_coord(struct
> lp_build_sample_context *bld,
>   */
>  static void
>  lp_build_sample_common(struct lp_build_sample_context *bld,
> -                       unsigned unit,
> +                       unsigned texture_index,
> +                       unsigned sampler_index,
>                         LLVMValueRef *s,
>                         LLVMValueRef *t,
>                         LLVMValueRef *r,
> @@ -1016,10 +1017,10 @@ lp_build_sample_common(struct
> lp_build_sample_context *bld,
>                         LLVMValueRef *ilevel0,
>                         LLVMValueRef *ilevel1)
>  {
> -   const unsigned mip_filter = bld->static_state->min_mip_filter;
> -   const unsigned min_filter = bld->static_state->min_img_filter;
> -   const unsigned mag_filter = bld->static_state->mag_img_filter;
> -   const unsigned target = bld->static_state->target;
> +   const unsigned mip_filter =
> bld->static_sampler_state->min_mip_filter;
> +   const unsigned min_filter =
> bld->static_sampler_state->min_img_filter;
> +   const unsigned mag_filter =
> bld->static_sampler_state->mag_img_filter;
> +   const unsigned target = bld->static_texture_state->target;
>     LLVMValueRef first_level;
>     struct lp_derivatives face_derivs;
>  
> @@ -1046,11 +1047,11 @@ lp_build_sample_common(struct
> lp_build_sample_context *bld,
>     }
>     else if (target == PIPE_TEXTURE_1D_ARRAY) {
>        *r = lp_build_iround(&bld->coord_bld, *t);
> -      *r = lp_build_layer_coord(bld, unit, *r);
> +      *r = lp_build_layer_coord(bld, texture_index, *r);
>     }
>     else if (target == PIPE_TEXTURE_2D_ARRAY) {
>        *r = lp_build_iround(&bld->coord_bld, *r);
> -      *r = lp_build_layer_coord(bld, unit, *r);
> +      *r = lp_build_layer_coord(bld, texture_index, *r);
>     }
>  
>     /*
> @@ -1061,8 +1062,8 @@ lp_build_sample_common(struct
> lp_build_sample_context *bld,
>        /* Need to compute lod either to choose mipmap levels or to
>         * distinguish between minification/magnification with one
>         mipmap level.
>         */
> -      lp_build_lod_selector(bld, unit, derivs,
> -                            lod_bias, explicit_lod,
> +      lp_build_lod_selector(bld, texture_index, sampler_index,
> +                            derivs, lod_bias, explicit_lod,
>                              mip_filter,
>                              lod_ipart, lod_fpart);
>     } else {
> @@ -1085,23 +1086,23 @@ lp_build_sample_common(struct
> lp_build_sample_context *bld,
>            * XXX should probably disable that on other llvm versions.
>            */
>           assert(*lod_ipart);
> -         lp_build_nearest_mip_level(bld, unit, *lod_ipart, ilevel0);
> +         lp_build_nearest_mip_level(bld, texture_index, *lod_ipart,
> ilevel0);
>        }
>        else {
>           first_level =
>           bld->dynamic_state->first_level(bld->dynamic_state,
> -                                                       bld->gallivm,
> unit);
> +                                                       bld->gallivm,
> texture_index);
>           first_level = lp_build_broadcast_scalar(&bld->perquadi_bld,
>           first_level);
>           *ilevel0 = first_level;
>        }
>        break;
>     case PIPE_TEX_MIPFILTER_NEAREST:
>        assert(*lod_ipart);
> -      lp_build_nearest_mip_level(bld, unit, *lod_ipart, ilevel0);
> +      lp_build_nearest_mip_level(bld, texture_index, *lod_ipart,
> ilevel0);
>        break;
>     case PIPE_TEX_MIPFILTER_LINEAR:
>        assert(*lod_ipart);
>        assert(*lod_fpart);
> -      lp_build_linear_mip_levels(bld, unit,
> +      lp_build_linear_mip_levels(bld, texture_index,
>                                   *lod_ipart, lod_fpart,
>                                   ilevel0, ilevel1);
>        break;
> @@ -1127,9 +1128,9 @@ lp_build_sample_general(struct
> lp_build_sample_context *bld,
>  {
>     struct lp_build_context *int_bld = &bld->int_bld;
>     LLVMBuilderRef builder = bld->gallivm->builder;
> -   const unsigned mip_filter = bld->static_state->min_mip_filter;
> -   const unsigned min_filter = bld->static_state->min_img_filter;
> -   const unsigned mag_filter = bld->static_state->mag_img_filter;
> +   const unsigned mip_filter =
> bld->static_sampler_state->min_mip_filter;
> +   const unsigned min_filter =
> bld->static_sampler_state->min_img_filter;
> +   const unsigned mag_filter =
> bld->static_sampler_state->mag_img_filter;
>     LLVMValueRef texels[4];
>     unsigned chan;
>  
> @@ -1221,7 +1222,7 @@ lp_build_fetch_texel(struct
> lp_build_sample_context *bld,
>     struct lp_build_context *perquadi_bld = &bld->perquadi_bld;
>     struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
>     unsigned dims = bld->dims, chan;
> -   unsigned target = bld->static_state->target;
> +   unsigned target = bld->static_texture_state->target;
>     LLVMValueRef size, ilevel;
>     LLVMValueRef row_stride_vec = NULL, img_stride_vec = NULL;
>     LLVMValueRef x = coords[0], y = coords[1], z = coords[2];
> @@ -1229,7 +1230,7 @@ lp_build_fetch_texel(struct
> lp_build_sample_context *bld,
>     LLVMValueRef offset, out_of_bounds, out1;
>  
>     /* XXX just like ordinary sampling, we don't handle per-pixel lod
>     (yet). */
> -   if (explicit_lod && bld->static_state->target != PIPE_BUFFER) {
> +   if (explicit_lod && bld->static_texture_state->target !=
> PIPE_BUFFER) {
>        ilevel = lp_build_pack_aos_scalars(bld->gallivm,
>        int_coord_bld->type,
>                                           perquadi_bld->type,
>                                           explicit_lod, 0);
>        lp_build_nearest_mip_level(bld, unit, ilevel, &ilevel);
> @@ -1288,7 +1289,7 @@ lp_build_fetch_texel(struct
> lp_build_sample_context *bld,
>                            x, y, z, row_stride_vec, img_stride_vec,
>                            &offset, &i, &j);
>  
> -   if (bld->static_state->target != PIPE_BUFFER) {
> +   if (bld->static_texture_state->target != PIPE_BUFFER) {
>        offset = lp_build_add(int_coord_bld, offset,
>                              lp_build_get_mip_offsets(bld, ilevel));
>     }
> @@ -1333,11 +1334,11 @@ lp_build_sample_compare(struct
> lp_build_sample_context *bld,
>     LLVMValueRef res, p;
>     const unsigned chan = 0;
>  
> -   if (bld->static_state->compare_mode == PIPE_TEX_COMPARE_NONE)
> +   if (bld->static_sampler_state->compare_mode ==
> PIPE_TEX_COMPARE_NONE)
>        return;
>  
> -   if (bld->static_state->target == PIPE_TEXTURE_2D_ARRAY ||
> -       bld->static_state->target == PIPE_TEXTURE_CUBE) {
> +   if (bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY ||
> +       bld->static_texture_state->target == PIPE_TEXTURE_CUBE) {
>        p = coords[3];
>     }
>     else {
> @@ -1359,7 +1360,7 @@ lp_build_sample_compare(struct
> lp_build_sample_context *bld,
>                        bld->coord_bld.one);
>  
>     /* result = (p FUNC texel) ? 1 : 0 */
> -   res = lp_build_cmp(texel_bld, bld->static_state->compare_func,
> +   res = lp_build_cmp(texel_bld,
> bld->static_sampler_state->compare_func,
>                        p, texel[chan]);
>     res = lp_build_select(texel_bld, res, texel_bld->one,
>     texel_bld->zero);
>  
> @@ -1400,11 +1401,13 @@ lp_build_sample_nop(struct gallivm_state
> *gallivm,
>   */
>  void
>  lp_build_sample_soa(struct gallivm_state *gallivm,
> -                    const struct lp_sampler_static_state
> *static_state,
> +                    const struct lp_static_texture_state
> *static_texture_state,
> +                    const struct lp_static_sampler_state
> *static_sampler_state,
>                      struct lp_sampler_dynamic_state *dynamic_state,
>                      struct lp_type type,
>                      boolean is_fetch,
> -                    unsigned unit,
> +                    unsigned texture_index,
> +                    unsigned sampler_index,
>                      const LLVMValueRef *coords,
>                      const LLVMValueRef *offsets,
>                      const struct lp_derivatives *derivs,
> @@ -1412,10 +1415,11 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>                      LLVMValueRef explicit_lod, /* optional */
>                      LLVMValueRef texel_out[4])
>  {
> -   unsigned dims = texture_dims(static_state->target);
> +   unsigned dims = texture_dims(static_texture_state->target);
>     unsigned num_quads = type.length / 4;
> -   unsigned mip_filter = static_state->min_mip_filter;
> +   unsigned mip_filter;
>     struct lp_build_sample_context bld;
> +   struct lp_static_sampler_state derived_sampler_state =
> *static_sampler_state;
>     LLVMTypeRef i32t = LLVMInt32TypeInContext(gallivm->context);
>     LLVMBuilderRef builder = gallivm->builder;
>     LLVMValueRef tex_width, tex_height, tex_depth;
> @@ -1424,7 +1428,7 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>     LLVMValueRef r;
>  
>     if (0) {
> -      enum pipe_format fmt = static_state->format;
> +      enum pipe_format fmt = static_texture_state->format;
>        debug_printf("Sample from %s\n", util_format_name(fmt));
>     }
>  
> @@ -1433,9 +1437,10 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>     /* Setup our build context */
>     memset(&bld, 0, sizeof bld);
>     bld.gallivm = gallivm;
> -   bld.static_state = static_state;
> +   bld.static_sampler_state = &derived_sampler_state;
> +   bld.static_texture_state = static_texture_state;
>     bld.dynamic_state = dynamic_state;
> -   bld.format_desc = util_format_description(static_state->format);
> +   bld.format_desc =
> util_format_description(static_texture_state->format);
>     bld.dims = dims;
>  
>     bld.vector_width = lp_type_width(type);
> @@ -1466,11 +1471,22 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>        }
>     }
>  
> +   if (!static_texture_state->level_zero_only) {
> +      derived_sampler_state.min_mip_filter =
> static_sampler_state->min_mip_filter;
> +   } else {
> +      derived_sampler_state.min_mip_filter =
> PIPE_TEX_MIPFILTER_NONE;
> +   }
> +   mip_filter = derived_sampler_state.min_mip_filter;
> +
> +   if (0) {
> +      debug_printf("  .min_mip_filter = %u\n",
> derived_sampler_state.min_mip_filter);
> +   }
> +
>     /*
>      * There are other situations where at least the multiple int
>      lods could be
>      * avoided like min and max lod being equal.
>      */
> -   if ((is_fetch && explicit_lod && bld.static_state->target !=
> PIPE_BUFFER) ||
> +   if ((is_fetch && explicit_lod && bld.static_texture_state->target
> != PIPE_BUFFER) ||
>         (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)) {
>        bld.num_lods = num_quads;
>     }
> @@ -1497,13 +1513,13 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>     lp_build_context_init(&bld.perquadi_bld, gallivm,
>     bld.perquadi_type);
>  
>     /* Get the dynamic state */
> -   tex_width = dynamic_state->width(dynamic_state, gallivm, unit);
> -   tex_height = dynamic_state->height(dynamic_state, gallivm, unit);
> -   tex_depth = dynamic_state->depth(dynamic_state, gallivm, unit);
> -   bld.row_stride_array = dynamic_state->row_stride(dynamic_state,
> gallivm, unit);
> -   bld.img_stride_array = dynamic_state->img_stride(dynamic_state,
> gallivm, unit);
> -   bld.base_ptr = dynamic_state->base_ptr(dynamic_state, gallivm,
> unit);
> -   bld.mip_offsets = dynamic_state->mip_offsets(dynamic_state,
> gallivm, unit);
> +   tex_width = dynamic_state->width(dynamic_state, gallivm,
> texture_index);
> +   tex_height = dynamic_state->height(dynamic_state, gallivm,
> texture_index);
> +   tex_depth = dynamic_state->depth(dynamic_state, gallivm,
> texture_index);
> +   bld.row_stride_array = dynamic_state->row_stride(dynamic_state,
> gallivm, texture_index);
> +   bld.img_stride_array = dynamic_state->img_stride(dynamic_state,
> gallivm, texture_index);
> +   bld.base_ptr = dynamic_state->base_ptr(dynamic_state, gallivm,
> texture_index);
> +   bld.mip_offsets = dynamic_state->mip_offsets(dynamic_state,
> gallivm, texture_index);
>     /* Note that mip_offsets is an array[level] of offsets to texture
>     images */
>  
>     s = coords[0];
> @@ -1536,7 +1552,7 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>     }
>  
>     else if (is_fetch) {
> -      lp_build_fetch_texel(&bld, unit, coords,
> +      lp_build_fetch_texel(&bld, texture_index, coords,
>                             explicit_lod, offsets,
>                             texel_out);
>     }
> @@ -1545,22 +1561,22 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>        LLVMValueRef lod_ipart = NULL, lod_fpart = NULL;
>        LLVMValueRef ilevel0 = NULL, ilevel1 = NULL;
>        boolean use_aos = util_format_fits_8unorm(bld.format_desc) &&
> -                        lp_is_simple_wrap_mode(static_state->wrap_s)
> &&
> -
>                        lp_is_simple_wrap_mode(static_state->wrap_t);
> +
>                        lp_is_simple_wrap_mode(static_sampler_state->wrap_s)
> &&
> +
>                        lp_is_simple_wrap_mode(static_sampler_state->wrap_t);
>  
>        if ((gallivm_debug & GALLIVM_DEBUG_PERF) &&
>            !use_aos && util_format_fits_8unorm(bld.format_desc)) {
>           debug_printf("%s: using floating point linear filtering for
>           %s\n",
>                        __FUNCTION__, bld.format_desc->short_name);
>           debug_printf("  min_img %d  mag_img %d  mip %d  wraps %d
>            wrapt %d\n",
> -                      static_state->min_img_filter,
> -                      static_state->mag_img_filter,
> -                      static_state->min_mip_filter,
> -                      static_state->wrap_s,
> -                      static_state->wrap_t);
> +                      static_sampler_state->min_img_filter,
> +                      static_sampler_state->mag_img_filter,
> +                      static_sampler_state->min_mip_filter,
> +                      static_sampler_state->wrap_s,
> +                      static_sampler_state->wrap_t);
>        }
>  
> -      lp_build_sample_common(&bld, unit,
> +      lp_build_sample_common(&bld, texture_index, sampler_index,
>                               &s, &t, &r,
>                               derivs, lod_bias, explicit_lod,
>                               &lod_ipart, &lod_fpart,
> @@ -1586,7 +1602,7 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>           }
>           if (use_aos) {
>              /* do sampling/filtering with fixed pt arithmetic */
> -            lp_build_sample_aos(&bld, unit,
> +            lp_build_sample_aos(&bld, sampler_index,
>                                  s, t, r,
>                                  lod_ipart, lod_fpart,
>                                  ilevel0, ilevel1,
> @@ -1594,7 +1610,7 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>           }
>  
>           else {
> -            lp_build_sample_general(&bld, unit,
> +            lp_build_sample_general(&bld, sampler_index,
>                                      s, t, r,
>                                      lod_ipart, lod_fpart,
>                                      ilevel0, ilevel1,
> @@ -1614,7 +1630,8 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>           /* Setup our build context */
>           memset(&bld4, 0, sizeof bld4);
>           bld4.gallivm = bld.gallivm;
> -         bld4.static_state = bld.static_state;
> +         bld4.static_texture_state = bld.static_texture_state;
> +         bld4.static_sampler_state = bld.static_sampler_state;
>           bld4.dynamic_state = bld.dynamic_state;
>           bld4.format_desc = bld.format_desc;
>           bld4.dims = bld.dims;
> @@ -1675,7 +1692,7 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>  
>              if (use_aos) {
>                 /* do sampling/filtering with fixed pt arithmetic */
> -               lp_build_sample_aos(&bld4, unit,
> +               lp_build_sample_aos(&bld4, sampler_index,
>                                     s4, t4, r4,
>                                     lod_iparts, lod_fparts,
>                                     ilevel0s, ilevel1s,
> @@ -1683,7 +1700,7 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>              }
>  
>              else {
> -               lp_build_sample_general(&bld4, unit,
> +               lp_build_sample_general(&bld4, sampler_index,
>                                         s4, t4, r4,
>                                         lod_iparts, lod_fparts,
>                                         ilevel0s, ilevel1s,
> @@ -1702,7 +1719,7 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>        lp_build_sample_compare(&bld, coords, texel_out);
>     }
>  
> -   if (static_state->target != PIPE_BUFFER) {
> +   if (static_texture_state->target != PIPE_BUFFER) {
>        apply_sampler_swizzle(&bld, texel_out);
>     }
>  
> @@ -1721,7 +1738,7 @@ lp_build_sample_soa(struct gallivm_state
> *gallivm,
>  
>  void
>  lp_build_size_query_soa(struct gallivm_state *gallivm,
> -                        const struct lp_sampler_static_state
> *static_state,
> +                        const struct lp_static_texture_state
> *static_state,
>                          struct lp_sampler_dynamic_state
>                          *dynamic_state,
>                          struct lp_type int_type,
>                          unsigned unit,
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> index 16d2ed9..4898849 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> @@ -173,7 +173,8 @@ struct lp_build_sampler_soa
>                          struct gallivm_state *gallivm,
>                          struct lp_type type,
>                          boolean is_fetch,
> -                        unsigned unit,
> +                        unsigned texture_index,
> +                        unsigned sampler_index,
>                          const LLVMValueRef *coords,
>                          const LLVMValueRef *offsets,
>                          const struct lp_derivatives *derivs,
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> index fbeb805..0621fb4 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -1331,7 +1331,8 @@ emit_tex( struct lp_build_tgsi_soa_context
> *bld,
>                                    bld->bld_base.base.gallivm,
>                                    bld->bld_base.base.type,
>                                    FALSE,
> -                                  unit, coords,
> +                                  unit, unit,
> +                                  coords,
>                                    offsets,
>                                    &derivs,
>                                    lod_bias, explicit_lod,
> @@ -1417,7 +1418,8 @@ emit_txf( struct lp_build_tgsi_soa_context
> *bld,
>                                    bld->bld_base.base.gallivm,
>                                    bld->bld_base.base.type,
>                                    TRUE,
> -                                  unit, coords,
> +                                  unit, unit,
> +                                  coords,
>                                    offsets,
>                                    &derivs,
>                                    NULL, explicit_lod,
> diff --git a/src/gallium/drivers/llvmpipe/lp_context.h
> b/src/gallium/drivers/llvmpipe/lp_context.h
> index b11a3d8..9ccb67b 100644
> --- a/src/gallium/drivers/llvmpipe/lp_context.h
> +++ b/src/gallium/drivers/llvmpipe/lp_context.h
> @@ -76,12 +76,12 @@ struct llvmpipe_context {
>     struct pipe_framebuffer_state framebuffer;
>     struct pipe_poly_stipple poly_stipple;
>     struct pipe_scissor_state scissor;
> -   struct pipe_sampler_view
> *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
> +   struct pipe_sampler_view
> *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
>  
>     struct pipe_viewport_state viewport;
>     struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
>     struct pipe_index_buffer index_buffer;
> -   struct pipe_resource *mapped_vs_tex[PIPE_MAX_SAMPLERS];
> +   struct pipe_resource
> *mapped_vs_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
>  
>     unsigned num_samplers[PIPE_SHADER_TYPES];
>     unsigned num_sampler_views[PIPE_SHADER_TYPES];
> diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c
> b/src/gallium/drivers/llvmpipe/lp_jit.c
> index ea7c805..d0a7916 100644
> --- a/src/gallium/drivers/llvmpipe/lp_jit.c
> +++ b/src/gallium/drivers/llvmpipe/lp_jit.c
> @@ -45,7 +45,7 @@ lp_jit_create_types(struct
> lp_fragment_shader_variant *lp)
>  {
>     struct gallivm_state *gallivm = lp->gallivm;
>     LLVMContextRef lc = gallivm->context;
> -   LLVMTypeRef texture_type;
> +   LLVMTypeRef texture_type, sampler_type;
>  
>     /* struct lp_jit_texture */
>     {
> @@ -61,11 +61,6 @@ lp_jit_create_types(struct
> lp_fragment_shader_variant *lp)
>        elem_types[LP_JIT_TEXTURE_IMG_STRIDE] =
>        elem_types[LP_JIT_TEXTURE_MIP_OFFSETS] =
>           LLVMArrayType(LLVMInt32TypeInContext(lc),
>           LP_MAX_TEXTURE_LEVELS);
> -      elem_types[LP_JIT_TEXTURE_MIN_LOD] =
> -      elem_types[LP_JIT_TEXTURE_MAX_LOD] =
> -      elem_types[LP_JIT_TEXTURE_LOD_BIAS] =
> LLVMFloatTypeInContext(lc);
> -      elem_types[LP_JIT_TEXTURE_BORDER_COLOR] =
> -         LLVMArrayType(LLVMFloatTypeInContext(lc), 4);
>  
>        texture_type = LLVMStructTypeInContext(lc, elem_types,
>                                               Elements(elem_types),
>                                               0);
> @@ -102,21 +97,41 @@ lp_jit_create_types(struct
> lp_fragment_shader_variant *lp)
>        LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, mip_offsets,
>                               gallivm->target, texture_type,
>                               LP_JIT_TEXTURE_MIP_OFFSETS);
> -      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, min_lod,
> +      LP_CHECK_STRUCT_SIZE(struct lp_jit_texture,
> +                           gallivm->target, texture_type);
> +   }
> +
> +   {
> +   /* struct lp_jit_sampler */
> +      LLVMTypeRef elem_types[LP_JIT_SAMPLER_NUM_FIELDS];
> +      elem_types[LP_JIT_SAMPLER_MIN_LOD] =
> +      elem_types[LP_JIT_SAMPLER_MAX_LOD] =
> +      elem_types[LP_JIT_SAMPLER_LOD_BIAS] =
> LLVMFloatTypeInContext(lc);
> +      elem_types[LP_JIT_SAMPLER_BORDER_COLOR] =
> +         LLVMArrayType(LLVMFloatTypeInContext(lc), 4);
> +
> +      sampler_type = LLVMStructTypeInContext(lc, elem_types,
> +                                             Elements(elem_types),
> 0);
> +#if HAVE_LLVM < 0x0300
> +      LLVMAddTypeName(gallivm->module, "texture", texture_type);
> +
> +      LLVMInvalidateStructLayout(gallivm->target, texture_type);
> +#endif
> +
> +      LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, min_lod,
>                               gallivm->target, texture_type,
> -                             LP_JIT_TEXTURE_MIN_LOD);
> -      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, max_lod,
> +                             LP_JIT_SAMPLER_MIN_LOD);
> +      LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, max_lod,
>                               gallivm->target, texture_type,
> -                             LP_JIT_TEXTURE_MAX_LOD);
> -      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, lod_bias,
> +                             LP_JIT_SAMPLER_MAX_LOD);
> +      LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, lod_bias,
>                               gallivm->target, texture_type,
> -                             LP_JIT_TEXTURE_LOD_BIAS);
> -      LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, border_color,
> +                             LP_JIT_SAMPLER_LOD_BIAS);
> +      LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, border_color,
>                               gallivm->target, texture_type,
> -                             LP_JIT_TEXTURE_BORDER_COLOR);
> -
> -      LP_CHECK_STRUCT_SIZE(struct lp_jit_texture,
> -                           gallivm->target, texture_type);
> +                             LP_JIT_SAMPLER_BORDER_COLOR);
> +      LP_CHECK_STRUCT_SIZE(struct lp_jit_sampler,
> +                           gallivm->target, sampler_type);
>     }
>  
>     /* struct lp_jit_context */
> @@ -132,6 +147,8 @@ lp_jit_create_types(struct
> lp_fragment_shader_variant *lp)
>        elem_types[LP_JIT_CTX_U8_BLEND_COLOR] =
>        LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
>        elem_types[LP_JIT_CTX_F_BLEND_COLOR] =
>        LLVMPointerType(LLVMFloatTypeInContext(lc), 0);
>        elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type,
> +
>                                                      PIPE_MAX_SHADER_SAMPLER_VIEWS);
> +      elem_types[LP_JIT_CTX_SAMPLERS] = LLVMArrayType(sampler_type,
>                                                        PIPE_MAX_SAMPLERS);
>  
>        context_type = LLVMStructTypeInContext(lc, elem_types,
> @@ -164,6 +181,9 @@ lp_jit_create_types(struct
> lp_fragment_shader_variant *lp)
>        LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
>                               gallivm->target, context_type,
>                               LP_JIT_CTX_TEXTURES);
> +      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, samplers,
> +                             gallivm->target, context_type,
> +                             LP_JIT_CTX_SAMPLERS);
>        LP_CHECK_STRUCT_SIZE(struct lp_jit_context,
>                             gallivm->target, context_type);
>  
> diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h
> b/src/gallium/drivers/llvmpipe/lp_jit.h
> index 5dc5bc4..3057c0d 100644
> --- a/src/gallium/drivers/llvmpipe/lp_jit.h
> +++ b/src/gallium/drivers/llvmpipe/lp_jit.h
> @@ -58,7 +58,11 @@ struct lp_jit_texture
>     uint32_t row_stride[LP_MAX_TEXTURE_LEVELS];
>     uint32_t img_stride[LP_MAX_TEXTURE_LEVELS];
>     uint32_t mip_offsets[LP_MAX_TEXTURE_LEVELS];
> -   /* sampler state, actually */
> +};
> +
> +
> +struct lp_jit_sampler
> +{
>     float min_lod;
>     float max_lod;
>     float lod_bias;
> @@ -76,14 +80,18 @@ enum {
>     LP_JIT_TEXTURE_ROW_STRIDE,
>     LP_JIT_TEXTURE_IMG_STRIDE,
>     LP_JIT_TEXTURE_MIP_OFFSETS,
> -   LP_JIT_TEXTURE_MIN_LOD,
> -   LP_JIT_TEXTURE_MAX_LOD,
> -   LP_JIT_TEXTURE_LOD_BIAS,
> -   LP_JIT_TEXTURE_BORDER_COLOR,
>     LP_JIT_TEXTURE_NUM_FIELDS  /* number of fields above */
>  };
>  
>  
> +enum {
> +   LP_JIT_SAMPLER_MIN_LOD,
> +   LP_JIT_SAMPLER_MAX_LOD,
> +   LP_JIT_SAMPLER_LOD_BIAS,
> +   LP_JIT_SAMPLER_BORDER_COLOR,
> +   LP_JIT_SAMPLER_NUM_FIELDS  /* number of fields above */
> +};
> +
>  
>  /**
>   * This structure is passed directly to the generated fragment
>   shader.
> @@ -107,7 +115,8 @@ struct lp_jit_context
>     uint8_t *u8_blend_color;
>     float *f_blend_color;
>  
> -   struct lp_jit_texture textures[PIPE_MAX_SAMPLERS];
> +   struct lp_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
> +   struct lp_jit_sampler samplers[PIPE_MAX_SAMPLERS];
>  };
>  
>  
> @@ -123,6 +132,7 @@ enum {
>     LP_JIT_CTX_U8_BLEND_COLOR,
>     LP_JIT_CTX_F_BLEND_COLOR,
>     LP_JIT_CTX_TEXTURES,
> +   LP_JIT_CTX_SAMPLERS,
>     LP_JIT_CTX_COUNT
>  };
>  
> @@ -148,6 +158,8 @@ enum {
>  #define lp_jit_context_textures(_gallivm, _ptr) \
>     lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_TEXTURES,
>     "textures")
>  
> +#define lp_jit_context_samplers(_gallivm, _ptr) \
> +   lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_SAMPLERS,
> "samplers")
>  
>  
>  /**
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c
> b/src/gallium/drivers/llvmpipe/lp_setup.c
> index ffa0fe6..b0bc4a8 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup.c
> @@ -668,9 +668,9 @@ lp_setup_set_fragment_sampler_views(struct
> lp_setup_context *setup,
>  
>     LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
>  
> -   assert(num <= PIPE_MAX_SAMPLERS);
> +   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
>  
> -   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
> +   for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
>        struct pipe_sampler_view *view = i < num ? views[i] : NULL;
>  
>        if (view) {
> @@ -780,13 +780,13 @@ lp_setup_set_fragment_sampler_state(struct
> lp_setup_context *setup,
>        const struct pipe_sampler_state *sampler = i < num ?
>        samplers[i] : NULL;
>  
>        if (sampler) {
> -         struct lp_jit_texture *jit_tex;
> -         jit_tex = &setup->fs.current.jit_context.textures[i];
> +         struct lp_jit_sampler *jit_sam;
> +         jit_sam = &setup->fs.current.jit_context.samplers[i];
>  
> -         jit_tex->min_lod = sampler->min_lod;
> -         jit_tex->max_lod = sampler->max_lod;
> -         jit_tex->lod_bias = sampler->lod_bias;
> -         COPY_4V(jit_tex->border_color, sampler->border_color.f);
> +         jit_sam->min_lod = sampler->min_lod;
> +         jit_sam->max_lod = sampler->max_lod;
> +         jit_sam->lod_bias = sampler->lod_bias;
> +         COPY_4V(jit_sam->border_color, sampler->border_color.f);
>        }
>     }
>  
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h
> b/src/gallium/drivers/llvmpipe/lp_setup_context.h
> index 4d20dd3..0e2de64 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
> +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
> @@ -123,7 +123,7 @@ struct lp_setup_context
>     struct {
>        const struct lp_rast_state *stored; /**< what's in the scene
>        */
>        struct lp_rast_state current;  /**< currently set state */
> -      struct pipe_resource *current_tex[PIPE_MAX_SAMPLERS];
> +      struct pipe_resource
> *current_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
>     } fs;
>  
>     /** fragment shader constants */
> diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c
> b/src/gallium/drivers/llvmpipe/lp_state_fs.c
> index cf936d0..09f37e0 100644
> --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
> +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
> @@ -1904,7 +1904,7 @@ generate_fragment(struct llvmpipe_context *lp,
>     LLVMPositionBuilderAtEnd(builder, block);
>  
>     /* code generated texture sampling */
> -   sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr);
> +   sampler = lp_llvm_sampler_soa_create(key->state, context_ptr);
>  
>     zs_format_desc = util_format_description(key->zsbuf_format);
>  
> @@ -2113,32 +2113,39 @@ dump_fs_variant_key(const struct
> lp_fragment_shader_variant_key *key)
>     }
>     debug_printf("blend.colormask = 0x%x\n",
>     key->blend.rt[0].colormask);
>     for (i = 0; i < key->nr_samplers; ++i) {
> +      const struct lp_static_sampler_state *sampler =
> &key->state[i].sampler_state;
>        debug_printf("sampler[%u] = \n", i);
> -      debug_printf("  .format = %s\n",
> -                   util_format_name(key->sampler[i].format));
> -      debug_printf("  .target = %s\n",
> -                   util_dump_tex_target(key->sampler[i].target,
> TRUE));
> -      debug_printf("  .pot = %u %u %u\n",
> -                   key->sampler[i].pot_width,
> -                   key->sampler[i].pot_height,
> -                   key->sampler[i].pot_depth);
>        debug_printf("  .wrap = %s %s %s\n",
> -                   util_dump_tex_wrap(key->sampler[i].wrap_s, TRUE),
> -                   util_dump_tex_wrap(key->sampler[i].wrap_t, TRUE),
> -                   util_dump_tex_wrap(key->sampler[i].wrap_r,
> TRUE));
> +                   util_dump_tex_wrap(sampler->wrap_s, TRUE),
> +                   util_dump_tex_wrap(sampler->wrap_t, TRUE),
> +                   util_dump_tex_wrap(sampler->wrap_r, TRUE));
>        debug_printf("  .min_img_filter = %s\n",
> -
>                   util_dump_tex_filter(key->sampler[i].min_img_filter,
> TRUE));
> +                   util_dump_tex_filter(sampler->min_img_filter,
> TRUE));
>        debug_printf("  .min_mip_filter = %s\n",
> -
>                   util_dump_tex_mipfilter(key->sampler[i].min_mip_filter,
> TRUE));
> +                   util_dump_tex_mipfilter(sampler->min_mip_filter,
> TRUE));
>        debug_printf("  .mag_img_filter = %s\n",
> -
>                   util_dump_tex_filter(key->sampler[i].mag_img_filter,
> TRUE));
> -      if (key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE)
> -         debug_printf("  .compare_func = %s\n",
> util_dump_func(key->sampler[i].compare_func, TRUE));
> -      debug_printf("  .normalized_coords = %u\n",
> key->sampler[i].normalized_coords);
> -      debug_printf("  .min_max_lod_equal = %u\n",
> key->sampler[i].min_max_lod_equal);
> -      debug_printf("  .lod_bias_non_zero = %u\n",
> key->sampler[i].lod_bias_non_zero);
> -      debug_printf("  .apply_min_lod = %u\n",
> key->sampler[i].apply_min_lod);
> -      debug_printf("  .apply_max_lod = %u\n",
> key->sampler[i].apply_max_lod);
> +                   util_dump_tex_filter(sampler->mag_img_filter,
> TRUE));
> +      if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE)
> +         debug_printf("  .compare_func = %s\n",
> util_dump_func(sampler->compare_func, TRUE));
> +      debug_printf("  .normalized_coords = %u\n",
> sampler->normalized_coords);
> +      debug_printf("  .min_max_lod_equal = %u\n",
> sampler->min_max_lod_equal);
> +      debug_printf("  .lod_bias_non_zero = %u\n",
> sampler->lod_bias_non_zero);
> +      debug_printf("  .apply_min_lod = %u\n",
> sampler->apply_min_lod);
> +      debug_printf("  .apply_max_lod = %u\n",
> sampler->apply_max_lod);
> +   }
> +   for (i = 0; i < key->nr_sampler_views; ++i) {
> +      const struct lp_static_texture_state *texture =
> &key->state[i].texture_state;
> +      debug_printf("texture[%u] = \n", i);
> +      debug_printf("  .format = %s\n",
> +                   util_format_name(texture->format));
> +      debug_printf("  .target = %s\n",
> +                   util_dump_tex_target(texture->target, TRUE));
> +      debug_printf("  .level_zero_only = %u\n",
> +                   texture->level_zero_only);
> +      debug_printf("  .pot = %u %u %u\n",
> +                   texture->pot_width,
> +                   texture->pot_height,
> +                   texture->pot_depth);
>     }
>  }
>  
> @@ -2251,6 +2258,7 @@ llvmpipe_create_fs_state(struct pipe_context
> *pipe,
>     struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
>     struct lp_fragment_shader *shader;
>     int nr_samplers;
> +   int nr_sampler_views;
>     int i;
>  
>     shader = CALLOC_STRUCT(lp_fragment_shader);
> @@ -2274,9 +2282,10 @@ llvmpipe_create_fs_state(struct pipe_context
> *pipe,
>     }
>  
>     nr_samplers = shader->info.base.file_max[TGSI_FILE_SAMPLER] + 1;
> +   nr_sampler_views =
> shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
>  
>     shader->variant_key_size = Offset(struct
>     lp_fragment_shader_variant_key,
> -				     sampler[nr_samplers]);
> +                                     state[MAX2(nr_samplers,
> nr_sampler_views)]);
>  
>     for (i = 0; i < shader->info.base.num_inputs; i++) {
>        shader->inputs[i].usage_mask =
>        shader->info.base.input_usage_mask[i];
> @@ -2605,9 +2614,32 @@ make_variant_key(struct llvmpipe_context *lp,
>  
>     for(i = 0; i < key->nr_samplers; ++i) {
>        if(shader->info.base.file_mask[TGSI_FILE_SAMPLER] & (1 << i))
>        {
> -         lp_sampler_static_state(&key->sampler[i],
> -				 lp->sampler_views[PIPE_SHADER_FRAGMENT][i],
> -				 lp->samplers[PIPE_SHADER_FRAGMENT][i]);
> +
>         lp_sampler_static_sampler_state(&key->state[i].sampler_state,
> +
>                                         lp->samplers[PIPE_SHADER_FRAGMENT][i]);
> +      }
> +   }
> +
> +   /*
> +    * XXX If TGSI_FILE_SAMPLER_VIEW exists assume all texture
> opcodes
> +    * are dx10-style? Can't really have mixed opcodes, at least not
> +    * if we want to skip the holes here (without rescanning tgsi).
> +    */
> +   if (shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] != -1) {
> +      key->nr_sampler_views =
> shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
> +      for(i = 0; i < key->nr_sampler_views; ++i) {
> +         if(shader->info.base.file_mask[TGSI_FILE_SAMPLER_VIEW] & (1
> << i)) {
> +
>            lp_sampler_static_texture_state(&key->state[i].texture_state,
> +
>                                            lp->sampler_views[PIPE_SHADER_FRAGMENT][i]);
> +         }
> +      }
> +   }
> +   else {
> +      key->nr_sampler_views = key->nr_samplers;
> +      for(i = 0; i < key->nr_sampler_views; ++i) {
> +         if(shader->info.base.file_mask[TGSI_FILE_SAMPLER] & (1 <<
> i)) {
> +
>            lp_sampler_static_texture_state(&key->state[i].texture_state,
> +
>                                            lp->sampler_views[PIPE_SHADER_FRAGMENT][i]);
> +         }
>        }
>     }
>  }
> diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h
> b/src/gallium/drivers/llvmpipe/lp_state_fs.h
> index 306f5f9..dbe657c 100644
> --- a/src/gallium/drivers/llvmpipe/lp_state_fs.h
> +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h
> @@ -46,6 +46,18 @@ struct lp_fragment_shader;
>  #define RAST_WHOLE 0
>  #define RAST_EDGE_TEST 1
>  
> +struct lp_sampler_static_state
> +{
> +   /*
> +    * These attributes are effectively interleaved for more sane key
> handling.
> +    * However, there might be lots of null space if the amount of
> samplers and
> +    * textures isn't the same.
> +    */
> +   struct lp_static_sampler_state sampler_state;
> +   struct lp_static_texture_state texture_state;
> +};
> +
> +
>  
>  struct lp_fragment_shader_variant_key
>  {
> @@ -59,14 +71,15 @@ struct lp_fragment_shader_variant_key
>     } alpha;
>  
>     unsigned nr_cbufs:8;
> -   unsigned nr_samplers:8;	/* actually derivable from just the
> shader */
> +   unsigned nr_samplers:8;      /* actually derivable from just the
> shader */
> +   unsigned nr_sampler_views:8; /* actually derivable from just the
> shader */
>     unsigned flatshade:1;
>     unsigned occlusion_count:1;
>  
>     enum pipe_format zsbuf_format;
>     enum pipe_format cbuf_format[PIPE_MAX_COLOR_BUFS];
>  
> -   struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS];
> +   struct lp_sampler_static_state
> state[PIPE_MAX_SHADER_SAMPLER_VIEWS];
>  };
>  
>  
> diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c
> b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
> index e7429cc..9736ca9 100644
> --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c
> +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
> @@ -143,7 +143,7 @@ llvmpipe_set_sampler_views(struct pipe_context
> *pipe,
>     struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
>     uint i;
>  
> -   assert(num <= PIPE_MAX_SAMPLERS);
> +   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
>  
>     assert(shader < PIPE_SHADER_TYPES);
>     assert(start + num <= Elements(llvmpipe->sampler_views[shader]));
> @@ -258,11 +258,11 @@ llvmpipe_prepare_vertex_sampling(struct
> llvmpipe_context *lp,
>     uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
>     const void *addr;
>  
> -   assert(num <= PIPE_MAX_SAMPLERS);
> +   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
>     if (!num)
>        return;
>  
> -   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
> +   for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
>        struct pipe_sampler_view *view = i < num ? views[i] : NULL;
>  
>        if (view) {
> diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c
> b/src/gallium/drivers/llvmpipe/lp_state_setup.c
> index f44eed4..9dd337a 100644
> --- a/src/gallium/drivers/llvmpipe/lp_state_setup.c
> +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c
> @@ -795,19 +795,19 @@ fail:
>  
>  static void
>  lp_make_setup_variant_key(struct llvmpipe_context *lp,
> -			  struct lp_setup_variant_key *key)
> +                          struct lp_setup_variant_key *key)
>  {
>     struct lp_fragment_shader *fs = lp->fs;
>     unsigned i;
>  
>     assert(sizeof key->inputs[0] == sizeof(uint));
> -
> +
>     key->num_inputs = fs->info.base.num_inputs;
>     key->flatshade_first = lp->rasterizer->flatshade_first;
>     key->pixel_center_half = lp->rasterizer->gl_rasterization_rules;
>     key->twoside = lp->rasterizer->light_twoside;
>     key->size = Offset(struct lp_setup_variant_key,
> -		      inputs[key->num_inputs]);
> +                      inputs[key->num_inputs]);
>  
>     key->color_slot  = lp->color_slot [0];
>     key->bcolor_slot = lp->bcolor_slot[0];
> @@ -825,9 +825,9 @@ lp_make_setup_variant_key(struct llvmpipe_context
> *lp,
>     for (i = 0; i < key->num_inputs; i++) {
>        if (key->inputs[i].interp == LP_INTERP_COLOR) {
>           if (lp->rasterizer->flatshade)
> -	    key->inputs[i].interp = LP_INTERP_CONSTANT;
> -	 else
> -	    key->inputs[i].interp = LP_INTERP_PERSPECTIVE;
> +            key->inputs[i].interp = LP_INTERP_CONSTANT;
> +         else
> +            key->inputs[i].interp = LP_INTERP_PERSPECTIVE;
>        }
>     }
>  
> @@ -836,11 +836,11 @@ lp_make_setup_variant_key(struct
> llvmpipe_context *lp,
>  
>  static void
>  remove_setup_variant(struct llvmpipe_context *lp,
> -		     struct lp_setup_variant *variant)
> +                     struct lp_setup_variant *variant)
>  {
>     if (gallivm_debug & GALLIVM_DEBUG_IR) {
>        debug_printf("llvmpipe: del setup_variant #%u total %u\n",
> -		   variant->no, lp->nr_setup_variants);
> +                   variant->no, lp->nr_setup_variants);
>     }
>  
>     if (variant->function) {
> diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c
> b/src/gallium/drivers/llvmpipe/lp_tex_sample.c
> index 0bd5c4a..25125a0 100644
> --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c
> +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c
> @@ -49,6 +49,7 @@
>  #include "gallivm/lp_bld_tgsi.h"
>  #include "lp_jit.h"
>  #include "lp_tex_sample.h"
> +#include "lp_state_fs.h"
>  #include "lp_debug.h"
>  
>  
> @@ -103,7 +104,7 @@ lp_llvm_texture_member(const struct
> lp_sampler_dynamic_state *base,
>     LLVMValueRef ptr;
>     LLVMValueRef res;
>  
> -   assert(unit < PIPE_MAX_SAMPLERS);
> +   assert(unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
>  
>     /* context[0] */
>     indices[0] = lp_build_const_int32(gallivm, 0);
> @@ -155,10 +156,69 @@ LP_LLVM_TEXTURE_MEMBER(base_ptr,
>   LP_JIT_TEXTURE_BASE, TRUE)
>  LP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE)
>  LP_LLVM_TEXTURE_MEMBER(img_stride, LP_JIT_TEXTURE_IMG_STRIDE, FALSE)
>  LP_LLVM_TEXTURE_MEMBER(mip_offsets, LP_JIT_TEXTURE_MIP_OFFSETS,
>  FALSE)
> -LP_LLVM_TEXTURE_MEMBER(min_lod,    LP_JIT_TEXTURE_MIN_LOD, TRUE)
> -LP_LLVM_TEXTURE_MEMBER(max_lod,    LP_JIT_TEXTURE_MAX_LOD, TRUE)
> -LP_LLVM_TEXTURE_MEMBER(lod_bias,   LP_JIT_TEXTURE_LOD_BIAS, TRUE)
> -LP_LLVM_TEXTURE_MEMBER(border_color, LP_JIT_TEXTURE_BORDER_COLOR,
> FALSE)
> +
> +
> +/**
> + * Fetch the specified member of the lp_jit_sampler structure.
> + * \param emit_load  if TRUE, emit the LLVM load instruction to
> actually
> + *                   fetch the field's value.  Otherwise, just emit
> the
> + *                   GEP code to address the field.
> + *
> + * @sa http://llvm.org/docs/GetElementPtr.html
> + */
> +static LLVMValueRef
> +lp_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
> +                       struct gallivm_state *gallivm,
> +                       unsigned unit,
> +                       unsigned member_index,
> +                       const char *member_name,
> +                       boolean emit_load)
> +{
> +   struct llvmpipe_sampler_dynamic_state *state =
> +      (struct llvmpipe_sampler_dynamic_state *)base;
> +   LLVMBuilderRef builder = gallivm->builder;
> +   LLVMValueRef indices[4];
> +   LLVMValueRef ptr;
> +   LLVMValueRef res;
> +
> +   assert(unit < PIPE_MAX_SAMPLERS);
> +
> +   /* context[0] */
> +   indices[0] = lp_build_const_int32(gallivm, 0);
> +   /* context[0].samplers */
> +   indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_SAMPLERS);
> +   /* context[0].samplers[unit] */
> +   indices[2] = lp_build_const_int32(gallivm, unit);
> +   /* context[0].samplers[unit].member */
> +   indices[3] = lp_build_const_int32(gallivm, member_index);
> +
> +   ptr = LLVMBuildGEP(builder, state->context_ptr, indices,
> Elements(indices), "");
> +
> +   if (emit_load)
> +      res = LLVMBuildLoad(builder, ptr, "");
> +   else
> +      res = ptr;
> +
> +   lp_build_name(res, "context.sampler%u.%s", unit, member_name);
> +
> +   return res;
> +}
> +
> +
> +#define LP_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load)  \
> +   static LLVMValueRef \
> +   lp_llvm_sampler_##_name( const struct lp_sampler_dynamic_state
> *base, \
> +                            struct gallivm_state *gallivm, \
> +                            unsigned unit) \
> +   { \
> +      return lp_llvm_sampler_member(base, gallivm, unit, _index,
> #_name, _emit_load ); \
> +   }
> +
> +
> +LP_LLVM_SAMPLER_MEMBER(min_lod,    LP_JIT_SAMPLER_MIN_LOD, TRUE)
> +LP_LLVM_SAMPLER_MEMBER(max_lod,    LP_JIT_SAMPLER_MAX_LOD, TRUE)
> +LP_LLVM_SAMPLER_MEMBER(lod_bias,   LP_JIT_SAMPLER_LOD_BIAS, TRUE)
> +LP_LLVM_SAMPLER_MEMBER(border_color, LP_JIT_SAMPLER_BORDER_COLOR,
> FALSE)
>  
>  
>  static void
> @@ -177,7 +237,8 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct
> lp_build_sampler_soa *base,
>                                       struct gallivm_state *gallivm,
>                                       struct lp_type type,
>                                       boolean is_fetch,
> -                                     unsigned unit,
> +                                     unsigned texture_index,
> +                                     unsigned sampler_index,
>                                       const LLVMValueRef *coords,
>                                       const LLVMValueRef *offsets,
>                                       const struct lp_derivatives
>                                       *derivs,
> @@ -187,7 +248,8 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct
> lp_build_sampler_soa *base,
>  {
>     struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa
>     *)base;
>  
> -   assert(unit < PIPE_MAX_SAMPLERS);
> +   assert(sampler_index < PIPE_MAX_SAMPLERS);
> +   assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
>     
>     if (LP_PERF & PERF_NO_TEX) {
>        lp_build_sample_nop(gallivm, type, coords, texel);
> @@ -195,11 +257,13 @@ lp_llvm_sampler_soa_emit_fetch_texel(const
> struct lp_build_sampler_soa *base,
>     }
>  
>     lp_build_sample_soa(gallivm,
> -                       &sampler->dynamic_state.static_state[unit],
> +
>                       &sampler->dynamic_state.static_state[texture_index].texture_state,
> +
>                       &sampler->dynamic_state.static_state[sampler_index].sampler_state,
>                         &sampler->dynamic_state.base,
>                         type,
>                         is_fetch,
> -                       unit,
> +                       texture_index,
> +                       sampler_index,
>                         coords,
>                         offsets,
>                         derivs,
> @@ -221,14 +285,14 @@ lp_llvm_sampler_soa_emit_size_query(const
> struct lp_build_sampler_soa *base,
>     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,
> +
>                           &sampler->dynamic_state.static_state[unit].texture_state,
> +                           &sampler->dynamic_state.base,
>                             type,
> -			   unit,
> -			   explicit_lod,
> -			   sizes_out);
> +                           unit,
> +                           explicit_lod,
> +                           sizes_out);
>  }
>  
>  
> @@ -254,10 +318,10 @@ lp_llvm_sampler_soa_create(const struct
> lp_sampler_static_state *static_state,
>     sampler->dynamic_state.base.row_stride =
>     lp_llvm_texture_row_stride;
>     sampler->dynamic_state.base.img_stride =
>     lp_llvm_texture_img_stride;
>     sampler->dynamic_state.base.mip_offsets =
>     lp_llvm_texture_mip_offsets;
> -   sampler->dynamic_state.base.min_lod = lp_llvm_texture_min_lod;
> -   sampler->dynamic_state.base.max_lod = lp_llvm_texture_max_lod;
> -   sampler->dynamic_state.base.lod_bias = lp_llvm_texture_lod_bias;
> -   sampler->dynamic_state.base.border_color =
> lp_llvm_texture_border_color;
> +   sampler->dynamic_state.base.min_lod = lp_llvm_sampler_min_lod;
> +   sampler->dynamic_state.base.max_lod = lp_llvm_sampler_max_lod;
> +   sampler->dynamic_state.base.lod_bias = lp_llvm_sampler_lod_bias;
> +   sampler->dynamic_state.base.border_color =
> lp_llvm_sampler_border_color;
>  
>     sampler->dynamic_state.static_state = static_state;
>     sampler->dynamic_state.context_ptr = context_ptr;
> --
> 1.7.9.5
> 


More information about the mesa-dev mailing list