Merge branch 'lp-offset-twoside'
[mesa.git] / src / gallium / auxiliary / draw / draw_llvm.c
index 940b2d7ae557a336ccb96f7d78795fc5e3611bdc..2b5f01cda74c4091d77e0faf39eea1883e40578f 100644 (file)
@@ -46,7 +46,7 @@
 #include "tgsi/tgsi_exec.h"
 #include "tgsi/tgsi_dump.h"
 
-#include "util/u_cpu_detect.h"
+#include "util/u_math.h"
 #include "util/u_pointer.h"
 #include "util/u_string.h"
 
@@ -74,12 +74,12 @@ init_globals(struct draw_llvm *llvm)
       elem_types[DRAW_JIT_TEXTURE_DEPTH] = LLVMInt32Type();
       elem_types[DRAW_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type();
       elem_types[DRAW_JIT_TEXTURE_ROW_STRIDE] =
-         LLVMArrayType(LLVMInt32Type(), DRAW_MAX_TEXTURE_LEVELS);
+         LLVMArrayType(LLVMInt32Type(), PIPE_MAX_TEXTURE_LEVELS);
       elem_types[DRAW_JIT_TEXTURE_IMG_STRIDE] =
-         LLVMArrayType(LLVMInt32Type(), DRAW_MAX_TEXTURE_LEVELS);
+         LLVMArrayType(LLVMInt32Type(), PIPE_MAX_TEXTURE_LEVELS);
       elem_types[DRAW_JIT_TEXTURE_DATA] =
          LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0),
-                       DRAW_MAX_TEXTURE_LEVELS);
+                       PIPE_MAX_TEXTURE_LEVELS);
       elem_types[DRAW_JIT_TEXTURE_MIN_LOD] = LLVMFloatType();
       elem_types[DRAW_JIT_TEXTURE_MAX_LOD] = LLVMFloatType();
       elem_types[DRAW_JIT_TEXTURE_LOD_BIAS] = LLVMFloatType();
@@ -130,12 +130,14 @@ init_globals(struct draw_llvm *llvm)
 
    /* struct draw_jit_context */
    {
-      LLVMTypeRef elem_types[3];
+      LLVMTypeRef elem_types[5];
       LLVMTypeRef context_type;
 
       elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* vs_constants */
-      elem_types[1] = LLVMPointerType(LLVMFloatType(), 0); /* vs_constants */
-      elem_types[2] = LLVMArrayType(texture_type,
+      elem_types[1] = LLVMPointerType(LLVMFloatType(), 0); /* gs_constants */
+      elem_types[2] = LLVMPointerType(LLVMArrayType(LLVMArrayType(LLVMFloatType(), 4), 12), 0); /* planes */
+      elem_types[3] = LLVMPointerType(LLVMFloatType(), 0); /* viewport */
+      elem_types[4] = LLVMArrayType(texture_type,
                                     PIPE_MAX_VERTEX_SAMPLERS); /* textures */
 
       context_type = LLVMStructType(elem_types, Elements(elem_types), 0);
@@ -144,6 +146,8 @@ init_globals(struct draw_llvm *llvm)
                              llvm->target, context_type, 0);
       LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, gs_constants,
                              llvm->target, context_type, 1);
+      LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, planes,
+                             llvm->target, context_type, 2);
       LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, textures,
                              llvm->target, context_type,
                              DRAW_JIT_CTX_TEXTURES);
@@ -269,13 +273,7 @@ draw_llvm_create(struct draw_context *draw)
          LLVMAddConstantPropagationPass(llvm->pass);
       }
 
-      if(util_cpu_caps.has_sse4_1) {
-         /* FIXME: There is a bug in this pass, whereby the combination of fptosi
-          * and sitofp (necessary for trunc/floor/ceil/round implementation)
-          * somehow becomes invalid code.
-          */
-         LLVMAddInstructionCombiningPass(llvm->pass);
-      }
+      LLVMAddInstructionCombiningPass(llvm->pass);
       LLVMAddGVNPass(llvm->pass);
    } else {
       /* We need at least this pass to prevent the backends to fail in
@@ -423,7 +421,7 @@ generate_fetch(LLVMBuilderRef builder,
                             "instance_divisor");
    }
 
-   /* limit index to min(inex, vb_max_index) */
+   /* limit index to min(index, vb_max_index) */
    cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, "");
    index = LLVMBuildSelect(builder, cond, index, vb_max_index, "");
 
