llvmpipe/gallivm: checkpoint: array of pointers to mipmap levels
authorBrian Paul <brianp@vmware.com>
Mon, 8 Mar 2010 22:19:13 +0000 (15:19 -0700)
committerBrian Paul <brianp@vmware.com>
Mon, 8 Mar 2010 23:26:44 +0000 (16:26 -0700)
Change the texture data_ptr from just a single image pointer to an
array of image pointers, indexed by mipmap level.
We'll use this for mipmap filtering.
For now, the mipmap level is hard-coded to zero.

src/gallium/auxiliary/gallivm/lp_bld_sample.c
src/gallium/auxiliary/gallivm/lp_bld_sample.h
src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
src/gallium/drivers/llvmpipe/lp_jit.c
src/gallium/drivers/llvmpipe/lp_jit.h
src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c

index 29cadcc15ae5286b0762399538480111f9358f50..311c9f1b9e435d0cbd87c1f7e0c47d687c1152e2 100644 (file)
@@ -162,8 +162,7 @@ lp_build_sample_offset(struct lp_build_context *bld,
                        const struct util_format_description *format_desc,
                        LLVMValueRef x,
                        LLVMValueRef y,
-                       LLVMValueRef y_stride,
-                       LLVMValueRef data_ptr)
+                       LLVMValueRef y_stride)
 {
    LLVMValueRef x_stride;
    LLVMValueRef offset;
index 5ba0925bb691ee5635f65775ddd4d11ae26ef0d8..68db91d6fd6716616c6557776c8c22d621d60eaa 100644 (file)
@@ -148,8 +148,7 @@ lp_build_sample_offset(struct lp_build_context *bld,
                        const struct util_format_description *format_desc,
                        LLVMValueRef x,
                        LLVMValueRef y,
-                       LLVMValueRef y_stride,
-                       LLVMValueRef data_ptr);
+                       LLVMValueRef y_stride);
 
 
 void
index 9058f76c1df60fa392a2237f0f3cc6a5855114fc..1dca29cdd5894559c2a90e05c294a314f03fe61e 100644 (file)
@@ -124,13 +124,14 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
                           LLVMValueRef x,
                           LLVMValueRef y,
                           LLVMValueRef y_stride,
-                          LLVMValueRef data_ptr,
+                          LLVMValueRef data_array,
                           LLVMValueRef *texel)
 {
    struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
    LLVMValueRef offset;
    LLVMValueRef packed;
    LLVMValueRef use_border = NULL;
+   LLVMValueRef data_ptr;
 
    /* use_border = x < 0 || x >= width || y < 0 || y >= height */
    if (wrap_mode_uses_border_color(bld->static_state->wrap_s)) {
@@ -153,6 +154,16 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
       }
    }
 
+   /* XXX always use mipmap level 0 for now */
+   {
+      const int level = 0;
+      LLVMValueRef indexes[2];
+      indexes[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
+      indexes[1] = LLVMConstInt(LLVMInt32Type(), level, 0);
+      data_ptr = LLVMBuildGEP(bld->builder, data_array, indexes, 2, "");
+      data_ptr = LLVMBuildLoad(bld->builder, data_ptr, "");
+   }
+
    /*
     * Note: if we find an app which frequently samples the texture border
     * we might want to implement a true conditional here to avoid sampling
@@ -171,8 +182,7 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
    /* convert x,y coords to linear offset from start of texture, in bytes */
    offset = lp_build_sample_offset(&bld->uint_coord_bld,
                                    bld->format_desc,
-                                   x, y, y_stride,
-                                   data_ptr);
+                                   x, y, y_stride);
 
    assert(bld->format_desc->block.width == 1);
    assert(bld->format_desc->block.height == 1);
@@ -210,19 +220,31 @@ lp_build_sample_packed(struct lp_build_sample_context *bld,
                        LLVMValueRef x,
                        LLVMValueRef y,
                        LLVMValueRef y_stride,
-                       LLVMValueRef data_ptr)
+                       LLVMValueRef data_array)
 {
    LLVMValueRef offset;
+   LLVMValueRef data_ptr;
 
    offset = lp_build_sample_offset(&bld->uint_coord_bld,
                                    bld->format_desc,
-                                   x, y, y_stride,
-                                   data_ptr);
+                                   x, y, y_stride);
 
    assert(bld->format_desc->block.width == 1);
    assert(bld->format_desc->block.height == 1);
    assert(bld->format_desc->block.bits <= bld->texel_type.width);
 
