From 614982d320985c04e247293b54b66d7df5c19004 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Tue, 5 Feb 2013 13:37:57 -0800 Subject: [PATCH] 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 --- src/gallium/auxiliary/draw/draw_llvm_sample.c | 2 + src/gallium/auxiliary/gallivm/lp_bld_sample.h | 1 + .../auxiliary/gallivm/lp_bld_sample_soa.c | 64 +++++++++++------- src/gallium/auxiliary/gallivm/lp_bld_tgsi.h | 1 + .../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 03a25921d65..e51e01101f6 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 77ce00869be..f5022167123 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 778400af5f0..c5b48b52da3 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 837394fb890..3446a8fd46d 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 5eeaaf4ed98..52a60dd43b6 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 94b6f60ca89..f8a3cb665f9 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 5f03f324535..31b679621da 100644 --- a/src/gallium/docs/source/tgsi.rst +++ b/src/gallium/docs/source/tgsi.rst @@ -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 diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c index 69ac8886547..df2a610027c 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); } -- 2.30.2