@@ -727,6 +725,7 @@ store_clip(LLVMBuilderRef builder,
    LLVMValueRef clip_ptr0, clip_ptr1, clip_ptr2, clip_ptr3;
    LLVMValueRef clip0_ptr, clip1_ptr, clip2_ptr, clip3_ptr;    
    LLVMValueRef out0elem, out1elem, out2elem, out3elem;
+   int i;
 
    LLVMValueRef ind0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
    LLVMValueRef ind1 = LLVMConstInt(LLVMInt32Type(), 1, 0);
@@ -751,7 +750,7 @@ store_clip(LLVMBuilderRef builder,
    clip_ptr2 = draw_jit_header_clip(builder, io2_ptr);
    clip_ptr3 = draw_jit_header_clip(builder, io3_ptr);
 
-   for (int i = 0; i<4; i++){
+   for (i = 0; i<4; i++){
       clip0_ptr = LLVMBuildGEP(builder, clip_ptr0,
                                indices, 2, ""); //x0
       clip1_ptr = LLVMBuildGEP(builder, clip_ptr1,
@@ -780,36 +779,66 @@ store_clip(LLVMBuilderRef builder,
 
 }
 
+/* Equivalent of _mm_set1_ps(a)
+ */
+static LLVMValueRef vec4f_from_scalar(LLVMBuilderRef bld,
+                                     LLVMValueRef a,
+                                     const char *name)
+{
+   LLVMValueRef res = LLVMGetUndef(LLVMVectorType(LLVMFloatType(), 4));
+   int i;
+
+   for(i = 0; i < 4; ++i) {
+      LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+      res = LLVMBuildInsertElement(bld, res, a, index, i == 3 ? name : "");
+   }
+
+   return res;
+}
+
 /*
  * Transforms the outputs for viewport mapping
  */
 static void
 generate_viewport(struct draw_llvm *llvm,
                   LLVMBuilderRef builder,
-                  LLVMValueRef (*outputs)[NUM_CHANNELS])
+                  LLVMValueRef (*outputs)[NUM_CHANNELS],
+                  LLVMValueRef context_ptr)
 {
    int i;
-   const float *scaleA = llvm->draw->viewport.scale;
-   const float *transA = llvm->draw->viewport.translate;
    struct lp_type f32_type = lp_type_float_vec(32);
    LLVMValueRef out3 = LLVMBuildLoad(builder, outputs[0][3], ""); /*w0 w1 w2 w3*/   
    LLVMValueRef const1 = lp_build_const_vec(f32_type, 1.0);       /*1.0 1.0 1.0 1.0*/ 
-   
+   LLVMValueRef vp_ptr = draw_jit_context_viewport(builder, context_ptr);
+
    /* for 1/w convention*/
    out3 = LLVMBuildFDiv(builder, const1, out3, "");
-
+   LLVMBuildStore(builder, out3, outputs[0][3]);
+  
    /* Viewport Mapping */
-   for (i=0; i<4; i++){
+   for (i=0; i<3; i++){
       LLVMValueRef out = LLVMBuildLoad(builder, outputs[0][i], ""); /*x0 x1 x2 x3*/
-      LLVMValueRef scale = lp_build_const_vec(f32_type, scaleA[i]); /*sx sx sx sx*/     
-      LLVMValueRef trans = lp_build_const_vec(f32_type, transA[i]); /*tx tx tx tx*/
+      LLVMValueRef scale;
+      LLVMValueRef trans;
+      LLVMValueRef scale_i;
+      LLVMValueRef trans_i;
+      LLVMValueRef index;
       
+      index = LLVMConstInt(LLVMInt32Type(), i, 0);
+      scale_i = LLVMBuildGEP(builder, vp_ptr, &index, 1, "");
+
+      index = LLVMConstInt(LLVMInt32Type(), i+4, 0);
+      trans_i = LLVMBuildGEP(builder, vp_ptr, &index, 1, "");
+
+      scale = vec4f_from_scalar(builder, LLVMBuildLoad(builder, scale_i, ""), "scale");
+      trans = vec4f_from_scalar(builder, LLVMBuildLoad(builder, trans_i, ""), "trans");
+
       /* divide by w */
-      out = LLVMBuildMul(builder, out, out3, "");
+      out = LLVMBuildFMul(builder, out, out3, "");
       /* mult by scale */
-      out = LLVMBuildMul(builder, out, scale, "");
+      out = LLVMBuildFMul(builder, out, scale, "");
       /* add translation */
-      out = LLVMBuildAdd(builder, out, trans, "");
+      out = LLVMBuildFAdd(builder, out, trans, "");
 
       /* store transformed outputs */
       LLVMBuildStore(builder, out, outputs[0][i]);
@@ -817,25 +846,35 @@ generate_viewport(struct draw_llvm *llvm,
    
 }
 
+
 /*
  * Returns clipmask as 4xi32 bitmask for the 4 vertices
  */
 static LLVMValueRef 
 generate_clipmask(LLVMBuilderRef builder,
                   LLVMValueRef (*outputs)[NUM_CHANNELS],
-                  boolean disable_zclipping,
-                  boolean enable_d3dclipping)
+                  boolean clip_xy,
+                  boolean clip_z,
+                  boolean clip_user,
+                  boolean clip_halfz,
+                  unsigned nr,
+                  LLVMValueRef context_ptr)
 {
    LLVMValueRef mask; /* stores the <4xi32> clipmasks */     
    LLVMValueRef test, temp; 
    LLVMValueRef zero, shift;
    LLVMValueRef pos_x, pos_y, pos_z, pos_w;
+   LLVMValueRef plane1, planes, plane_ptr, sum;
+
+   unsigned i;
 
    struct lp_type f32_type = lp_type_float_vec(32); 
 
+   mask = lp_build_const_int_vec(lp_type_int_vec(32), 0);
+   temp = lp_build_const_int_vec(lp_type_int_vec(32), 0);
    zero = lp_build_const_vec(f32_type, 0);                    /* 0.0f 0.0f 0.0f 0.0f */
    shift = lp_build_const_int_vec(lp_type_int_vec(32), 1);    /* 1 1 1 1 */
-  
+
    /* Assuming position stored at output[0] */
    pos_x = LLVMBuildLoad(builder, outputs[0][0], ""); /*x0 x1 x2 x3*/
    pos_y = LLVMBuildLoad(builder, outputs[0][1], ""); /*y0 y1 y2 y3*/
@@ -843,37 +882,39 @@ generate_clipmask(LLVMBuilderRef builder,
    pos_w = LLVMBuildLoad(builder, outputs[0][3], ""); /*w0 w1 w2 w3*/   
 
    /* Cliptest, for hardwired planes */
-   /* plane 1 */
-   test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, pos_x , pos_w);
-   temp = shift;
-   test = LLVMBuildAnd(builder, test, temp, ""); 
-   mask = test;
+   if (clip_xy){
+      /* plane 1 */
+      test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, pos_x , pos_w);
+      temp = shift;
+      test = LLVMBuildAnd(builder, test, temp, ""); 
+      mask = test;
    
-   /* plane 2 */
-   test = LLVMBuildFAdd(builder, pos_x, pos_w, "");
-   test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, zero, test);
-   temp = LLVMBuildShl(builder, temp, shift, "");
-   test = LLVMBuildAnd(builder, test, temp, ""); 
-   mask = LLVMBuildOr(builder, mask, test, "");
+      /* plane 2 */
+      test = LLVMBuildFAdd(builder, pos_x, pos_w, "");
+      test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, zero, test);
+      temp = LLVMBuildShl(builder, temp, shift, "");
+      test = LLVMBuildAnd(builder, test, temp, ""); 
+      mask = LLVMBuildOr(builder, mask, test, "");
    
-   /* plane 3 */
-   test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, pos_y, pos_w);
-   temp = LLVMBuildShl(builder, temp, shift, "");
-   test = LLVMBuildAnd(builder, test, temp, ""); 
-   mask = LLVMBuildOr(builder, mask, test, "");
-
-   /* plane 4 */
-   test = LLVMBuildFAdd(builder, pos_y, pos_w, "");
-   test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, zero, test);
-   temp = LLVMBuildShl(builder, temp, shift, "");
-   test = LLVMBuildAnd(builder, test, temp, ""); 
-   mask = LLVMBuildOr(builder, mask, test, "");
-
-   if (!disable_zclipping){
-      if (enable_d3dclipping){
+      /* plane 3 */
+      test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, pos_y, pos_w);
+      temp = LLVMBuildShl(builder, temp, shift, "");
+      test = LLVMBuildAnd(builder, test, temp, ""); 
+      mask = LLVMBuildOr(builder, mask, test, "");
+
+      /* plane 4 */
+      test = LLVMBuildFAdd(builder, pos_y, pos_w, "");
+      test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, zero, test);
+      temp = LLVMBuildShl(builder, temp, shift, "");
+      test = LLVMBuildAnd(builder, test, temp, ""); 
+      mask = LLVMBuildOr(builder, mask, test, "");
+   }
+
+   if (clip_z){
+      temp = lp_build_const_int_vec(lp_type_int_vec(32), 16);
+      if (clip_halfz){
          /* plane 5 */
          test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, zero, pos_z);
-         temp = LLVMBuildShl(builder, temp, shift, "");
          test = LLVMBuildAnd(builder, test, temp, ""); 
          mask = LLVMBuildOr(builder, mask, test, "");
       }  
@@ -881,7 +922,6 @@ generate_clipmask(LLVMBuilderRef builder,
          /* plane 5 */
          test = LLVMBuildFAdd(builder, pos_z, pos_w, "");
          test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, zero, test);
-         temp = LLVMBuildShl(builder, temp, shift, "");
          test = LLVMBuildAnd(builder, test, temp, ""); 
          mask = LLVMBuildOr(builder, mask, test, "");
       }
@@ -892,6 +932,49 @@ generate_clipmask(LLVMBuilderRef builder,
       mask = LLVMBuildOr(builder, mask, test, "");
    }   
 
+   if (clip_user){
+      LLVMValueRef planes_ptr = draw_jit_context_planes(builder, context_ptr);
+      LLVMValueRef indices[3];
+      temp = lp_build_const_int_vec(lp_type_int_vec(32), 32);
+
+      /* userclip planes */
+      for (i = 6; i < nr; i++) {
+         indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
+         indices[1] = LLVMConstInt(LLVMInt32Type(), i, 0);
+
+         indices[2] = LLVMConstInt(LLVMInt32Type(), 0, 0);
+         plane_ptr = LLVMBuildGEP(builder, planes_ptr, indices, 3, "");
+         plane1 = LLVMBuildLoad(builder, plane_ptr, "plane_x");
+         planes = vec4f_from_scalar(builder, plane1, "plane4_x");
+         sum = LLVMBuildFMul(builder, planes, pos_x, "");
+
+         indices[2] = LLVMConstInt(LLVMInt32Type(), 1, 0);
+         plane_ptr = LLVMBuildGEP(builder, planes_ptr, indices, 3, "");
+         plane1 = LLVMBuildLoad(builder, plane_ptr, "plane_y"); 
+         planes = vec4f_from_scalar(builder, plane1, "plane4_y");
+         test = LLVMBuildFMul(builder, planes, pos_y, "");
+         sum = LLVMBuildFAdd(builder, sum, test, "");
+         
+         indices[2] = LLVMConstInt(LLVMInt32Type(), 2, 0);
+         plane_ptr = LLVMBuildGEP(builder, planes_ptr, indices, 3, "");
+         plane1 = LLVMBuildLoad(builder, plane_ptr, "plane_z"); 
+         planes = vec4f_from_scalar(builder, plane1, "plane4_z");
+         test = LLVMBuildFMul(builder, planes, pos_z, "");
+         sum = LLVMBuildFAdd(builder, sum, test, "");
+
+         indices[2] = LLVMConstInt(LLVMInt32Type(), 3, 0);
+         plane_ptr = LLVMBuildGEP(builder, planes_ptr, indices, 3, "");
+         plane1 = LLVMBuildLoad(builder, plane_ptr, "plane_w"); 
+         planes = vec4f_from_scalar(builder, plane1, "plane4_w");
+         test = LLVMBuildFMul(builder, planes, pos_w, "");
+         sum = LLVMBuildFAdd(builder, sum, test, "");
+
+         test = lp_build_compare(builder, f32_type, PIPE_FUNC_GREATER, zero, sum);
+         temp = LLVMBuildShl(builder, temp, shift, "");
+         test = LLVMBuildAnd(builder, test, temp, ""); 
+         mask = LLVMBuildOr(builder, mask, test, "");
+      }
+   }
    return mask;
 }
 
