gallivm: fix up size queries for dx10 sviewinfo opcode

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.

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
This commit is contained in:
Roland Scheidegger 2013-02-05 13:37:57 -08:00
parent 0a8043bb76
commit 614982d320
8 changed files with 67 additions and 75 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
};

View File

@ -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

View File

@ -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:

View File

@ -1444,7 +1444,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

View File

@ -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);
}