[Mesa-dev] [PATCH] gallivm: fix up size queries for dx10 sviewinfo opcode

sroland at vmware.com sroland at vmware.com
Fri Feb 1 17:54:19 PST 2013


From: Roland Scheidegger <sroland at vmware.com>

Need to calculate the number of mip levels (if it would be worthwile could
store it in dynamic state).
Also, it looks like without modifiers this opcode should return floats
so handle that as well.
While here, the query code also used chan 2 for the lod value.
This worked with mesa state tracker but it seems safer to use chan 0.
Still passes piglit textureSize (with some handwaving), though the non-GL
parts are untested.
---
 src/gallium/auxiliary/draw/draw_llvm_sample.c     |    2 +
 src/gallium/auxiliary/gallivm/lp_bld_sample.h     |    1 +
 src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c |   60 ++++++++++++++++++---
 src/gallium/auxiliary/gallivm/lp_bld_tgsi.h       |    1 +
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   |   33 +++++++-----
 src/gallium/drivers/llvmpipe/lp_tex_sample.c      |    2 +
 6 files changed, 78 insertions(+), 21 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_llvm_sample.c b/src/gallium/auxiliary/draw/draw_llvm_sample.c
index 03a2592..e51e011 100644
--- a/src/gallium/auxiliary/draw/draw_llvm_sample.c
+++ b/src/gallium/auxiliary/draw/draw_llvm_sample.c
@@ -269,6 +269,7 @@ draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
                                       struct gallivm_state *gallivm,
                                       struct lp_type type,
                                       unsigned texture_unit,