@@ -908,18 +991,13 @@ clipmask_bool(LLVMBuilderRef builder,
    LLVMValueRef temp;
    int i;
 
-   LLVMDumpValue(clipmask);
-
    for (i=0; i<4; i++){   
       temp = LLVMBuildExtractElement(builder, clipmask,
                                      LLVMConstInt(LLVMInt32Type(), i, 0) , "");
       ret = LLVMBuildOr(builder, ret, temp, "");
-      LLVMDumpValue(ret);  
    }
    
    LLVMBuildStore(builder, ret, ret_ptr);
-   LLVMDumpValue(ret_ptr); 
-
 }
 
 static void
@@ -942,8 +1020,10 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
    void *code;
    struct lp_build_sampler_soa *sampler = 0;
    LLVMValueRef ret, ret_ptr;
-   boolean disable_cliptest = variant->key.disable_cliptest;
-   boolean disable_viewport = variant->key.disable_viewport;
+   boolean bypass_viewport = variant->key.bypass_viewport;
+   boolean enable_cliptest = variant->key.clip_xy || 
+                             variant->key.clip_z  ||
+                             variant->key.clip_user;
    
    arg_types[0] = llvm->context_ptr_type;           /* context */
    arg_types[1] = llvm->vertex_header_ptr_type;     /* vertex_header */
