From c5a27b5939427bdc95c926b450ed3de1ff4baafb Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Sat, 8 Jan 2011 23:49:23 -0800 Subject: glsl: Change texel offsets to a single vector rvalue. Having these as actual integer values makes it difficult to implement the texture*Offset built-in functions, since the offset is actually a function parameter (which doesn't have a constant value). The original rationale was that some hardware needs these offset baked into the instruction opcode. However, at least i965 should be able to support non-constant offsets. Others should be able to rely on inlining and constant propagation. --- src/glsl/builtins/tools/texture_builtins.py | 2 +- src/glsl/ir.h | 26 +++++++++++++------------- src/glsl/ir_clone.cpp | 4 ++-- src/glsl/ir_hv_accept.cpp | 6 ++++++ src/glsl/ir_print_visitor.cpp | 10 +++++++++- src/glsl/ir_reader.cpp | 21 +++++++++------------ src/glsl/ir_rvalue_visitor.cpp | 1 + src/glsl/opt_tree_grafting.cpp | 1 + 8 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/glsl/builtins/tools/texture_builtins.py b/src/glsl/builtins/tools/texture_builtins.py index 8bf708b5aa..d7ac4d3e85 100755 --- a/src/glsl/builtins/tools/texture_builtins.py +++ b/src/glsl/builtins/tools/texture_builtins.py @@ -64,7 +64,7 @@ def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0 print "(var_ref P)", # Offset - print "(0 0 0)", + print "0", if tex_inst != "txf": # Projective divisor diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 1fce272756..878c1779d8 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1190,21 +1190,21 @@ enum ir_texture_opcode { * selected from \c ir_texture_opcodes. In the printed IR, these will * appear as: * - * Texel offset - * | Projection divisor - * | | Shadow comparitor - * | | | - * v v v - * (tex (sampler) (coordinate) (0 0 0) (1) ( )) - * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias)) - * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod)) - * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy)) - * (txf (sampler) (coordinate) (0 0 0) (lod)) + * Texel offset (0 or an expression) + * | Projection divisor + * | | Shadow comparitor + * | | | + * v v v + * (tex 0 1 ( )) + * (txb 0 1 ( ) ) + * (txl 0 1 ( ) ) + * (txd 0 1 ( ) (dPdx dPdy)) + * (txf 0 ) */ class ir_texture : public ir_rvalue { public: ir_texture(enum ir_texture_opcode op) - : op(op), projector(NULL), shadow_comparitor(NULL) + : op(op), projector(NULL), shadow_comparitor(NULL), offset(NULL) { this->ir_type = ir_type_texture; } @@ -1258,8 +1258,8 @@ public: */ ir_rvalue *shadow_comparitor; - /** Explicit texel offsets. */ - signed char offsets[3]; + /** Texel offset. */ + ir_rvalue *offset; union { ir_rvalue *lod; /**< Floating point LOD */ diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 20a59b1e43..2c0574dc6b 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -217,8 +217,8 @@ ir_texture::clone(void *mem_ctx, struct hash_table *ht) const new_tex->shadow_comparitor = this->shadow_comparitor->clone(mem_ctx, ht); } - for (int i = 0; i < 3; i++) - new_tex->offsets[i] = this->offsets[i]; + if (this->offset != NULL) + new_tex->offset = this->offset->clone(mem_ctx, ht); switch (this->op) { case ir_tex: diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp index be8b36a7cf..4a607dc874 100644 --- a/src/glsl/ir_hv_accept.cpp +++ b/src/glsl/ir_hv_accept.cpp @@ -187,6 +187,12 @@ ir_texture::accept(ir_hierarchical_visitor *v) return (s == visit_continue_with_parent) ? visit_continue : s; } + if (this->offset) { + s = this->offset->accept(v); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + } + switch (this->op) { case ir_tex: break; diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index d0373cb631..630850048f 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -192,7 +192,15 @@ void ir_print_visitor::visit(ir_texture *ir) ir->coordinate->accept(this); - printf(" (%d %d %d) ", ir->offsets[0], ir->offsets[1], ir->offsets[2]); + printf(" "); + + if (ir->offset != NULL) { + ir->offset->accept(this); + } else { + printf("0"); + } + + printf(" "); if (ir->op != ir_txf) { if (ir->projector) diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index bff75ed0e8..9ed3d23508 100644 --- a/src/glsl/ir_reader.cpp +++ b/src/glsl/ir_reader.cpp @@ -869,7 +869,7 @@ ir_reader::read_texture(s_expression *expr) s_symbol *tag = NULL; s_expression *s_sampler = NULL; s_expression *s_coord = NULL; - s_list *s_offset = NULL; + s_expression *s_offset = NULL; s_expression *s_proj = NULL; s_list *s_shadow = NULL; s_expression *s_lod = NULL; @@ -915,18 +915,15 @@ ir_reader::read_texture(s_expression *expr) return NULL; } - // Read texel offset, i.e. (0 0 0) - s_int *offset_x; - s_int *offset_y; - s_int *offset_z; - s_pattern offset_pat[] = { offset_x, offset_y, offset_z }; - if (!MATCH(s_offset, offset_pat)) { - ir_read_error(s_offset, "expected ( )"); - return NULL; + // Read texel offset - either 0 or an rvalue. + s_int *si_offset = SX_AS_INT(s_offset); + if (si_offset == NULL || si_offset->value() != 0) { + tex->offset = read_rvalue(s_offset); + if (tex->offset == NULL) { + ir_read_error(s_offset, "expected 0 or an expression"); + return NULL; + } } - tex->offsets[0] = offset_x->value(); - tex->offsets[1] = offset_y->value(); - tex->offsets[2] = offset_z->value(); if (op != ir_txf) { s_int *proj_as_int = SX_AS_INT(s_proj); diff --git a/src/glsl/ir_rvalue_visitor.cpp b/src/glsl/ir_rvalue_visitor.cpp index 773bfcfa3e..ed6c7cb6a1 100644 --- a/src/glsl/ir_rvalue_visitor.cpp +++ b/src/glsl/ir_rvalue_visitor.cpp @@ -53,6 +53,7 @@ ir_rvalue_visitor::visit_leave(ir_texture *ir) handle_rvalue(&ir->coordinate); handle_rvalue(&ir->projector); handle_rvalue(&ir->shadow_comparitor); + handle_rvalue(&ir->offset); switch (ir->op) { case ir_tex: diff --git a/src/glsl/opt_tree_grafting.cpp b/src/glsl/opt_tree_grafting.cpp index 9917c045b1..ae77408dbe 100644 --- a/src/glsl/opt_tree_grafting.cpp +++ b/src/glsl/opt_tree_grafting.cpp @@ -245,6 +245,7 @@ ir_tree_grafting_visitor::visit_enter(ir_texture *ir) { if (do_graft(&ir->coordinate) || do_graft(&ir->projector) || + do_graft(&ir->offset) || do_graft(&ir->shadow_comparitor)) return visit_stop; -- cgit v1.2.3