From 5d10d757276a599a60a68b88b21087b5824a8df7 Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Thu, 17 May 2012 16:48:54 +0200 Subject: [PATCH] llvmpipe: Implement TXQ. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Piglits test for fragment shaders pass, vertex shaders fail. The actual failure seems to be in the interpolators, and not the textureSize query. Signed-off-by: Olivier Galibert Reviewed-by: Roland Scheidegger Reviewed-by: José Fonseca --- src/gallium/auxiliary/draw/draw_llvm_sample.c | 23 +++++ src/gallium/auxiliary/gallivm/lp_bld_sample.c | 7 +- src/gallium/auxiliary/gallivm/lp_bld_sample.h | 14 +++ .../auxiliary/gallivm/lp_bld_sample_soa.c | 73 ++++++++++++++++ src/gallium/auxiliary/gallivm/lp_bld_tgsi.h | 7 ++ .../auxiliary/gallivm/lp_bld_tgsi_soa.c | 86 +++++++++++++++++++ src/gallium/drivers/llvmpipe/lp_tex_sample.c | 23 +++++ 7 files changed, 227 insertions(+), 6 deletions(-) diff --git a/src/gallium/auxiliary/draw/draw_llvm_sample.c b/src/gallium/auxiliary/draw/draw_llvm_sample.c index 8af34617353..0a8b3bc535f 100644 --- a/src/gallium/auxiliary/draw/draw_llvm_sample.c +++ b/src/gallium/auxiliary/draw/draw_llvm_sample.c @@ -195,6 +195,28 @@ draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, } +/** + * Fetch the texture size. + */ +static void +draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base, + struct gallivm_state *gallivm, + unsigned unit, + LLVMValueRef explicit_lod, /* optional */ + LLVMValueRef *sizes_out) +{ + struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base; + + assert(unit < PIPE_MAX_VERTEX_SAMPLERS); + + lp_build_size_query_soa(gallivm, + &sampler->dynamic_state.static_state[unit], + &sampler->dynamic_state.base, + unit, + explicit_lod, + sizes_out); +} + struct lp_build_sampler_soa * draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, LLVMValueRef context_ptr) @@ -207,6 +229,7 @@ draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, sampler->base.destroy = draw_llvm_sampler_soa_destroy; sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel; + sampler->base.emit_size_query = draw_llvm_sampler_soa_emit_size_query; sampler->dynamic_state.base.width = draw_llvm_texture_width; sampler->dynamic_state.base.height = draw_llvm_texture_height; sampler->dynamic_state.base.depth = draw_llvm_texture_depth; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index c6d4f1bcc28..2ffd9b8bfc3 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -51,11 +51,6 @@ */ #define BRILINEAR_FACTOR 2 -static LLVMValueRef -lp_build_minify(struct lp_build_context *bld, - LLVMValueRef base_size, - LLVMValueRef level); - /** * Does the given texture wrap mode allow sampling the texture border color? * XXX maybe move this into gallium util code. @@ -670,7 +665,7 @@ lp_build_get_const_mipmap_level(struct lp_build_sample_context *bld, * Codegen equivalent for u_minify(). * Return max(1, base_size >> level); */ -static LLVMValueRef +LLVMValueRef lp_build_minify(struct lp_build_context *bld, LLVMValueRef base_size, LLVMValueRef level) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index a71e656fe0e..8ccba2ca09e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -404,9 +404,23 @@ lp_build_sample_soa(struct gallivm_state *gallivm, LLVMValueRef explicit_lod, LLVMValueRef texel_out[4]); +void +lp_build_size_query_soa(struct gallivm_state *gallivm, + const struct lp_sampler_static_state *static_state, + struct lp_sampler_dynamic_state *dynamic_state, + unsigned unit, + LLVMValueRef explicit_lod, + LLVMValueRef *sizes_out); + void lp_build_sample_nop(struct gallivm_state *gallivm, struct lp_type type, LLVMValueRef texel_out[4]); +LLVMValueRef +lp_build_minify(struct lp_build_context *bld, + LLVMValueRef base_size, + LLVMValueRef level); + + #endif /* LP_BLD_SAMPLE_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index 4ea7b4bd8a2..73dc3e77083 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -35,6 +35,7 @@ #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "pipe/p_shader_tokens.h" #include "util/u_debug.h" #include "util/u_dump.h" #include "util/u_memory.h" @@ -1277,3 +1278,75 @@ lp_build_sample_soa(struct gallivm_state *gallivm, apply_sampler_swizzle(&bld, texel_out); } + +void +lp_build_size_query_soa(struct gallivm_state *gallivm, + const struct lp_sampler_static_state *static_state, + struct lp_sampler_dynamic_state *dynamic_state, + unsigned unit, + LLVMValueRef explicit_lod, + LLVMValueRef *sizes_out) +{ + LLVMValueRef lod; + LLVMValueRef size; + int dims, i; + struct lp_build_context bld_int_vec; + + switch (static_state->target) { + case PIPE_TEXTURE_1D: + case PIPE_BUFFER: + dims = 1; + break; + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_CUBE: + case PIPE_TEXTURE_RECT: + dims = 2; + break; + case PIPE_TEXTURE_3D: + dims = 3; + break; + + default: + assert(0); + return; + } + + lp_build_context_init(&bld_int_vec, gallivm, lp_type_int_vec(32)); + + 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, unit); + lod = lp_build_broadcast_scalar(&bld_int_vec, + LLVMBuildAdd(gallivm->builder, lod, first_level, "lod")); + + } else { + lod = bld_int_vec.zero; + } + + size = bld_int_vec.undef; + + size = LLVMBuildInsertElement(gallivm->builder, size, + dynamic_state->width(dynamic_state, gallivm, unit), + lp_build_const_int32(gallivm, 0), ""); + + if (dims >= 2) { + size = LLVMBuildInsertElement(gallivm->builder, size, + dynamic_state->height(dynamic_state, gallivm, unit), + lp_build_const_int32(gallivm, 1), ""); + } + + if (dims >= 3) { + size = LLVMBuildInsertElement(gallivm->builder, size, + dynamic_state->depth(dynamic_state, gallivm, unit), + lp_build_const_int32(gallivm, 2), ""); + } + + size = lp_build_minify(&bld_int_vec, size, lod); + + for (i=0; i < dims; i++) { + sizes_out[i] = lp_build_extract_broadcast(gallivm, bld_int_vec.type, bld_int_vec.type, + size, + lp_build_const_int32(gallivm, i)); + } +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h index 773c679a4d8..141e799c4e4 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h @@ -170,6 +170,13 @@ struct lp_build_sampler_soa LLVMValueRef lod_bias, /* optional */ LLVMValueRef explicit_lod, /* optional */ LLVMValueRef *texel); + + void + (*emit_size_query)( const struct lp_build_sampler_soa *sampler, + struct gallivm_state *gallivm, + unsigned unit, + 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 cca7ef5f89a..a9d69a3259e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -1209,6 +1209,80 @@ emit_tex( struct lp_build_tgsi_soa_context *bld, texel); } +static void +emit_txq( struct lp_build_tgsi_soa_context *bld, + const struct tgsi_full_instruction *inst, + LLVMValueRef *sizes_out) +{ + LLVMValueRef explicit_lod; + unsigned num_coords, has_lod; + unsigned i; + + switch (inst->Texture.Texture) { + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWCUBE: + num_coords = 1; + has_lod = 1; + break; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_CUBE: + 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; + } + + 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; + return; + } + + if (has_lod) + explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 2 ); + else + explicit_lod = NULL; + + bld->sampler->emit_size_query(bld->sampler, + bld->bld_base.base.gallivm, + inst->Src[1].Register.Index, + explicit_lod, + sizes_out); +} + static boolean near_end_of_shader(struct lp_build_tgsi_soa_context *bld, int pc) @@ -1584,6 +1658,17 @@ txp_emit( emit_data->output); } +static void +txq_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base); + + emit_txq(bld, emit_data->inst, emit_data->output); +} + static void cal_emit( const struct lp_build_tgsi_action * action, @@ -1954,6 +2039,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm, bld.bld_base.op_actions[TGSI_OPCODE_TXD].emit = txd_emit; bld.bld_base.op_actions[TGSI_OPCODE_TXL].emit = txl_emit; bld.bld_base.op_actions[TGSI_OPCODE_TXP].emit = txp_emit; + bld.bld_base.op_actions[TGSI_OPCODE_TXQ].emit = txq_emit; lp_exec_mask_init(&bld.exec_mask, &bld.bld_base.base); diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c index ccc139603ee..daa96f20c7e 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c @@ -204,6 +204,28 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, texel); } +/** + * Fetch the texture size. + */ +static void +lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base, + struct gallivm_state *gallivm, + unsigned unit, + LLVMValueRef explicit_lod, /* optional */ + LLVMValueRef *sizes_out) +{ + struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base; + + assert(unit < PIPE_MAX_SAMPLERS); + + lp_build_size_query_soa(gallivm, + &sampler->dynamic_state.static_state[unit], + &sampler->dynamic_state.base, + unit, + explicit_lod, + sizes_out); +} + struct lp_build_sampler_soa * lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, @@ -217,6 +239,7 @@ lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, sampler->base.destroy = lp_llvm_sampler_soa_destroy; sampler->base.emit_fetch_texel = lp_llvm_sampler_soa_emit_fetch_texel; + sampler->base.emit_size_query = lp_llvm_sampler_soa_emit_size_query; sampler->dynamic_state.base.width = lp_llvm_texture_width; sampler->dynamic_state.base.height = lp_llvm_texture_height; sampler->dynamic_state.base.depth = lp_llvm_texture_depth; -- 2.30.2