+                                      boolean need_nr_mips,
                                       LLVMValueRef explicit_lod, /* optional */
                                       LLVMValueRef *sizes_out)
 {
@@ -281,6 +282,7 @@ draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
                            &sampler->dynamic_state.base,
                            type,
                            texture_unit,
+                           need_nr_mips,
                            explicit_lod,
                            sizes_out);
 }
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
index 77ce008..f502216 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
@@ -487,6 +487,7 @@ lp_build_size_query_soa(struct gallivm_state *gallivm,
                         struct lp_sampler_dynamic_state *dynamic_state,
                         struct lp_type int_type,
                         unsigned texture_unit,
+                        boolean need_nr_mips,
                         LLVMValueRef explicit_lod,
                         LLVMValueRef *sizes_out);
 
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index 778400a..f6fe366 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -1740,16 +1740,19 @@ void
 lp_build_size_query_soa(struct gallivm_state *gallivm,
                         const struct lp_static_texture_state *static_state,
                         struct lp_sampler_dynamic_state *dynamic_state,
-                        struct lp_type int_type,
+                        struct lp_type ret_type,
                         unsigned texture_unit,
+                        boolean need_nr_mips,
                         LLVMValueRef explicit_lod,
                         LLVMValueRef *sizes_out)
 {
    LLVMValueRef lod;
    LLVMValueRef size;
+   LLVMValueRef first_level = NULL;
    int dims, i;
    boolean has_array = FALSE;
    struct lp_build_context bld_int_vec;
+   struct lp_type size_type;
 
    switch (static_state->target) {
    case PIPE_TEXTURE_1D:
@@ -1777,12 +1780,9 @@ lp_build_size_query_soa(struct gallivm_state *gallivm,
       return;
    }
 
-   assert(!int_type.floating);
-
    lp_build_context_init(&bld_int_vec, gallivm, lp_type_int_vec(32, 128));
 
    if (explicit_lod) {
-      LLVMValueRef first_level;
       lod = LLVMBuildExtractElement(gallivm->builder, explicit_lod, lp_build_const_int32(gallivm, 0), "");
       first_level = dynamic_state->first_level(dynamic_state, gallivm, texture_unit);
       lod = lp_build_broadcast_scalar(&bld_int_vec,
@@ -1792,7 +1792,12 @@ lp_build_size_query_soa(struct gallivm_state *gallivm,
       lod = bld_int_vec.zero;
    }
 
-   size = bld_int_vec.undef;
+   if (need_nr_mips) {
+      size = bld_int_vec.zero;
+   }
+   else {
+      size = bld_int_vec.undef;
+   }
 
    size = LLVMBuildInsertElement(gallivm->builder, size,
                                  dynamic_state->width(dynamic_state, gallivm, texture_unit),
@@ -1811,15 +1816,56 @@ lp_build_size_query_soa(struct gallivm_state *gallivm,
    }
 
    size = lp_build_minify(&bld_int_vec, size, lod);
- 
+
    if (has_array)
       size = LLVMBuildInsertElement(gallivm->builder, size,
                                     dynamic_state->depth(dynamic_state, gallivm, texture_unit),
                                     lp_build_const_int32(gallivm, dims), "");
 
+   /*
+    * XXX for out-of-bounds lod, should set size to zero vector here
+    * (for dx10-style only, i.e. need_nr_mips)
+    */
+ 
+   if (need_nr_mips) {
+      struct lp_build_context bld_int_scalar;
+      LLVMValueRef num_levels;
+      lp_build_context_init(&bld_int_scalar, gallivm, lp_type_int(32));
+
+      if (static_state->target == PIPE_BUFFER ||
+          static_state->level_zero_only) {
+         num_levels = bld_int_scalar.one;
+      }
+      else {
+         LLVMValueRef last_level, num_levels;
+         assert(first_level);
+
+         last_level = dynamic_state->last_level(dynamic_state, gallivm, texture_unit);
+         num_levels = lp_build_sub(&bld_int_scalar, last_level, first_level);
+         num_levels = lp_build_add(&bld_int_scalar, num_levels, bld_int_scalar.one);
+      }
+      size = LLVMBuildInsertElement(gallivm->builder, size,
+                                    num_levels,
+                                    lp_build_const_int32(gallivm, 3), "");
+   }
+
+   if (ret_type.floating) {
+      size = lp_build_int_to_float(&bld_int_vec, size);
+      size_type = lp_type_float_vec(32, 128);
+   }
+   else {
+      size_type = bld_int_vec.type;
+   }
+
    for (i = 0; i < dims + (has_array ? 1 : 0); i++) {
-      sizes_out[i] = lp_build_extract_broadcast(gallivm, bld_int_vec.type, int_type,
+      sizes_out[i] = lp_build_extract_broadcast(gallivm, size_type, ret_type,
                                                 size,
                                                 lp_build_const_int32(gallivm, i));
    }
+
+   if (need_nr_mips) {
+      sizes_out[3] =  lp_build_extract_broadcast(gallivm, size_type, ret_type,
+                                                 size,
+                                                 lp_build_const_int32(gallivm, 3));
+   }
 }
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
index adc63ef..407e968 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
@@ -189,6 +189,7 @@ struct lp_build_sampler_soa
                        struct gallivm_state *gallivm,
                        struct lp_type type,
                        unsigned unit,
+                       boolean need_nr_mips,
                        LLVMValueRef explicit_lod, /* optional */
                        LLVMValueRef *sizes_out);
 };
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index 5eeaaf4..2d4e7cf 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -1621,14 +1621,23 @@ emit_txf( struct lp_build_tgsi_soa_context *bld,
 }
 
 static void
-emit_txq( struct lp_build_tgsi_soa_context *bld,
-          const struct tgsi_full_instruction *inst,
-          LLVMValueRef *sizes_out)
+emit_size_query( struct lp_build_tgsi_soa_context *bld,
+                 const struct tgsi_full_instruction *inst,
+                 LLVMValueRef *sizes_out,
+                 boolean is_sviewinfo)
 {
+   struct lp_build_context *bld_ctx;
    LLVMValueRef explicit_lod;
    unsigned num_coords, has_lod;
    unsigned i;
 
+   if (is_sviewinfo) {
+      bld_ctx = &bld->bld_base.base;
+   }
+   else {
+      bld_ctx = &bld->bld_base.int_bld;
+   }
+
    switch (inst->Texture.Texture) {
    case TGSI_TEXTURE_1D:
    case TGSI_TEXTURE_SHADOW1D:
@@ -1678,19 +1687,20 @@ emit_txq( struct lp_build_tgsi_soa_context *bld,
    if (!bld->sampler) {
       _debug_printf("warning: found texture query instruction but no sampler generator supplied\n");
       for (i = 0; i < num_coords; i++)
-         sizes_out[i] = bld->bld_base.base.undef;
+         sizes_out[i] = bld_ctx->undef;
       return;
    }
 
    if (has_lod)
-      explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 2 );
+      explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 0 );
    else
       explicit_lod = NULL;
 
    bld->sampler->emit_size_query(bld->sampler,
                                  bld->bld_base.base.gallivm,
-                                 bld->bld_base.int_bld.type,
+                                 bld_ctx->type,
                                  inst->Src[1].Register.Index,
+                                 is_sviewinfo,
                                  explicit_lod,
                                  sizes_out);
 }
@@ -2078,7 +2088,7 @@ txq_emit(
 {
    struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
 
-   emit_txq(bld, emit_data->inst, emit_data->output);
+   emit_size_query(bld, emit_data->inst, emit_data->output, FALSE);
 }
 
 static void
@@ -2174,13 +2184,8 @@ sviewinfo_emit(
    struct lp_build_emit_data * emit_data)
 {
    struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
-   /*
-    * FIXME: unlike txq we are required to return number of mipmap levels
-    * too, and the unused channels are defined to be zero.
-    * Either always do that (and hope llvm can optimize it away?)
-    * or pass a parameter all the way down.
-    */
-   emit_txq(bld, emit_data->inst, emit_data->output);
+
+   emit_size_query(bld, emit_data->inst, emit_data->output, TRUE);
 }
 
 static void
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c
index 69ac888..df2a610 100644
--- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c
+++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c
@@ -279,6 +279,7 @@ lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
                                     struct gallivm_state *gallivm,
                                     struct lp_type type,
                                     unsigned texture_unit,
+                                    boolean need_nr_mips,
                                     LLVMValueRef explicit_lod, /* optional */
                                     LLVMValueRef *sizes_out)
 {
@@ -291,6 +292,7 @@ lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
                            &sampler->dynamic_state.base,
                            type,
                            texture_unit,
+                           need_nr_mips,
                            explicit_lod,
                            sizes_out);
 }
-- 
1.7.9.5



More information about the mesa-dev mailing list