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

sroland at vmware.com sroland at vmware.com
Tue Feb 5 13:40:31 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).
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 (largely) untested.

v2: clarify and expect the sviewinfo opcode to return ints, not floats,
just like the OpenGL textureSize (dx10 supports dst modifiers with resinfo).
Also simplify some code.
---
 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 |   64 +++++++++++++-------
 src/gallium/auxiliary/gallivm/lp_bld_tgsi.h       |    1 +
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   |   66 +++++----------------
 src/gallium/auxiliary/tgsi/tgsi_info.c            |    4 ++
 src/gallium/docs/source/tgsi.rst                  |    2 +-
 src/gallium/drivers/llvmpipe/lp_tex_sample.c      |    2 +
 8 files changed, 67 insertions(+), 75 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..c5b48b5 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -1742,39 +1742,27 @@ 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)
 {
    LLVMValueRef lod;
    LLVMValueRef size;
+   LLVMValueRef first_level = NULL;
    int dims, i;
-   boolean has_array = FALSE;
+   boolean has_array;
    struct lp_build_context bld_int_vec;
 
+   dims = texture_dims(static_state->target);
+
    switch (static_state->target) {
-   case PIPE_TEXTURE_1D:
-   case PIPE_BUFFER:
-      dims = 1;
-      break;
    case PIPE_TEXTURE_1D_ARRAY:
-      dims = 1;
-      has_array = TRUE;
-      break;
-   case PIPE_TEXTURE_2D:
-   case PIPE_TEXTURE_CUBE:
-   case PIPE_TEXTURE_RECT:
-      dims = 2;
-      break;
-   case PIPE_TEXTURE_3D:
-      dims = 3;
-      break;
    case PIPE_TEXTURE_2D_ARRAY:
-      dims = 2;
       has_array = TRUE;
       break;
    default:
-      assert(0);
-      return;
+      has_array = FALSE;
+      break;
    }
 
    assert(!int_type.floating);
@@ -1782,7 +1770,6 @@ lp_build_size_query_soa(struct gallivm_state *gallivm,
    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 +1779,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 +1803,43 @@ 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)
+    */
+
    for (i = 0; i < dims + (has_array ? 1 : 0); i++) {
       sizes_out[i] = lp_build_extract_broadcast(gallivm, bld_int_vec.type, int_type,
                                                 size,
                                                 lp_build_const_int32(gallivm, i));
    }
+
+   /*
+    * if there's no explicit_lod (buffers, rects) queries requiring nr of
+    * mips would be illegal.
+    */
+   if (need_nr_mips && explicit_lod) {
+      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->level_zero_only) {
+         num_levels = bld_int_scalar.one;
+      }
+      else {
+         LLVMValueRef last_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);
+      }
+      sizes_out[3] = lp_build_broadcast(gallivm, lp_build_vec_type(gallivm, int_type),
+                                        num_levels);
+   }
 }
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..52a60dd 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -1621,69 +1621,35 @@ 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)
 {
    LLVMValueRef explicit_lod;
-   unsigned num_coords, has_lod;
+   unsigned has_lod;
    unsigned i;
 
    switch (inst->Texture.Texture) {
-   case TGSI_TEXTURE_1D:
-   case TGSI_TEXTURE_SHADOW1D:
-      num_coords = 1;
-      has_lod = 1;
-      break;
-   case TGSI_TEXTURE_2D:
-   case TGSI_TEXTURE_SHADOW2D:
-   case TGSI_TEXTURE_CUBE:
-   case TGSI_TEXTURE_SHADOWCUBE:
-   case TGSI_TEXTURE_1D_ARRAY:
-   case TGSI_TEXTURE_SHADOW1D_ARRAY:
-      num_coords = 2;
-      has_lod = 1;
-      break;
-   case TGSI_TEXTURE_3D:
-// case TGSI_TEXTURE_CUBE_ARRAY:
-// case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
-   case TGSI_TEXTURE_2D_ARRAY:
-   case TGSI_TEXTURE_SHADOW2D_ARRAY:
-      num_coords = 3;
-      has_lod = 1;
-      break;
-
    case TGSI_TEXTURE_BUFFER:
-      num_coords = 1;
-      has_lod = 0;
-      break;
-
    case TGSI_TEXTURE_RECT:
    case TGSI_TEXTURE_SHADOWRECT:
-// case TGSI_TEXTURE_2D_MS:
-      num_coords = 2;
       has_lod = 0;
       break;
-
-// case TGSI_TEXTURE_2D_MS_ARRAY:
-//    num_coords = 3;
-//    has_lod = 0;
-//    break;
-
    default:
-      assert(0);
-      return;
+      has_lod = 1;
+      break;
    }
 
    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;
+      for (i = 0; i < 4; i++)
+         sizes_out[i] = bld->bld_base.int_bld.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;
 
@@ -1691,6 +1657,7 @@ emit_txq( struct lp_build_tgsi_soa_context *bld,
                                  bld->bld_base.base.gallivm,
                                  bld->bld_base.int_bld.type,
                                  inst->Src[1].Register.Index,
+                                 is_sviewinfo,
                                  explicit_lod,
                                  sizes_out);
 }
@@ -2078,7 +2045,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 +2141,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/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
index 458bc69..f87cf4c 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -293,7 +293,10 @@ tgsi_opcode_infer_src_type( uint opcode )
    case TGSI_OPCODE_USHR:
    case TGSI_OPCODE_SHL:
    case TGSI_OPCODE_TXQ:
+   case TGSI_OPCODE_SVIEWINFO:
    case TGSI_OPCODE_TXF:
+   case TGSI_OPCODE_SAMPLE_I:
+   case TGSI_OPCODE_SAMPLE_I_MS:
       return TGSI_TYPE_UNSIGNED;
    case TGSI_OPCODE_MOD:
    case TGSI_OPCODE_I2F:
@@ -343,6 +346,7 @@ tgsi_opcode_infer_dst_type( uint opcode )
    case TGSI_OPCODE_SHL:
    case TGSI_OPCODE_TXQ:
    case TGSI_OPCODE_TXQ_LZ:
+   case TGSI_OPCODE_SVIEWINFO:
       return TGSI_TYPE_UNSIGNED;
    case TGSI_OPCODE_F2I:
    case TGSI_OPCODE_IDIV:
diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst
index 548a9a3..e0a65f7 100644
--- a/src/gallium/docs/source/tgsi.rst
+++ b/src/gallium/docs/source/tgsi.rst
@@ -1435,7 +1435,7 @@ instructions. If in doubt double check Direct3D documentation.
 
 .. opcode:: SVIEWINFO - query the dimensions of a given sampler view.
                dst receives width, height, depth or array size and
-               number of mipmap levels. The dst can have a writemask
+               number of mipmap levels as int4. The dst can have a writemask
                which will specify what info is the caller interested
                in.
                SVIEWINFO dst, src_mip_level, sampler_view
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