+   /* XXX always use mipmap level 0 for now */
+   {
+      const int level = 0;
+      LLVMValueRef indexes[2];
+      /* get data_ptr[level] */
+      indexes[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
+      indexes[1] = LLVMConstInt(LLVMInt32Type(), level, 0);
+      data_ptr = LLVMBuildGEP(bld->builder, data_array, indexes, 2, "");
+      /* load texture base address */
+      data_ptr = LLVMBuildLoad(bld->builder, data_ptr, "");
+   }
+
    return lp_build_gather(bld->builder,
                           bld->texel_type.length,
                           bld->format_desc->block.bits,
@@ -720,7 +742,7 @@ lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
                                LLVMValueRef width,
                                LLVMValueRef height,
                                LLVMValueRef stride,
-                               LLVMValueRef data_ptr,
+                               LLVMValueRef data_array,
                                LLVMValueRef *texel)
 {
    LLVMValueRef x, y;
@@ -735,7 +757,7 @@ lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
    lp_build_name(x, "tex.x.wrapped");
    lp_build_name(y, "tex.y.wrapped");
 
-   lp_build_sample_texel_soa(bld, width, height, x, y, stride, data_ptr, texel);
+   lp_build_sample_texel_soa(bld, width, height, x, y, stride, data_array, texel);
 }
 
 
@@ -749,7 +771,7 @@ lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
                               LLVMValueRef width,
                               LLVMValueRef height,
                               LLVMValueRef stride,
-                              LLVMValueRef data_ptr,
+                              LLVMValueRef data_array,
                               LLVMValueRef *texel)
 {
    LLVMValueRef s_fpart;
@@ -764,10 +786,10 @@ lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
    lp_build_sample_wrap_linear(bld, t, height, bld->static_state->pot_height,
                                bld->static_state->wrap_t, &y0, &y1, &t_fpart);
 
-   lp_build_sample_texel_soa(bld, width, height, x0, y0, stride, data_ptr, neighbors[0][0]);
-   lp_build_sample_texel_soa(bld, width, height, x1, y0, stride, data_ptr, neighbors[0][1]);
-   lp_build_sample_texel_soa(bld, width, height, x0, y1, stride, data_ptr, neighbors[1][0]);
-   lp_build_sample_texel_soa(bld, width, height, x1, y1, stride, data_ptr, neighbors[1][1]);
+   lp_build_sample_texel_soa(bld, width, height, x0, y0, stride, data_array, neighbors[0][0]);
+   lp_build_sample_texel_soa(bld, width, height, x1, y0, stride, data_array, neighbors[0][1]);
+   lp_build_sample_texel_soa(bld, width, height, x0, y1, stride, data_array, neighbors[1][0]);
+   lp_build_sample_texel_soa(bld, width, height, x1, y1, stride, data_array, neighbors[1][1]);
 
    /* TODO: Don't interpolate missing channels */
    for(chan = 0; chan < 4; ++chan) {
@@ -818,7 +840,7 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
                               LLVMValueRef width,
                               LLVMValueRef height,
                               LLVMValueRef stride,
-                              LLVMValueRef data_ptr,
+                              LLVMValueRef data_array,
                               LLVMValueRef *texel)
 {
    LLVMBuilderRef builder = bld->builder;
@@ -958,10 +980,10 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
     * The higher 8 bits of the resulting elements will be zero.
     */
 
-   neighbors[0][0] = lp_build_sample_packed(bld, x0, y0, stride, data_ptr);
-   neighbors[0][1] = lp_build_sample_packed(bld, x1, y0, stride, data_ptr);
-   neighbors[1][0] = lp_build_sample_packed(bld, x0, y1, stride, data_ptr);
-   neighbors[1][1] = lp_build_sample_packed(bld, x1, y1, stride, data_ptr);
+   neighbors[0][0] = lp_build_sample_packed(bld, x0, y0, stride, data_array);
+   neighbors[0][1] = lp_build_sample_packed(bld, x1, y0, stride, data_array);
+   neighbors[1][0] = lp_build_sample_packed(bld, x0, y1, stride, data_array);
+   neighbors[1][1] = lp_build_sample_packed(bld, x1, y1, stride, data_array);
 
    neighbors[0][0] = LLVMBuildBitCast(builder, neighbors[0][0], u8n_vec_type, "");
    neighbors[0][1] = LLVMBuildBitCast(builder, neighbors[0][1], u8n_vec_type, "");
@@ -1248,7 +1270,7 @@ lp_build_sample_soa(LLVMBuilderRef builder,
    LLVMValueRef width;
    LLVMValueRef height;
    LLVMValueRef stride;
-   LLVMValueRef data_ptr;
+   LLVMValueRef data_array;
    LLVMValueRef s;
    LLVMValueRef t;
    LLVMValueRef r;
@@ -1276,7 +1298,8 @@ lp_build_sample_soa(LLVMBuilderRef builder,
    width = dynamic_state->width(dynamic_state, builder, unit);
    height = dynamic_state->height(dynamic_state, builder, unit);
    stride = dynamic_state->stride(dynamic_state, builder, unit);
-   data_ptr = dynamic_state->data_ptr(dynamic_state, builder, unit);
+   data_array = dynamic_state->data_ptr(dynamic_state, builder, unit);
+   /* Note that data_array is an array[level] of pointers to texture images */
 
    s = coords[0];
    t = coords[1];
@@ -1292,17 +1315,17 @@ lp_build_sample_soa(LLVMBuilderRef builder,
    switch (static_state->min_img_filter) {
    case PIPE_TEX_FILTER_NEAREST:
       lp_build_sample_2d_nearest_soa(&bld, s, t, width, height,
-                                     stride, data_ptr, texel);
+                                     stride, data_array, texel);
       break;
    case PIPE_TEX_FILTER_LINEAR:
       if(lp_format_is_rgba8(bld.format_desc) &&
          is_simple_wrap_mode(static_state->wrap_s) &&
          is_simple_wrap_mode(static_state->wrap_t))
          lp_build_sample_2d_linear_aos(&bld, s, t, width, height,
-                                       stride, data_ptr, texel);
+                                       stride, data_array, texel);
       else
          lp_build_sample_2d_linear_soa(&bld, s, t, width, height,
-                                       stride, data_ptr, texel);
+                                       stride, data_array, texel);
       break;
    default:
       assert(0);
index bacff500d63ca48c7f6cfb067a523bfc616c08db..08c8f93794d219e4ec3428046819759bf066f655 100644 (file)
@@ -58,7 +58,9 @@ lp_jit_init_globals(struct llvmpipe_screen *screen)
       elem_types[LP_JIT_TEXTURE_DEPTH] = LLVMInt32Type();
       elem_types[LP_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type();
       elem_types[LP_JIT_TEXTURE_STRIDE] = LLVMInt32Type();
-      elem_types[LP_JIT_TEXTURE_DATA]   = LLVMPointerType(LLVMInt8Type(), 0);
+      elem_types[LP_JIT_TEXTURE_DATA] =
+         LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0),
+                       LP_MAX_TEXTURE_2D_LEVELS);
 
       texture_type = LLVMStructType(elem_types, Elements(elem_types), 0);
 
index 0ebb2826fa2684f116cfad714521d47253b3704f..5cc7a12c03bd96ec8cb05153cc71f2e28654558c 100644 (file)
@@ -39,6 +39,7 @@
 #include "gallivm/lp_bld_struct.h"
 
 #include "pipe/p_state.h"
+#include "lp_texture.h"
 
 
 struct llvmpipe_screen;
@@ -51,7 +52,7 @@ struct lp_jit_texture
    uint32_t depth;
    uint32_t last_level;
    uint32_t stride;
-   const void *data;
+   const void *data[LP_MAX_TEXTURE_2D_LEVELS];
 };
 
 
index b0713c3b71d6d6239089831360cd595465e29421..cc7c18c8c0c039294532febdf9ec4d18b4f9ec59 100644 (file)
@@ -472,19 +472,25 @@ lp_setup_set_sampler_textures( struct setup_context *setup,
          jit_tex->depth = tex->depth0;
          jit_tex->last_level = tex->last_level;
          jit_tex->stride = lp_tex->stride[0];
-         if(!lp_tex->dt) {
-            jit_tex->data = lp_tex->data;
+         if (!lp_tex->dt) {
+            /* regular texture - setup array of mipmap level pointers */
+            int j;
+            for (j = 0; j < LP_MAX_TEXTURE_2D_LEVELS; j++) {
+               jit_tex->data[j] =
+                  (ubyte *) lp_tex->data + lp_tex->level_offset[j];
+            }
          }
          else {
+            /* display target texture/surface */
             /*
              * XXX: Where should this be unmapped?
              */
 
             struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen);
             struct llvmpipe_winsys *winsys = screen->winsys;
-            jit_tex->data = winsys->displaytarget_map(winsys, lp_tex->dt,
-                                                      PIPE_BUFFER_USAGE_CPU_READ);
-            assert(jit_tex->data);
+            jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt,
+                                                 PIPE_BUFFER_USAGE_CPU_READ);
+            assert(jit_tex->data[0]);
          }
 
          /* the scene references this texture */
index fde2d653eba6ea254940f9174cff44b92664f6ab..5a3cf37d6d8eafb45c6c734d6658edb836e40a6c 100644 (file)
@@ -80,6 +80,9 @@ struct lp_llvm_sampler_soa
 
 /**
  * Fetch the specified member of the lp_jit_texture 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
  */
@@ -88,7 +91,8 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base,
                        LLVMBuilderRef builder,
                        unsigned unit,
                        unsigned member_index,
-                       const char *member_name)
+                       const char *member_name,
+                       boolean emit_load)
 {
    struct llvmpipe_sampler_dynamic_state *state =
       (struct llvmpipe_sampler_dynamic_state *)base;
@@ -109,7 +113,10 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base,
 
    ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
 
-   res = LLVMBuildLoad(builder, ptr, "");
+   if (emit_load)
+      res = LLVMBuildLoad(builder, ptr, "");
+   else
+      res = ptr;
 
    lp_build_name(res, "context.texture%u.%s", unit, member_name);
 
@@ -126,22 +133,22 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base,
  * sampler code generator a reusable module without dependencies to
  * llvmpipe internals.
  */
-#define LP_LLVM_TEXTURE_MEMBER(_name, _index) \
+#define LP_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load)  \
    static LLVMValueRef \
    lp_llvm_texture_##_name( struct lp_sampler_dynamic_state *base, \
                             LLVMBuilderRef builder, \
                             unsigned unit) \
    { \
-      return lp_llvm_texture_member(base, builder, unit, _index, #_name ); \
+      return lp_llvm_texture_member(base, builder, unit, _index, #_name, _emit_load ); \
    }
 
 
-LP_LLVM_TEXTURE_MEMBER(width,      LP_JIT_TEXTURE_WIDTH)
-LP_LLVM_TEXTURE_MEMBER(height,     LP_JIT_TEXTURE_HEIGHT)
-LP_LLVM_TEXTURE_MEMBER(depth,      LP_JIT_TEXTURE_DEPTH)
-LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL)
-LP_LLVM_TEXTURE_MEMBER(stride,     LP_JIT_TEXTURE_STRIDE)
-LP_LLVM_TEXTURE_MEMBER(data_ptr,   LP_JIT_TEXTURE_DATA)
+LP_LLVM_TEXTURE_MEMBER(width,      LP_JIT_TEXTURE_WIDTH, TRUE)
+LP_LLVM_TEXTURE_MEMBER(height,     LP_JIT_TEXTURE_HEIGHT, TRUE)
+LP_LLVM_TEXTURE_MEMBER(depth,      LP_JIT_TEXTURE_DEPTH, TRUE)
+LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL, TRUE)
+LP_LLVM_TEXTURE_MEMBER(stride,     LP_JIT_TEXTURE_STRIDE, TRUE)
+LP_LLVM_TEXTURE_MEMBER(data_ptr,   LP_JIT_TEXTURE_DATA, FALSE)
 
 
 static void