[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