@@ -1053,10 +1133,15 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
       store_clip(builder, io, outputs);
 
       /* do cliptest */
-      if (!disable_cliptest){
+      if (enable_cliptest){
          /* allocate clipmask, assign it integer type */
-         clipmask = generate_clipmask(builder, outputs, 
-                       variant->key.disable_zclipping, variant->key.enable_d3dclipping);
+         clipmask = generate_clipmask(builder, outputs,
+                                      variant->key.clip_xy,
+                                      variant->key.clip_z, 
+                                      variant->key.clip_user,
+                                      variant->key.clip_halfz,
+                                      variant->key.nr_planes,
+                                      context_ptr);
          /* return clipping boolean value for function */
          clipmask_bool(builder, clipmask, ret_ptr);
       }
@@ -1065,8 +1150,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
       }
       
       /* do viewport mapping */
-      if (!disable_viewport){
-         generate_viewport(llvm, builder, outputs);
+      if (!bypass_viewport){
+         generate_viewport(llvm, builder, outputs, context_ptr);
       }
 
       /* store clipmask in vertex header and positions in data */
@@ -1079,11 +1164,6 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
 
    sampler->destroy(sampler);
 
-#ifdef PIPE_ARCH_X86
-   /* Avoid corrupting the FPU stack on 32bit OSes. */
-   lp_build_intrinsic(builder, "llvm.x86.mmx.emms", LLVMVoidType(), NULL, 0);
-#endif
-
    ret = LLVMBuildLoad(builder, ret_ptr,"");
    LLVMBuildRet(builder, ret);
       
@@ -1137,9 +1217,11 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
    void *code;
    struct lp_build_sampler_soa *sampler = 0;
    LLVMValueRef ret, ret_ptr;
-   boolean disable_cliptest = variant->key.disable_cliptest;
-   boolean disable_viewport = variant->key.disable_viewport;
-
+   boolean bypass_viewport = variant->key.bypass_viewport;
+   boolean enable_cliptest = variant->key.clip_xy || 
+                             variant->key.clip_z  ||
+                             variant->key.clip_user;
+   
    arg_types[0] = llvm->context_ptr_type;               /* context */
    arg_types[1] = llvm->vertex_header_ptr_type;         /* vertex_header */
    arg_types[2] = llvm->buffer_ptr_type;                /* vbuffers */
@@ -1257,10 +1339,15 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
       store_clip(builder, io, outputs);
 
       /* do cliptest */
-      if (!disable_cliptest){
+      if (enable_cliptest){
          /* allocate clipmask, assign it integer type */
-         clipmask = generate_clipmask(builder, outputs, 
-                       variant->key.disable_zclipping, variant->key.enable_d3dclipping);
+         clipmask = generate_clipmask(builder, outputs,
+                                      variant->key.clip_xy,
+                                      variant->key.clip_z, 
+                                      variant->key.clip_user,
+                                      variant->key.clip_halfz,
+                                      variant->key.nr_planes,
+                                      context_ptr);
          /* return clipping boolean value for function */
          clipmask_bool(builder, clipmask, ret_ptr);
       }
@@ -1269,8 +1356,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
       }
       
       /* do viewport mapping */
-      if (!disable_viewport){
-         generate_viewport(llvm, builder, outputs);
+      if (!bypass_viewport){
+         generate_viewport(llvm, builder, outputs, context_ptr);
       }
 
       /* store clipmask in vertex header, 
@@ -1286,11 +1373,6 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
 
    sampler->destroy(sampler);
 
-#ifdef PIPE_ARCH_X86
-   /* Avoid corrupting the FPU stack on 32bit OSes. */
-   lp_build_intrinsic(builder, "llvm.x86.mmx.emms", LLVMVoidType(), NULL, 0);
-#endif
-
    ret = LLVMBuildLoad(builder, ret_ptr,"");   
    LLVMBuildRet(builder, ret);
    
@@ -1338,10 +1420,14 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
    key->nr_vertex_elements = llvm->draw->pt.nr_vertex_elements;
 
    /* will have to rig this up properly later */
-   key->disable_cliptest = 0;
-   key->disable_viewport = 0;
-   key->disable_zclipping = 0;
-   key->enable_d3dclipping = 0;
+   key->clip_xy = llvm->draw->clip_xy;
+   key->clip_z = llvm->draw->clip_z;
+   key->clip_user = llvm->draw->clip_user;
+   key->bypass_viewport = llvm->draw->identity_viewport;
+   key->clip_halfz = !llvm->draw->rasterizer->gl_rasterization_rules;
+   key->need_edgeflags = (llvm->draw->vs.edgeflag_output ? TRUE : FALSE);
+   key->nr_planes = llvm->draw->nr_planes;
+   key->pad = 0;
 
    /* All variants of this shader will have the same value for
     * nr_samplers.  Not yet trying to compact away holes in the
@@ -1371,9 +1457,9 @@ draw_llvm_set_mapped_texture(struct draw_context *draw,
                              unsigned sampler_idx,
                              uint32_t width, uint32_t height, uint32_t depth,
                              uint32_t last_level,
-                             uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS],
-                             uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS],
-                             const void *data[DRAW_MAX_TEXTURE_LEVELS])
+                             uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS],
+                             uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
+                             const void *data[PIPE_MAX_TEXTURE_LEVELS])
 {
    unsigned j;
    struct draw_jit_texture *jit_tex;
@@ -1395,6 +1481,25 @@ draw_llvm_set_mapped_texture(struct draw_context *draw,
    }
 }
 
+
+void
+draw_llvm_set_sampler_state(struct draw_context *draw)
+{
+   unsigned i;
+
+   for (i = 0; i < draw->num_samplers; i++) {
+      struct draw_jit_texture *jit_tex = &draw->llvm->jit_context.textures[i];
+
+      if (draw->samplers[i]) {
+         jit_tex->min_lod = draw->samplers[i]->min_lod;
+         jit_tex->max_lod = draw->samplers[i]->max_lod;
+         jit_tex->lod_bias = draw->samplers[i]->lod_bias;
+         COPY_4V(jit_tex->border_color, draw->samplers[i]->border_color);
+      }
+   }
+}
+
+
 void
 draw_llvm_destroy_variant(struct draw_llvm_variant *variant)
 {