From 5b6890a388d554f06880e88d61c73dcd62c5f141 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jul 2010 19:08:44 -0700 Subject: ir_to_mesa: Add support for structure constants. Fixes: TPPStreamCompiler::assignOperands --- src/mesa/program/ir_to_mesa.cpp | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 1903b8fcf8..20228e0428 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1381,12 +1381,37 @@ ir_to_mesa_visitor::visit(ir_constant *ir) assert(!"FINISHME: array constants"); } + /* Unfortunately, 4 floats is all we can get into + * _mesa_add_unnamed_constant. So, make a temp to store an + * aggregate constant and move each constant value into it. If we + * get lucky, copy propagation will eliminate the extra moves. + */ + + if (ir->type->base_type == GLSL_TYPE_STRUCT) { + ir_to_mesa_src_reg temp_base = get_temp(ir->type); + ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base); + + foreach_iter(exec_list_iterator, iter, ir->components) { + ir_constant *field_value = (ir_constant *)iter.get(); + int size = type_size(field_value->type); + + assert(size > 0); + + field_value->accept(this); + src_reg = this->result; + + for (i = 0; i < (unsigned int)size; i++) { + ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg); + + src_reg.index++; + temp.index++; + } + } + this->result = temp_base; + return; + } + if (ir->type->is_matrix()) { - /* Unfortunately, 4 floats is all we can get into - * _mesa_add_unnamed_constant. So, make a temp to store the - * matrix and move each constant value into it. If we get - * lucky, copy propagation will eliminate the extra moves. - */ ir_to_mesa_src_reg mat = get_temp(glsl_type::vec4_type); ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat); -- cgit v1.2.3 From c91809e1e4a4fa8884e6588159368ea32431ee0e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jul 2010 19:41:23 -0700 Subject: ir_to_mesa: Actually allocate the right size for constant matrix temps. --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 20228e0428..6eceddfb81 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1412,7 +1412,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir) } if (ir->type->is_matrix()) { - ir_to_mesa_src_reg mat = get_temp(glsl_type::vec4_type); + ir_to_mesa_src_reg mat = get_temp(ir->type); ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat); for (i = 0; i < ir->type->matrix_columns; i++) { -- cgit v1.2.3 From 576d01ad8c8b8aa57b4711c98d8e004d4f20fc0b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jul 2010 19:36:53 -0700 Subject: ir_to_mesa: Fix up handling of void function returns. void functions have a type of glsl_type::void_type, not a null type. --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 6eceddfb81..d06b83261c 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1501,7 +1501,7 @@ ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig) break; } - if (sig->return_type) { + if (!sig->return_type->is_void()) { entry->return_reg = get_temp(sig->return_type); } else { entry->return_reg = ir_to_mesa_undef; -- cgit v1.2.3 From 832aad989e3d319a8aaac046aa49df25da134d82 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jul 2010 22:50:29 -0700 Subject: glsl2: Add optimization pass for algebraic simplifications. This cleans up the assembly output of almost all the non-logic tests glsl-algebraic-*. glsl-algebraic-pow-two needs love (basically, flattening to a temporary and squaring it). --- src/glsl/Makefile | 1 + src/glsl/ir.h | 8 + src/glsl/ir_algebraic.cpp | 366 ++++++++++++++++++++++++++++++++++++++++ src/glsl/ir_optimization.h | 3 +- src/glsl/main.cpp | 1 + src/mesa/program/ir_to_mesa.cpp | 1 + 6 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 src/glsl/ir_algebraic.cpp (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/Makefile b/src/glsl/Makefile index 462d49e884..4c85af8906 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -30,6 +30,7 @@ CXX_SOURCES = \ glsl_parser_extras.cpp \ glsl_types.cpp \ hir_field_selection.cpp \ + ir_algebraic.cpp \ ir_basic_block.cpp \ ir_clone.cpp \ ir_constant_expression.cpp \ diff --git a/src/glsl/ir.h b/src/glsl/ir.h index e0f3683a7a..7e8363106d 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -613,7 +613,15 @@ enum ir_expression_operation { ir_binop_greater, ir_binop_lequal, ir_binop_gequal, + /** + * Returns single boolean for whether all components of operands[0] + * equal the components of operands[1]. + */ ir_binop_equal, + /** + * Returns single boolean for whether any component of operands[0] + * is not equal to the corresponding component of operands[1]. + */ ir_binop_nequal, /*@}*/ diff --git a/src/glsl/ir_algebraic.cpp b/src/glsl/ir_algebraic.cpp new file mode 100644 index 0000000000..5b065b086e --- /dev/null +++ b/src/glsl/ir_algebraic.cpp @@ -0,0 +1,366 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_algebraic.cpp + * + * Takes advantage of association, commutivity, and other algebraic + * properties to simplify expressions. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_optimization.h" +#include "glsl_types.h" + +/** + * Visitor class for replacing expressions with ir_constant values. + */ + +class ir_algebraic_visitor : public ir_hierarchical_visitor { +public: + ir_algebraic_visitor() + { + this->progress = false; + } + + virtual ~ir_algebraic_visitor() + { + } + + virtual ir_visitor_status visit_leave(ir_assignment *); + virtual ir_visitor_status visit_leave(ir_call *); + virtual ir_visitor_status visit_leave(ir_dereference_array *); + virtual ir_visitor_status visit_leave(ir_expression *); + virtual ir_visitor_status visit_leave(ir_if *); + virtual ir_visitor_status visit_leave(ir_return *); + virtual ir_visitor_status visit_leave(ir_swizzle *); + virtual ir_visitor_status visit_leave(ir_texture *); + + ir_rvalue *handle_expression(ir_rvalue *in_ir); + + bool progress; +}; + +static bool +is_vec_zero(ir_constant *ir) +{ + int c; + + if (!ir) + return false; + if (!ir->type->is_scalar() && + !ir->type->is_vector()) + return false; + + for (c = 0; c < ir->type->vector_elements; c++) { + switch (ir->type->base_type) { + case GLSL_TYPE_FLOAT: + if (ir->value.f[c] != 0.0) + return false; + break; + case GLSL_TYPE_INT: + if (ir->value.i[c] != 0) + return false; + break; + case GLSL_TYPE_UINT: + if (ir->value.u[c] != 0) + return false; + break; + case GLSL_TYPE_BOOL: + if (ir->value.b[c] != false) + return false; + break; + default: + assert(!"bad base type"); + return false; + } + } + + return true; +} + +static bool +is_vec_one(ir_constant *ir) +{ + int c; + + if (!ir) + return false; + if (!ir->type->is_scalar() && + !ir->type->is_vector()) + return false; + + for (c = 0; c < ir->type->vector_elements; c++) { + switch (ir->type->base_type) { + case GLSL_TYPE_FLOAT: + if (ir->value.f[c] != 1.0) + return false; + break; + case GLSL_TYPE_INT: + if (ir->value.i[c] != 1) + return false; + break; + case GLSL_TYPE_UINT: + if (ir->value.u[c] != 1) + return false; + break; + case GLSL_TYPE_BOOL: + if (ir->value.b[c] != true) + return false; + break; + default: + assert(!"bad base type"); + return false; + } + } + + return true; +} + +ir_rvalue * +ir_algebraic_visitor::handle_expression(ir_rvalue *in_ir) +{ + ir_expression *ir = (ir_expression *)in_ir; + ir_constant *op_const[2] = {NULL, NULL}; + ir_expression *op_expr[2] = {NULL, NULL}; + unsigned int i; + + if (!in_ir) + return NULL; + + if (in_ir->ir_type != ir_type_expression) + return in_ir; + + for (i = 0; i < ir->get_num_operands(); i++) { + if (ir->operands[i]->type->is_matrix()) + return in_ir; + + op_const[i] = ir->operands[i]->constant_expression_value(); + op_expr[i] = ir->operands[i]->as_expression(); + } + + switch (ir->operation) { + case ir_unop_logic_not: + if (op_expr[0] && op_expr[0]->operation == ir_binop_equal) { + this->progress = true; + return new(ir) ir_expression(ir_binop_nequal, + ir->type, + op_expr[0]->operands[0], + op_expr[0]->operands[1]); + } + if (op_expr[0] && op_expr[0]->operation == ir_binop_nequal) { + this->progress = true; + return new(ir) ir_expression(ir_binop_equal, + ir->type, + op_expr[0]->operands[0], + op_expr[0]->operands[1]); + } + break; + + case ir_binop_add: + if (is_vec_zero(op_const[0])) { + this->progress = true; + return ir->operands[1]; + } + if (is_vec_zero(op_const[1])) { + this->progress = true; + return ir->operands[0]; + } + break; + + case ir_binop_sub: + if (is_vec_zero(op_const[0])) { + this->progress = true; + return new(ir) ir_expression(ir_unop_neg, + ir->type, + ir->operands[1], + NULL); + } + if (is_vec_zero(op_const[1])) { + this->progress = true; + return ir->operands[0]; + } + break; + + case ir_binop_mul: + if (is_vec_one(op_const[0])) { + this->progress = true; + return ir->operands[1]; + } + if (is_vec_one(op_const[1])) { + this->progress = true; + return ir->operands[0]; + } + + if (is_vec_zero(op_const[0]) || + is_vec_zero(op_const[1])) { + ir_constant_data zero_data; + memset(&zero_data, 0, sizeof(zero_data)); + + this->progress = true; + return new(ir) ir_constant(ir->type, &zero_data); + } + break; + + case ir_binop_div: + if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) { + this->progress = true; + return new(ir) ir_expression(ir_unop_rcp, + ir->type, + ir->operands[1], + NULL); + } + if (is_vec_one(op_const[1])) { + this->progress = true; + return ir->operands[0]; + } + break; + + case ir_unop_rcp: + if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) { + this->progress = true; + return op_expr[0]->operands[0]; + } + + /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some + * backends, except that some backends will have done sqrt -> + * rcp(rsq(x)) and we don't want to undo it for them. + */ + + /* As far as we know, all backends are OK with rsq. */ + if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) { + this->progress = true; + return new(ir) ir_expression(ir_unop_rsq, + ir->type, + op_expr[0]->operands[0], + NULL); + } + + break; + + default: + break; + } + + return in_ir; +} + +ir_visitor_status +ir_algebraic_visitor::visit_leave(ir_expression *ir) +{ + unsigned int operand; + + for (operand = 0; operand < ir->get_num_operands(); operand++) { + ir->operands[operand] = handle_expression(ir->operands[operand]); + } + + return visit_continue; +} + +ir_visitor_status +ir_algebraic_visitor::visit_leave(ir_texture *ir) +{ + ir->coordinate = handle_expression(ir->coordinate); + ir->projector = handle_expression(ir->projector); + ir->shadow_comparitor = handle_expression(ir->shadow_comparitor); + + switch (ir->op) { + case ir_tex: + break; + case ir_txb: + ir->lod_info.bias = handle_expression(ir->lod_info.bias); + break; + case ir_txf: + case ir_txl: + ir->lod_info.lod = handle_expression(ir->lod_info.lod); + break; + case ir_txd: + ir->lod_info.grad.dPdx = handle_expression(ir->lod_info.grad.dPdx); + ir->lod_info.grad.dPdy = handle_expression(ir->lod_info.grad.dPdy); + break; + } + + return visit_continue; +} + +ir_visitor_status +ir_algebraic_visitor::visit_leave(ir_swizzle *ir) +{ + ir->val = handle_expression(ir->val); + return visit_continue; +} + +ir_visitor_status +ir_algebraic_visitor::visit_leave(ir_dereference_array *ir) +{ + ir->array_index = handle_expression(ir->array_index); + return visit_continue; +} + +ir_visitor_status +ir_algebraic_visitor::visit_leave(ir_assignment *ir) +{ + ir->rhs = handle_expression(ir->rhs); + ir->condition = handle_expression(ir->condition); + return visit_continue; +} + +ir_visitor_status +ir_algebraic_visitor::visit_leave(ir_call *ir) +{ + foreach_iter(exec_list_iterator, iter, *ir) { + ir_rvalue *param = (ir_rvalue *)iter.get(); + ir_rvalue *new_param = handle_expression(param); + + if (new_param != param) { + param->replace_with(new_param); + } + } + return visit_continue; +} + +ir_visitor_status +ir_algebraic_visitor::visit_leave(ir_return *ir) +{ + ir->value = handle_expression(ir->value);; + return visit_continue; +} + +ir_visitor_status +ir_algebraic_visitor::visit_leave(ir_if *ir) +{ + ir->condition = handle_expression(ir->condition); + return visit_continue; +} + + +bool +do_algebraic(exec_list *instructions) +{ + ir_algebraic_visitor v; + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 06cb4d22ca..4f39565e5f 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -23,11 +23,12 @@ /** - * \file ir_dead_code.h + * \file ir_optimization.h * * Prototypes for optimization passes to be called by the compiler and drivers. */ +bool do_algebraic(exec_list *instructions); bool do_constant_folding(exec_list *instructions); bool do_constant_variable(exec_list *instructions); bool do_constant_variable_unlinked(exec_list *instructions); diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index 5c0f6475e0..b62902278c 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -165,6 +165,7 @@ compile_shader(struct gl_shader *shader) progress = do_dead_code_unlinked(state, shader->ir) || progress; progress = do_constant_variable_unlinked(shader->ir) || progress; progress = do_constant_folding(shader->ir) || progress; + progress = do_algebraic(shader->ir) || progress; progress = do_vec_index_to_swizzle(shader->ir) || progress; progress = do_vec_index_to_cond_assign(shader->ir) || progress; progress = do_swizzle_swizzle(shader->ir) || progress; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index d06b83261c..2fd0507c2f 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2240,6 +2240,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) progress = do_dead_code_unlinked(state, shader->ir) || progress; progress = do_constant_variable_unlinked(shader->ir) || progress; progress = do_constant_folding(shader->ir) || progress; + progress = do_algebraic(shader->ir) || progress; progress = do_if_return(shader->ir) || progress; if (ctx->Shader.EmitNoIfs) progress = do_if_to_cond_assign(shader->ir) || progress; -- cgit v1.2.3 From fdbaca931a504a70d6fec54e2f85caac6281377d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jul 2010 10:08:38 -0700 Subject: ir_to_mesa: Fix stray "break" that broke functions of >1 argument. --- src/mesa/program/ir_to_mesa.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 2fd0507c2f..defacc7fdc 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1498,7 +1498,6 @@ ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig) this->variables.push_tail(storage); this->next_temp += type_size(param->type); - break; } if (!sig->return_type->is_void()) { -- cgit v1.2.3 From 9a770ee49f8cb82653bb5c1976f7751d9a6b801e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jul 2010 10:39:40 -0700 Subject: ir_to_mesa: Set the swizzle on constant struct src regs. MESA_GLSL=nopt now produces believable output for glsl-fs-raytrace. --- src/mesa/program/ir_to_mesa.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index defacc7fdc..5cc999c2e3 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1389,6 +1389,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir) if (ir->type->base_type == GLSL_TYPE_STRUCT) { ir_to_mesa_src_reg temp_base = get_temp(ir->type); + temp_base.swizzle = SWIZZLE_NOOP; ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base); foreach_iter(exec_list_iterator, iter, ir->components) { -- cgit v1.2.3 From 66d4c65ee2c311ea0c71c39a28456d0c11798d6b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jul 2010 11:28:26 -0700 Subject: glsl2: Make the dead code handler make its own talloc context. This way, we don't need to pass in a parse state, and the context doesn't grow with the number of passes through optimization. --- src/glsl/ir_dead_code.cpp | 12 ++++++------ src/glsl/ir_optimization.h | 6 ++---- src/glsl/main.cpp | 2 +- src/mesa/program/ir_to_mesa.cpp | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/ir_dead_code.cpp b/src/glsl/ir_dead_code.cpp index ea78107f49..4804407bdc 100644 --- a/src/glsl/ir_dead_code.cpp +++ b/src/glsl/ir_dead_code.cpp @@ -146,13 +146,12 @@ ir_dead_code_visitor::visit_leave(ir_assignment *ir) * for usage on an unlinked instruction stream. */ bool -do_dead_code(struct _mesa_glsl_parse_state *state, - exec_list *instructions) +do_dead_code(exec_list *instructions) { ir_dead_code_visitor v; bool progress = false; - v.mem_ctx = state; + v.mem_ctx = talloc_new(NULL); v.run(instructions); foreach_iter(exec_list_iterator, iter, v.variable_list) { @@ -188,6 +187,8 @@ do_dead_code(struct _mesa_glsl_parse_state *state, progress = true; } } + talloc_free(v.mem_ctx); + return progress; } @@ -199,8 +200,7 @@ do_dead_code(struct _mesa_glsl_parse_state *state, * with global scope. */ bool -do_dead_code_unlinked(struct _mesa_glsl_parse_state *state, - exec_list *instructions) +do_dead_code_unlinked(exec_list *instructions) { bool progress = false; @@ -211,7 +211,7 @@ do_dead_code_unlinked(struct _mesa_glsl_parse_state *state, foreach_iter(exec_list_iterator, sigiter, *f) { ir_function_signature *sig = (ir_function_signature *) sigiter.get(); - if (do_dead_code(state, &sig->body)) + if (do_dead_code(&sig->body)) progress = true; } } diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 4f39565e5f..5dbb025d35 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -33,11 +33,9 @@ bool do_constant_folding(exec_list *instructions); bool do_constant_variable(exec_list *instructions); bool do_constant_variable_unlinked(exec_list *instructions); bool do_copy_propagation(exec_list *instructions); -bool do_dead_code(struct _mesa_glsl_parse_state *state, - exec_list *instructions); +bool do_dead_code(exec_list *instructions); bool do_dead_code_local(exec_list *instructions); -bool do_dead_code_unlinked(struct _mesa_glsl_parse_state *state, - exec_list *instructions); +bool do_dead_code_unlinked(exec_list *instructions); bool do_div_to_mul_rcp(exec_list *instructions); bool do_function_inlining(exec_list *instructions); bool do_if_return(exec_list *instructions); diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index b62902278c..08b133f124 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -162,7 +162,7 @@ compile_shader(struct gl_shader *shader) progress = do_if_simplification(shader->ir) || progress; progress = do_copy_propagation(shader->ir) || progress; progress = do_dead_code_local(shader->ir) || progress; - progress = do_dead_code_unlinked(state, shader->ir) || progress; + progress = do_dead_code_unlinked(shader->ir) || progress; progress = do_constant_variable_unlinked(shader->ir) || progress; progress = do_constant_folding(shader->ir) || progress; progress = do_algebraic(shader->ir) || progress; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 5cc999c2e3..409b6d7288 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2237,7 +2237,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) progress = do_if_simplification(shader->ir) || progress; progress = do_copy_propagation(shader->ir) || progress; progress = do_dead_code_local(shader->ir) || progress; - progress = do_dead_code_unlinked(state, shader->ir) || progress; + progress = do_dead_code_unlinked(shader->ir) || progress; progress = do_constant_variable_unlinked(shader->ir) || progress; progress = do_constant_folding(shader->ir) || progress; progress = do_algebraic(shader->ir) || progress; -- cgit v1.2.3 From 20c074ae28b310348a6a1920ad0ddf1e5cbb7a46 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jul 2010 11:58:32 -0700 Subject: ir_to_mesa: Add support for array constants. Fixes: glsl1-GLSL 1.20 array constructor 1 glsl1-GLSL 1.20 array constructor 2 glsl1-GLSL 1.20 array.length() glsl1-GLSL 1.20 const array constructor 1 glsl1-GLSL 1.20 const array constructor 2 --- src/mesa/program/ir_to_mesa.cpp | 48 ++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 17 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 409b6d7288..bd79913dcf 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -518,19 +518,21 @@ ir_to_mesa_visitor::get_temp(const glsl_type *type) int swizzle[4]; int i; - assert(!type->is_array()); - src_reg.file = PROGRAM_TEMPORARY; src_reg.index = next_temp; src_reg.reladdr = NULL; next_temp += type_size(type); - for (i = 0; i < type->vector_elements; i++) - swizzle[i] = i; - for (; i < 4; i++) - swizzle[i] = type->vector_elements - 1; - src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], - swizzle[2], swizzle[3]); + if (type->is_array() || type->is_record()) { + src_reg.swizzle = SWIZZLE_NOOP; + } else { + for (i = 0; i < type->vector_elements; i++) + swizzle[i] = i; + for (; i < 4; i++) + swizzle[i] = type->vector_elements - 1; + src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], + swizzle[2], swizzle[3]); + } src_reg.negate = 0; return src_reg; @@ -1329,8 +1331,6 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) struct ir_to_mesa_src_reg r; int i; - assert(!ir->lhs->type->is_array()); - ir->rhs->accept(this); r = this->result; @@ -1375,12 +1375,6 @@ ir_to_mesa_visitor::visit(ir_constant *ir) GLfloat *values = stack_vals; unsigned int i; - if (ir->type->is_array()) { - ir->print(); - printf("\n"); - assert(!"FINISHME: array constants"); - } - /* Unfortunately, 4 floats is all we can get into * _mesa_add_unnamed_constant. So, make a temp to store an * aggregate constant and move each constant value into it. If we @@ -1389,7 +1383,6 @@ ir_to_mesa_visitor::visit(ir_constant *ir) if (ir->type->base_type == GLSL_TYPE_STRUCT) { ir_to_mesa_src_reg temp_base = get_temp(ir->type); - temp_base.swizzle = SWIZZLE_NOOP; ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base); foreach_iter(exec_list_iterator, iter, ir->components) { @@ -1412,6 +1405,27 @@ ir_to_mesa_visitor::visit(ir_constant *ir) return; } + if (ir->type->is_array()) { + ir_to_mesa_src_reg temp_base = get_temp(ir->type); + ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base); + int size = type_size(ir->type->fields.array); + + assert(size > 0); + + for (i = 0; i < ir->type->length; i++) { + ir->array_elements[i]->accept(this); + src_reg = this->result; + for (int j = 0; j < size; j++) { + ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg); + + src_reg.index++; + temp.index++; + } + } + this->result = temp_base; + return; + } + if (ir->type->is_matrix()) { ir_to_mesa_src_reg mat = get_temp(ir->type); ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat); -- cgit v1.2.3 From 9a670c2e9b7e07ba43d175f3bfb23951296794c4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jul 2010 15:10:38 -0700 Subject: ir_to_mesa: Provide a restricted type size to _mesa_add_uniform. Fixes: glsl-uniform-out-of-bounds. --- src/mesa/program/ir_to_mesa.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index bd79913dcf..fe0c19acea 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1061,6 +1061,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) ir_to_mesa_src_reg src_reg; variable_storage *entry = find_variable_storage(ir->var); unsigned int loc; + int len; if (!entry) { switch (ir->var->mode) { @@ -1089,9 +1090,17 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) assert(ir->var->type->gl_type != 0 && ir->var->type->gl_type != GL_INVALID_ENUM); + + if (ir->var->type->is_vector() || + ir->var->type->is_scalar()) { + len = ir->var->type->vector_elements; + } else { + len = type_size(ir->var->type) * 4; + } + loc = _mesa_add_uniform(this->prog->Parameters, ir->var->name, - type_size(ir->var->type) * 4, + len, ir->var->type->gl_type, NULL); -- cgit v1.2.3 From dc27e7356952984d023e05fef90d0f8c4bb07a09 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 28 Jul 2010 08:13:53 -0700 Subject: ir_to_mesa: Add remaining state variable (builtin uniforms) support. Fixes: glsl1-GL state variable reference (diffuse product) glsl1-GL state variable reference (gl_FrontMaterial.ambient) glsl1-GL state variable reference (gl_LightSource[0].diffuse) glsl1-GL state variable reference (point attenuation) glsl1-GL state variable reference (point size) glsl1-linear fog --- src/mesa/program/ir_to_mesa.cpp | 201 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index fe0c19acea..c53381e29d 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -946,6 +946,181 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir) this->result = src_reg; } +static const struct { + const char *name; + const char *field; + int tokens[STATE_LENGTH]; + int swizzle; + bool array_indexed; +} statevars[] = { + {"gl_DepthRange", "near", + {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX}, + {"gl_DepthRange", "far", + {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY}, + {"gl_DepthRange", "diff", + {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ}, + + {"gl_ClipPlane", NULL, + {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW, true} +, + {"gl_Point", "size", + {STATE_POINT_SIZE}, SWIZZLE_XXXX}, + {"gl_Point", "sizeMin", + {STATE_POINT_SIZE}, SWIZZLE_YYYY}, + {"gl_Point", "sizeMax", + {STATE_POINT_SIZE}, SWIZZLE_ZZZZ}, + {"gl_Point", "fadeThresholdSize", + {STATE_POINT_SIZE}, SWIZZLE_WWWW}, + {"gl_Point", "distanceConstantAttenuation", + {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX}, + {"gl_Point", "distanceLinearAttenuation", + {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY}, + {"gl_Point", "distanceQuadraticAttenuation", + {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ}, + + {"gl_FrontMaterial", "emission", + {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW}, + {"gl_FrontMaterial", "ambient", + {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"gl_FrontMaterial", "diffuse", + {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"gl_FrontMaterial", "specular", + {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, + {"gl_FrontMaterial", "shininess", + {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX}, + + {"gl_BackMaterial", "emission", + {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW}, + {"gl_BackMaterial", "ambient", + {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"gl_BackMaterial", "diffuse", + {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"gl_BackMaterial", "specular", + {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, + {"gl_BackMaterial", "shininess", + {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX}, + + {"gl_LightSource", "ambient", + {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true}, + {"gl_LightSource", "diffuse", + {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true}, + {"gl_LightSource", "specular", + {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true}, + {"gl_LightSource", "position", + {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW, true}, + {"gl_LightSource", "halfVector", + {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW, true}, + {"gl_LightSource", "spotDirection", + {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW, true}, + {"gl_LightSource", "spotCosCutoff", + {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW, true}, + {"gl_LightSource", "spotCutoff", + {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX, true}, + {"gl_LightSource", "spotExponent", + {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW, true}, + {"gl_LightSource", "constantAttenuation", + {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX, true}, + {"gl_LightSource", "linearAttenuation", + {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY, true}, + {"gl_LightSource", "quadraticAttenuation", + {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ, true}, + + {"gl_LightModel", NULL, + {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW}, + + {"gl_FrontLightModelProduct", NULL, + {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW}, + {"gl_BackLightModelProduct", NULL, + {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW}, + + {"gl_FrontLightProduct", "ambient", + {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true}, + {"gl_FrontLightProduct", "diffuse", + {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true}, + {"gl_FrontLightProduct", "specular", + {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true}, + + {"gl_BackLightProduct", "ambient", + {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW, true}, + {"gl_BackLightProduct", "diffuse", + {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, true}, + {"gl_BackLightProduct", "specular", + {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW, true}, + + {"gl_TextureEnvColor", "ambient", + {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW, true}, + + {"gl_EyePlaneS", NULL, + {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW, true}, + {"gl_EyePlaneT", NULL, + {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW, true}, + {"gl_EyePlaneR", NULL, + {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW, true}, + {"gl_EyePlaneQ", NULL, + {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW, true}, + + {"gl_ObjectPlaneS", NULL, + {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW, true}, + {"gl_ObjectPlaneT", NULL, + {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW, true}, + {"gl_ObjectPlaneR", NULL, + {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW, true}, + {"gl_ObjectPlaneQ", NULL, + {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW, true}, + + {"gl_Fog", "color", + {STATE_FOG_COLOR}, SWIZZLE_XYZW}, + {"gl_Fog", "density", + {STATE_FOG_PARAMS}, SWIZZLE_XXXX}, + {"gl_Fog", "start", + {STATE_FOG_PARAMS}, SWIZZLE_YYYY}, + {"gl_Fog", "end", + {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ}, + {"gl_Fog", "scale", + {STATE_FOG_PARAMS}, SWIZZLE_WWWW}, +}; + +static ir_to_mesa_src_reg +get_builtin_uniform_reg(struct gl_program *prog, + const char *name, int array_index, const char *field) +{ + unsigned int i; + ir_to_mesa_src_reg src_reg; + int tokens[STATE_LENGTH]; + + for (i = 0; i < Elements(statevars); i++) { + if (strcmp(statevars[i].name, name) != 0) + continue; + if (!field && statevars[i].field) { + assert(!"FINISHME: whole-structure state var dereference"); + } + if (field && strcmp(statevars[i].field, field) != 0) + continue; + break; + } + + if (i == Elements(statevars)) { + printf("builtin uniform %s%s%s not found\n", + name, + field ? "." : "", + field ? field : ""); + abort(); + } + + memcpy(&tokens, statevars[i].tokens, sizeof(tokens)); + if (statevars[i].array_indexed) + tokens[1] = array_index; + + src_reg.file = PROGRAM_STATE_VAR; + src_reg.index = _mesa_add_state_reference(prog->Parameters, + (gl_state_index *)tokens); + src_reg.swizzle = statevars[i].swizzle; + src_reg.negate = 0; + src_reg.reladdr = false; + + return src_reg; +} + static int add_matrix_ref(struct gl_program *prog, int *tokens) { @@ -1176,6 +1351,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) void ir_to_mesa_visitor::visit(ir_dereference_array *ir) { + ir_variable *var = ir->variable_referenced(); ir_constant *index; ir_to_mesa_src_reg src_reg; ir_dereference_variable *deref_var = ir->array->as_dereference_variable(); @@ -1216,6 +1392,20 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir) return; } + if (strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform && + !var->type->is_matrix()) { + ir_dereference_record *record = NULL; + if (ir->array->ir_type == ir_type_dereference_record) + record = (ir_dereference_record *)ir->array; + + assert(index || !"FINISHME: variable-indexed builtin uniform access"); + + this->result = get_builtin_uniform_reg(prog, + var->name, + index->value.i[0], + record ? record->field : NULL); + } + ir->array->accept(this); src_reg = this->result; @@ -1260,6 +1450,17 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) unsigned int i; const glsl_type *struct_type = ir->record->type; int offset = 0; + ir_variable *var = ir->record->variable_referenced(); + + if (strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform) { + assert(var); + + this->result = get_builtin_uniform_reg(prog, + var->name, + 0, + ir->field); + return; + } ir->record->accept(this); -- cgit v1.2.3 From 4a962170d7cf4243d6ae156fca20a6167388925d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 28 Jul 2010 14:41:51 -0700 Subject: glsl2: Add support for redeclaring layout of gl_FragCoord for ARB_fcc. Fixes: glsl-arb-fragment-coord-conventions --- src/glsl/ast_to_hir.cpp | 15 +++++++++++++-- src/glsl/ir.h | 4 ++++ src/glsl/ir_clone.cpp | 2 ++ src/mesa/program/ir_to_mesa.cpp | 7 ++++++- 4 files changed, 25 insertions(+), 3 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index d82cf33389..8e8690c628 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -50,6 +50,7 @@ */ #include "main/imports.h" +#include "main/extensions.h" #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ast.h" @@ -1542,8 +1543,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, else var->interpolation = ir_var_smooth; - /* FINISHME: Apply the fragment coord convetion layout qualifiers. - */ + var->pixel_center_integer = qual->pixel_center_integer; + var->origin_upper_left = qual->origin_upper_left; if ((qual->origin_upper_left || qual->pixel_center_integer) && (strcmp(var->name, "gl_FragCoord") != 0)) { const char *const qual_string = (qual->origin_upper_left) @@ -1932,6 +1933,16 @@ ast_declarator_list::hir(exec_list *instructions, earlier->type = var->type; delete var; var = NULL; + } else if (state->extensions->ARB_fragment_coord_conventions && + (earlier != NULL) && + (strcmp(var->name, "gl_FragCoord") == 0) && + earlier->type == var->type && + earlier->mode == var->mode) { + /* Allow redeclaration of gl_FragCoord for ARB_fcc layout + * qualifiers. + */ + earlier->origin_upper_left = var->origin_upper_left; + earlier->pixel_center_integer = var->pixel_center_integer; } else { YYLTYPE loc = this->get_location(); diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 7e8363106d..202685d145 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -238,6 +238,10 @@ public: */ unsigned array_lvalue:1; + /* ARB_fragment_coord_conventions */ + unsigned origin_upper_left:1; + unsigned pixel_center_integer:1; + /** * Storage location of the base of this variable * diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index c49a732481..f97080d205 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -52,6 +52,8 @@ ir_variable::clone(struct hash_table *ht) const var->array_lvalue = this->array_lvalue; var->location = this->location; var->warn_extension = this->warn_extension; + var->origin_upper_left = this->origin_upper_left; + var->pixel_center_integer = this->pixel_center_integer; if (this->constant_value) var->constant_value = this->constant_value->clone(ht); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index c53381e29d..a3019cc650 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -557,7 +557,12 @@ ir_to_mesa_visitor::find_variable_storage(ir_variable *var) void ir_to_mesa_visitor::visit(ir_variable *ir) { - (void)ir; + if (strcmp(ir->name, "gl_FragCoord") == 0) { + struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; + + fp->OriginUpperLeft = ir->origin_upper_left; + fp->PixelCenterInteger = ir->pixel_center_integer; + } } void -- cgit v1.2.3 From 859fd56245c1d725cacab17a34793d41ea14e867 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 28 Jul 2010 15:42:35 -0700 Subject: ir_to_mesa: Respect the driver if it rejects a shader. --- src/mesa/drivers/dri/i965/brw_program.c | 6 ++---- src/mesa/program/ir_to_mesa.cpp | 14 +++++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c index 4b08d2599b..c6d11fed06 100644 --- a/src/mesa/drivers/dri/i965/brw_program.c +++ b/src/mesa/drivers/dri/i965/brw_program.c @@ -36,6 +36,7 @@ #include "program/program.h" #include "program/programopt.h" #include "tnl/tnl.h" +#include "talloc.h" #include "brw_context.h" #include "brw_wm.h" @@ -114,10 +115,7 @@ shader_error(GLcontext *ctx, struct gl_program *prog, const char *msg) shader = _mesa_lookup_shader_program(ctx, prog->Id); if (shader) { - if (shader->InfoLog) { - free(shader->InfoLog); - } - shader->InfoLog = _mesa_strdup(msg); + shader->InfoLog = talloc_strdup_append(shader->InfoLog, msg); shader->LinkStatus = GL_FALSE; } } diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index a3019cc650..3a28c566d4 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2320,7 +2320,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, validate_ir_tree(shader->ir); - prog = ctx->Driver.NewProgram(ctx, target, 1); + prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name); if (!prog) return NULL; prog->Parameters = _mesa_new_parameter_list(); @@ -2536,6 +2536,7 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) if (prog->LinkStatus) { for (i = 0; i < prog->_NumLinkedShaders; i++) { struct gl_program *linked_prog; + bool ok = true; linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); @@ -2547,16 +2548,19 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) case GL_VERTEX_SHADER: _mesa_reference_vertprog(ctx, &prog->VertexProgram, (struct gl_vertex_program *)linked_prog); - ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, - linked_prog); + ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, + linked_prog); break; case GL_FRAGMENT_SHADER: _mesa_reference_fragprog(ctx, &prog->FragmentProgram, (struct gl_fragment_program *)linked_prog); - ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, - linked_prog); + ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, + linked_prog); break; } + if (!ok) { + prog->LinkStatus = GL_FALSE; + } } } } -- cgit v1.2.3 From 806cb9f9528e3c55c157d7e8bbb751b769b6fcb7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 29 Jul 2010 15:17:23 -0700 Subject: ir_to_mesa: Don't emit a duplicate return at the end of a function. It was harmless, but ugly. --- src/mesa/program/ir_to_mesa.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 3a28c566d4..b6dfde3783 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2350,8 +2350,12 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, visit_exec_list(&entry->sig->body, &v); - entry->bgn_inst = v.ir_to_mesa_emit_op0(NULL, OPCODE_RET); - entry->bgn_inst = v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB); + ir_to_mesa_instruction *last; + last = (ir_to_mesa_instruction *)v.instructions.get_tail(); + if (last->op != OPCODE_RET) + v.ir_to_mesa_emit_op0(NULL, OPCODE_RET); + + v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB); progress = GL_TRUE; } } -- cgit v1.2.3 From 40f57c2becbb2cee7cfb6d6ed49dc1db57987e9a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 30 Jul 2010 14:44:09 -0700 Subject: ir_to_mesa: Add the function name as a comment to BGNSUB and ENDSUB. --- src/mesa/program/ir_to_mesa.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index b6dfde3783..e62395a3b9 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2355,7 +2355,10 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, if (last->op != OPCODE_RET) v.ir_to_mesa_emit_op0(NULL, OPCODE_RET); - v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB); + ir_to_mesa_instruction *end; + end = v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB); + end->function = entry; + progress = GL_TRUE; } } @@ -2401,12 +2404,23 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, shader_program->LinkStatus = false; } - if (mesa_inst->Opcode == OPCODE_BGNSUB) + switch (mesa_inst->Opcode) { + case OPCODE_BGNSUB: inst->function->inst = i; - else if (mesa_inst->Opcode == OPCODE_CAL) + mesa_inst->Comment = strdup(inst->function->sig->function_name()); + break; + case OPCODE_ENDSUB: + mesa_inst->Comment = strdup(inst->function->sig->function_name()); + break; + case OPCODE_CAL: mesa_inst->BranchTarget = inst->function->sig_id; /* rewritten later */ - else if (mesa_inst->Opcode == OPCODE_ARL) + break; + case OPCODE_ARL: prog->NumAddressRegs = 1; + break; + default: + break; + } mesa_inst++; i++; -- cgit v1.2.3 From 784695442c415cf0be882434a25671ecfb635d34 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 30 Jul 2010 17:04:49 -0700 Subject: glsl2: Add new tree grafting optimization pass. --- src/glsl/Makefile | 1 + src/glsl/ir_optimization.h | 1 + src/glsl/ir_tree_grafting.cpp | 356 ++++++++++++++++++++++++++++++++++++++++ src/glsl/linker.cpp | 1 + src/glsl/main.cpp | 1 + src/mesa/program/ir_to_mesa.cpp | 1 + 6 files changed, 361 insertions(+) create mode 100644 src/glsl/ir_tree_grafting.cpp (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/Makefile b/src/glsl/Makefile index aa1922f3be..0254fec756 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -56,6 +56,7 @@ CXX_SOURCES = \ ir_print_visitor.cpp \ ir_reader.cpp \ ir_swizzle_swizzle.cpp \ + ir_tree_grafting.cpp \ ir_validate.cpp \ ir_variable.cpp \ ir_variable_refcount.cpp \ diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 5dbb025d35..55ec327193 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -44,5 +44,6 @@ bool do_if_to_cond_assign(exec_list *instructions); bool do_mat_op_to_vec(exec_list *instructions); bool do_mod_to_fract(exec_list *instructions); bool do_swizzle_swizzle(exec_list *instructions); +bool do_tree_grafting(exec_list *instructions); bool do_vec_index_to_cond_assign(exec_list *instructions); bool do_vec_index_to_swizzle(exec_list *instructions); diff --git a/src/glsl/ir_tree_grafting.cpp b/src/glsl/ir_tree_grafting.cpp new file mode 100644 index 0000000000..6f62de758b --- /dev/null +++ b/src/glsl/ir_tree_grafting.cpp @@ -0,0 +1,356 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_tree_grafting.cpp + * + * Takes assignments to variables that are dereferenced only once and + * pastes the RHS expression into where the variable is dereferenced. + * + * In the process of various operations like function inlining and + * tertiary op handling, we'll end up with our expression trees having + * been chopped up into a series of assignments of short expressions + * to temps. Other passes like ir_algebraic.cpp would prefer to see + * the deepest expression trees they can to try to optimize them. + * + * This is a lot like copy propagaton. In comparison, copy + * propagation only acts on plain copies, not arbitrary expressions on + * the RHS. Generally, we wouldn't want to go pasting some + * complicated expression everywhere it got used, though, so we don't + * handle expressions in that pass. + * + * The hard part is making sure we don't move an expression across + * some other assignments that would change the value of the + * expression. So we split this into two passes: First, find the + * variables in our scope which are written to once and read once, and + * then go through basic blocks seeing if we find an opportunity to + * move those expressions safely. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_variable_refcount.h" +#include "ir_basic_block.h" +#include "ir_optimization.h" +#include "glsl_types.h" + +static bool debug = false; + +class ir_tree_grafting_visitor : public ir_hierarchical_visitor { +public: + ir_tree_grafting_visitor(ir_assignment *graft_assign, + ir_variable *graft_var) + { + this->progress = false; + this->graft_assign = graft_assign; + this->graft_var = graft_var; + } + + virtual ir_visitor_status visit_leave(class ir_assignment *); + virtual ir_visitor_status visit_enter(class ir_call *); + virtual ir_visitor_status visit_enter(class ir_expression *); + virtual ir_visitor_status visit_enter(class ir_function *); + virtual ir_visitor_status visit_enter(class ir_function_signature *); + virtual ir_visitor_status visit_enter(class ir_if *); + virtual ir_visitor_status visit_enter(class ir_loop *); + virtual ir_visitor_status visit_enter(class ir_swizzle *); + virtual ir_visitor_status visit_enter(class ir_texture *); + + bool do_graft(ir_rvalue **rvalue); + + bool progress; + ir_variable *graft_var; + ir_assignment *graft_assign; +}; + +struct find_deref_info { + ir_variable *var; + bool found; +}; + +void +dereferences_variable_callback(ir_instruction *ir, void *data) +{ + struct find_deref_info *info = (struct find_deref_info *)data; + + if (ir == info->var) + info->found = true; +} + +static bool +dereferences_variable(ir_instruction *ir, ir_variable *var) +{ + struct find_deref_info info; + + info.var = var; + info.found = false; + + visit_tree(ir, dereferences_variable_callback, &info); + + return info.found; +} + +bool +ir_tree_grafting_visitor::do_graft(ir_rvalue **rvalue) +{ + if (!*rvalue) + return false; + + ir_dereference_variable *deref = (*rvalue)->as_dereference_variable(); + + if (!deref || deref->var != this->graft_var) + return false; + + if (debug) { + printf("GRAFTING:\n"); + this->graft_assign->rhs->print(); + printf("\n"); + printf("TO:\n"); + (*rvalue)->print(); + printf("\n"); + } + + this->graft_assign->remove(); + *rvalue = this->graft_assign->rhs; + + this->progress = true; + return true; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_enter(ir_loop *ir) +{ + (void)ir; + /* Do not traverse into the body of the loop since that is a + * different basic block. + */ + return visit_stop; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_leave(ir_assignment *ir) +{ + if (do_graft(&ir->rhs) || + do_graft(&ir->condition)) + return visit_stop; + + /* If this assignment updates a variable used in the assignment + * we're trying to graft, then we're done. + */ + if (dereferences_variable(this->graft_assign->rhs, + ir->lhs->variable_referenced())) { + if (debug) { + printf("graft killed by: "); + ir->print(); + printf("\n"); + } + return visit_stop; + } + + return visit_continue; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_enter(ir_function *ir) +{ + (void) ir; + return visit_continue_with_parent; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_enter(ir_function_signature *ir) +{ + (void)ir; + return visit_continue_with_parent; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_enter(ir_call *ir) +{ + /* Reminder: iterating ir_call iterates its parameters. */ + foreach_iter(exec_list_iterator, iter, *ir) { + ir_rvalue *ir = (ir_rvalue *)iter.get(); + ir_rvalue *new_ir = ir; + + if (do_graft(&new_ir)) { + ir->replace_with(new_ir); + return visit_stop; + } + } + + return visit_continue; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_enter(ir_expression *ir) +{ + for (unsigned int i = 0; i < ir->get_num_operands(); i++) { + if (do_graft(&ir->operands[i])) + return visit_stop; + } + + return visit_continue; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_enter(ir_if *ir) +{ + if (do_graft(&ir->condition)) + return visit_stop; + + /* Do not traverse into the body of the if-statement since that is a + * different basic block. + */ + return visit_continue_with_parent; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_enter(ir_swizzle *ir) +{ + if (do_graft(&ir->val)) + return visit_stop; + + return visit_continue; +} + +ir_visitor_status +ir_tree_grafting_visitor::visit_enter(ir_texture *ir) +{ + if (do_graft(&ir->coordinate) || + do_graft(&ir->projector) || + do_graft(&ir->shadow_comparitor)) + return visit_stop; + + switch (ir->op) { + case ir_tex: + break; + case ir_txb: + if (do_graft(&ir->lod_info.bias)) + return visit_stop; + break; + case ir_txf: + case ir_txl: + if (do_graft(&ir->lod_info.lod)) + return visit_stop; + break; + case ir_txd: + if (do_graft(&ir->lod_info.grad.dPdx) || + do_graft(&ir->lod_info.grad.dPdy)) + return visit_stop; + break; + } + + return visit_continue; +} + +struct tree_grafting_info { + ir_variable_refcount_visitor *refs; + bool progress; +}; + +static bool +try_tree_grafting(ir_assignment *start, + ir_variable *lhs_var, + ir_instruction *bb_last) +{ + ir_tree_grafting_visitor v(start, lhs_var); + + if (debug) { + printf("trying to graft: "); + lhs_var->print(); + printf("\n"); + } + + for (ir_instruction *ir = (ir_instruction *)start->next; + ir != bb_last->next; + ir = (ir_instruction *)ir->next) { + + if (debug) { + printf("- "); + ir->print(); + printf("\n"); + } + + ir_visitor_status s = ir->accept(&v); + if (s == visit_stop) + return v.progress; + } + + return false; +} + +static void +tree_grafting_basic_block(ir_instruction *bb_first, + ir_instruction *bb_last, + void *data) +{ + struct tree_grafting_info *info = (struct tree_grafting_info *)data; + ir_instruction *ir, *next; + + for (ir = bb_first, next = (ir_instruction *)ir->next; + ir != bb_last->next; + ir = next, next = (ir_instruction *)ir->next) { + ir_assignment *assign = ir->as_assignment(); + + if (!assign) + continue; + + ir_variable *lhs_var = assign->lhs->whole_variable_referenced(); + if (!lhs_var) + continue; + + struct variable_entry *entry = info->refs->get_variable_entry(lhs_var); + + if (!entry->declaration || + entry->assigned_count != 1 || + entry->referenced_count != 2) + continue; + + assert(assign == entry->assign); + + /* Found a possibly graftable assignment. Now, walk through the + * rest of the BB seeing if the deref is here, and if nothing interfered with + * pasting its expression's values in between. + */ + info->progress |= try_tree_grafting(assign, lhs_var, bb_last); + } +} + +/** + * Does a copy propagation pass on the code present in the instruction stream. + */ +bool +do_tree_grafting(exec_list *instructions) +{ + ir_variable_refcount_visitor refs; + struct tree_grafting_info info; + + info.progress = false; + info.refs = &refs; + + visit_list_elements(info.refs, instructions); + + call_for_basic_blocks(instructions, tree_grafting_basic_block, &info); + + return info.progress; +} diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index e9daad28ec..9b47e4788f 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1286,6 +1286,7 @@ link_shaders(struct gl_shader_program *prog) progress = do_copy_propagation(ir) || progress; progress = do_dead_code_local(ir) || progress; progress = do_dead_code(ir) || progress; + progress = do_tree_grafting(ir) || progress; progress = do_constant_variable_unlinked(ir) || progress; progress = do_constant_folding(ir) || progress; progress = do_if_return(ir) || progress; diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index 08b133f124..d557dcc493 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -163,6 +163,7 @@ compile_shader(struct gl_shader *shader) progress = do_copy_propagation(shader->ir) || progress; progress = do_dead_code_local(shader->ir) || progress; progress = do_dead_code_unlinked(shader->ir) || progress; + progress = do_tree_grafting(shader->ir) || progress; progress = do_constant_variable_unlinked(shader->ir) || progress; progress = do_constant_folding(shader->ir) || progress; progress = do_algebraic(shader->ir) || progress; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index e62395a3b9..9274723eb7 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2485,6 +2485,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) progress = do_copy_propagation(shader->ir) || progress; progress = do_dead_code_local(shader->ir) || progress; progress = do_dead_code_unlinked(shader->ir) || progress; + progress = do_tree_grafting(shader->ir) || progress; progress = do_constant_variable_unlinked(shader->ir) || progress; progress = do_constant_folding(shader->ir) || progress; progress = do_algebraic(shader->ir) || progress; -- cgit v1.2.3 From b42519108dc7ab104cf9ade65a508f54a0294406 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 1 Aug 2010 11:40:41 -0700 Subject: ir_to_mesa: Add support for MESA_GLSL=log. This is the option that dumps shader source to files in the current directory. --- src/mesa/program/ir_to_mesa.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 9274723eb7..8f790af09a 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2514,6 +2514,10 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link); shader->num_builtins_to_link = state->num_builtins_to_link; + if (ctx->Shader.Flags & GLSL_LOG) { + _mesa_write_shader_to_file(shader); + } + /* Retain any live IR, but trash the rest. */ reparent_ir(shader->ir, shader); -- cgit v1.2.3 From 9c02412cdc0270f2b0dc64afe709721e049fd5b0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 2 Aug 2010 14:47:10 -0700 Subject: ir_to_mesa: Add a constructor for ir_to_mesa_src_reg. This helps makes sure we don't miss any new fields, and makes totally uninitialized src_regs be PROGRAM_UNDEFINED. --- src/mesa/program/ir_to_mesa.cpp | 82 +++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 48 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 8f790af09a..5510440475 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -53,11 +53,30 @@ extern "C" { #include "program/prog_parameter.h" } +static int swizzle_for_size(int size); + /** * This struct is a corresponding struct to Mesa prog_src_register, with * wider fields. */ typedef struct ir_to_mesa_src_reg { + ir_to_mesa_src_reg(int file, int index, const glsl_type *type) + { + this->file = file; + this->index = index; + if (type && (type->is_scalar() || type->is_vector() || type->is_matrix())) + this->swizzle = swizzle_for_size(type->vector_elements); + else + this->swizzle = SWIZZLE_XYZW; + this->negate = 0; + this->reladdr = NULL; + } + + ir_to_mesa_src_reg() + { + this->file = PROGRAM_UNDEFINED; + } + int file; /**< PROGRAM_* from Mesa */ int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */ GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */ @@ -242,9 +261,7 @@ public: void *mem_ctx; }; -ir_to_mesa_src_reg ir_to_mesa_undef = { - PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, NEGATE_NONE, NULL, -}; +ir_to_mesa_src_reg ir_to_mesa_undef = ir_to_mesa_src_reg(PROGRAM_UNDEFINED, 0, NULL); ir_to_mesa_dst_reg ir_to_mesa_undef_dst = { PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, COND_TR, NULL, @@ -379,15 +396,7 @@ ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg) inline ir_to_mesa_src_reg ir_to_mesa_src_reg_from_dst(ir_to_mesa_dst_reg reg) { - ir_to_mesa_src_reg src_reg; - - src_reg.file = reg.file; - src_reg.index = reg.index; - src_reg.swizzle = SWIZZLE_XYZW; - src_reg.negate = 0; - src_reg.reladdr = reg.reladdr; - - return src_reg; + return ir_to_mesa_src_reg(reg.file, reg.index, NULL); } /** @@ -460,13 +469,10 @@ ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir, struct ir_to_mesa_src_reg ir_to_mesa_visitor::src_reg_for_float(float val) { - ir_to_mesa_src_reg src_reg; + ir_to_mesa_src_reg src_reg(PROGRAM_CONSTANT, -1, NULL); - src_reg.file = PROGRAM_CONSTANT; src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters, &val, 1, &src_reg.swizzle); - src_reg.reladdr = NULL; - src_reg.negate = 0; return src_reg; } @@ -1238,7 +1244,6 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var, void ir_to_mesa_visitor::visit(ir_dereference_variable *ir) { - ir_to_mesa_src_reg src_reg; variable_storage *entry = find_variable_storage(ir->var); unsigned int loc; int len; @@ -1340,17 +1345,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) } } - src_reg.file = entry->file; - src_reg.index = entry->index; - /* If the type is smaller than a vec4, replicate the last channel out. */ - if (ir->type->is_scalar() || ir->type->is_vector()) - src_reg.swizzle = swizzle_for_size(ir->var->type->vector_elements); - else - src_reg.swizzle = SWIZZLE_NOOP; - src_reg.reladdr = NULL; - src_reg.negate = 0; - - this->result = src_reg; + this->result = ir_to_mesa_src_reg(entry->file, entry->index, ir->var->type); } void @@ -1367,17 +1362,13 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir) if (deref_var && strncmp(deref_var->var->name, "gl_TextureMatrix", strlen("gl_TextureMatrix")) == 0) { - ir_to_mesa_src_reg src_reg; struct variable_storage *entry; entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, deref_var->var, ir->array_index); assert(entry); - src_reg.file = entry->file; - src_reg.index = entry->index; - src_reg.swizzle = swizzle_for_size(ir->type->vector_elements); - src_reg.negate = 0; + ir_to_mesa_src_reg src_reg(entry->file, entry->index, ir->type); if (index) { src_reg.reladdr = NULL; @@ -1646,17 +1637,14 @@ ir_to_mesa_visitor::visit(ir_constant *ir) ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat); for (i = 0; i < ir->type->matrix_columns; i++) { - src_reg.file = PROGRAM_CONSTANT; - assert(ir->type->base_type == GLSL_TYPE_FLOAT); values = &ir->value.f[i * ir->type->vector_elements]; + src_reg = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, NULL); src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters, - values, - ir->type->vector_elements, - &src_reg.swizzle); - src_reg.reladdr = NULL; - src_reg.negate = 0; + values, + ir->type->vector_elements, + &src_reg.swizzle); ir_to_mesa_emit_op1(ir, OPCODE_MOV, mat_column, src_reg); mat_column.index++; @@ -1689,13 +1677,11 @@ ir_to_mesa_visitor::visit(ir_constant *ir) assert(!"Non-float/uint/int/bool constant"); } - src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters, - values, ir->type->vector_elements, - &src_reg.swizzle); - src_reg.reladdr = NULL; - src_reg.negate = 0; - - this->result = src_reg; + this->result = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, ir->type); + this->result.index = _mesa_add_unnamed_constant(this->prog->Parameters, + values, + ir->type->vector_elements, + &this->result.swizzle); } function_entry * @@ -1825,7 +1811,7 @@ ir_to_mesa_visitor::visit(ir_call *ir) void ir_to_mesa_visitor::visit(ir_texture *ir) { - ir_to_mesa_src_reg result_src, coord, lod_info = { 0 }, projector; + ir_to_mesa_src_reg result_src, coord, lod_info, projector; ir_to_mesa_dst_reg result_dst, coord_dst; ir_to_mesa_instruction *inst = NULL; prog_opcode opcode = OPCODE_NOP; -- cgit v1.2.3 From 26675e37bc5a086c6df77946d2dada34dc9129f0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 2 Aug 2010 14:32:52 -0700 Subject: ir_to_mesa: Support for struct uniforms. Fixes glsl-uniform-struct. --- src/mesa/program/ir_to_mesa.cpp | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 5510440475..7d5761f699 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -252,6 +252,11 @@ public: GLboolean try_emit_mad(ir_expression *ir, int mul_operand); + void add_aggregate_uniform(ir_instruction *ir, + const char *name, + const struct glsl_type *type, + struct ir_to_mesa_dst_reg temp); + int *sampler_map; int sampler_map_size; @@ -1241,6 +1246,62 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var, return NULL; } +/* Recursively add all the members of the aggregate uniform as uniform names + * to Mesa, moving those uniforms to our structured temporary. + */ +void +ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir, + const char *name, + const struct glsl_type *type, + struct ir_to_mesa_dst_reg temp) +{ + int loc; + + if (type->is_record()) { + void *mem_ctx = talloc_new(NULL); + + for (unsigned int i = 0; i < type->length; i++) { + const glsl_type *field_type = type->fields.structure[i].type; + add_aggregate_uniform(ir, + talloc_asprintf(mem_ctx, "%s.%s", name, + type->fields.structure[i].name), + field_type, temp); + temp.index += type_size(field_type); + } + + talloc_free(mem_ctx); + + return; + } + + assert(type->is_vector() || type->is_scalar() || !"FINISHME: other types"); + + int len; + + if (type->is_vector() || + type->is_scalar()) { + len = type->vector_elements; + } else { + len = type_size(type) * 4; + } + + loc = _mesa_add_uniform(this->prog->Parameters, + name, + len, + type->gl_type, + NULL); + + + ir_to_mesa_src_reg uniform(PROGRAM_UNIFORM, loc, type); + + for (int i = 0; i < type_size(type); i++) { + ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, uniform); + temp.index++; + uniform.index++; + } +} + + void ir_to_mesa_visitor::visit(ir_dereference_variable *ir) { @@ -1276,6 +1337,23 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) assert(ir->var->type->gl_type != 0 && ir->var->type->gl_type != GL_INVALID_ENUM); + /* Oh, the joy of aggregate types in Mesa. Like constants, + * we can only really do vec4s. So, make a temp, chop the + * aggregate up into vec4s, and move those vec4s to the temp. + */ + if (ir->var->type->is_record()) { + ir_to_mesa_src_reg temp = get_temp(ir->var->type); + + entry = new(mem_ctx) variable_storage(ir->var, + temp.file, + temp.index); + this->variables.push_tail(entry); + + add_aggregate_uniform(ir->var, ir->var->name, ir->var->type, + ir_to_mesa_dst_reg_from_src(temp)); + break; + } + if (ir->var->type->is_vector() || ir->var->type->is_scalar()) { len = ir->var->type->vector_elements; -- cgit v1.2.3 From b10bb527eaf39378da25dd4ad21b1c68ceaa1e2d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 2 Aug 2010 16:59:20 -0700 Subject: Initialize a couple of HasIndex2 fields on Mesa IR src regs. --- src/mesa/drivers/dri/i965/brw_wm_fp.c | 1 + src/mesa/program/ir_to_mesa.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/drivers/dri/i965/brw_wm_fp.c b/src/mesa/drivers/dri/i965/brw_wm_fp.c index 0bef874b88..df9e54c6b4 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_fp.c +++ b/src/mesa/drivers/dri/i965/brw_wm_fp.c @@ -88,6 +88,7 @@ static struct prog_src_register src_reg(GLuint file, GLuint idx) reg.RelAddr = 0; reg.Negate = NEGATE_NONE; reg.Abs = 0; + reg.HasIndex2 = 0; return reg; } diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7d5761f699..af306f05d8 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2115,6 +2115,7 @@ mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg) mesa_reg.RelAddr = reg.reladdr != NULL; mesa_reg.Negate = reg.negate; mesa_reg.Abs = 0; + mesa_reg.HasIndex2 = GL_FALSE; return mesa_reg; } -- cgit v1.2.3 From 47f305a4fcd23f859d097c6cc25a739547462939 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 2 Aug 2010 17:05:48 -0700 Subject: ir_to_mesa: Add support for 1.20 uniform initializers. Fixes: glsl-uniform-initializer-1 glsl-uniform-initializer-2 glsl-uniform-initializer-3 glsl-uniform-initializer-4 glsl1-GLSL 1.20 uniform array constructor --- src/mesa/program/ir_to_mesa.cpp | 127 ++++++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 30 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index af306f05d8..ba0934c446 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -252,9 +252,13 @@ public: GLboolean try_emit_mad(ir_expression *ir, int mul_operand); + int add_uniform(const char *name, + const glsl_type *type, + ir_constant *constant); void add_aggregate_uniform(ir_instruction *ir, const char *name, const struct glsl_type *type, + ir_constant *constant, struct ir_to_mesa_dst_reg temp); int *sampler_map; @@ -1246,6 +1250,83 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var, return NULL; } +int +ir_to_mesa_visitor::add_uniform(const char *name, + const glsl_type *type, + ir_constant *constant) +{ + int len; + + if (type->is_vector() || + type->is_scalar()) { + len = type->vector_elements; + } else { + len = type_size(type) * 4; + } + + float *values = NULL; + if (constant && type->is_array()) { + values = (float *)malloc(type->length * 4 * sizeof(float)); + + assert(type->fields.array->is_scalar() || + type->fields.array->is_vector() || + !"FINISHME: uniform array initializers for non-vector"); + + for (unsigned int i = 0; i < type->length; i++) { + ir_constant *element = constant->array_elements[i]; + unsigned int c; + + for (c = 0; c < type->fields.array->vector_elements; c++) { + switch (type->fields.array->base_type) { + case GLSL_TYPE_FLOAT: + values[4 * i + c] = element->value.f[c]; + break; + case GLSL_TYPE_INT: + values[4 * i + c] = element->value.i[c]; + break; + case GLSL_TYPE_UINT: + values[4 * i + c] = element->value.u[c]; + break; + case GLSL_TYPE_BOOL: + values[4 * i + c] = element->value.b[c]; + break; + default: + assert(!"not reached"); + } + } + } + } else if (constant) { + values = (float *)malloc(16 * sizeof(float)); + for (unsigned int i = 0; i < type->components(); i++) { + switch (type->base_type) { + case GLSL_TYPE_FLOAT: + values[i] = constant->value.f[i]; + break; + case GLSL_TYPE_INT: + values[i] = constant->value.i[i]; + break; + case GLSL_TYPE_UINT: + values[i] = constant->value.u[i]; + break; + case GLSL_TYPE_BOOL: + values[i] = constant->value.b[i]; + break; + default: + assert(!"not reached"); + } + } + } + + int loc = _mesa_add_uniform(this->prog->Parameters, + name, + len, + type->gl_type, + values); + free(values); + + return loc; +} + /* Recursively add all the members of the aggregate uniform as uniform names * to Mesa, moving those uniforms to our structured temporary. */ @@ -1253,20 +1334,29 @@ void ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir, const char *name, const struct glsl_type *type, + ir_constant *constant, struct ir_to_mesa_dst_reg temp) { int loc; if (type->is_record()) { void *mem_ctx = talloc_new(NULL); + ir_constant *field_constant = NULL; + + if (constant) + field_constant = (ir_constant *)constant->components.get_head(); for (unsigned int i = 0; i < type->length; i++) { const glsl_type *field_type = type->fields.structure[i].type; + add_aggregate_uniform(ir, talloc_asprintf(mem_ctx, "%s.%s", name, type->fields.structure[i].name), - field_type, temp); + field_type, field_constant, temp); temp.index += type_size(field_type); + + if (constant) + field_constant = (ir_constant *)field_constant->next; } talloc_free(mem_ctx); @@ -1276,21 +1366,7 @@ ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir, assert(type->is_vector() || type->is_scalar() || !"FINISHME: other types"); - int len; - - if (type->is_vector() || - type->is_scalar()) { - len = type->vector_elements; - } else { - len = type_size(type) * 4; - } - - loc = _mesa_add_uniform(this->prog->Parameters, - name, - len, - type->gl_type, - NULL); - + loc = add_uniform(name, type, constant); ir_to_mesa_src_reg uniform(PROGRAM_UNIFORM, loc, type); @@ -1307,7 +1383,6 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) { variable_storage *entry = find_variable_storage(ir->var); unsigned int loc; - int len; if (!entry) { switch (ir->var->mode) { @@ -1350,22 +1425,14 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) this->variables.push_tail(entry); add_aggregate_uniform(ir->var, ir->var->name, ir->var->type, - ir_to_mesa_dst_reg_from_src(temp)); + ir->var->constant_value, + ir_to_mesa_dst_reg_from_src(temp)); break; } - if (ir->var->type->is_vector() || - ir->var->type->is_scalar()) { - len = ir->var->type->vector_elements; - } else { - len = type_size(ir->var->type) * 4; - } - - loc = _mesa_add_uniform(this->prog->Parameters, - ir->var->name, - len, - ir->var->type->gl_type, - NULL); + loc = add_uniform(ir->var->name, + ir->var->type, + ir->var->constant_value); /* Always mark the uniform used at this point. If it isn't * used, dead code elimination should have nuked the decl already. -- cgit v1.2.3 From 952d0f88e1741d51b641be75f7c5a6565e245a69 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 12:57:58 -0700 Subject: glsl2: Skip talloc_parent in constant_expression of non-constant arrays. --- src/glsl/ir_constant_expression.cpp | 2 +- src/mesa/program/ir_to_mesa.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index 677353e542..0a924246da 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -690,11 +690,11 @@ ir_dereference_variable::constant_expression_value() ir_constant * ir_dereference_array::constant_expression_value() { - void *ctx = talloc_parent(this); ir_constant *array = this->array->constant_expression_value(); ir_constant *idx = this->array_index->constant_expression_value(); if ((array != NULL) && (idx != NULL)) { + void *ctx = talloc_parent(this); if (array->type->is_matrix()) { /* Array access of a matrix results in a vector. */ diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index ba0934c446..dcf8c497c6 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2622,7 +2622,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) progress = do_constant_folding(shader->ir) || progress; progress = do_algebraic(shader->ir) || progress; progress = do_if_return(shader->ir) || progress; - if (ctx->Shader.EmitNoIfs) + if (1 || ctx->Shader.EmitNoIfs) progress = do_if_to_cond_assign(shader->ir) || progress; progress = do_vec_index_to_swizzle(shader->ir) || progress; -- cgit v1.2.3 From fe1918c71c3e387939cef9359d4b31ebc5c11a17 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 14:21:01 -0700 Subject: ir_to_mesa: Clean up the mapping of samplers to Mesa's sampler uniforms. Instead of using a linker-assigned location (since samplers don't actually take up uniform space, being a link-time choice), use the sampler's varaible pointer as a hash key. --- src/mesa/program/ir_to_mesa.cpp | 42 +++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index dcf8c497c6..777b4d91f4 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -45,6 +45,7 @@ extern "C" { #include "main/mtypes.h" #include "main/shaderobj.h" #include "main/uniforms.h" +#include "program/hash_table.h" #include "program/prog_instruction.h" #include "program/prog_optimize.h" #include "program/prog_print.h" @@ -160,6 +161,7 @@ public: class ir_to_mesa_visitor : public ir_visitor { public: ir_to_mesa_visitor(); + ~ir_to_mesa_visitor(); function_entry *current_function; @@ -261,11 +263,10 @@ public: ir_constant *constant, struct ir_to_mesa_dst_reg temp); - int *sampler_map; - int sampler_map_size; + struct hash_table *sampler_map; - void map_sampler(int location, int sampler); - int get_sampler_number(int location); + void set_sampler_location(ir_variable *sampler, int location); + int get_sampler_location(ir_variable *sampler); void *mem_ctx; }; @@ -370,22 +371,22 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op0(ir_instruction *ir, } void -ir_to_mesa_visitor::map_sampler(int location, int sampler) +ir_to_mesa_visitor::set_sampler_location(ir_variable *sampler, int location) { - if (this->sampler_map_size <= location) { - this->sampler_map = talloc_realloc(this->mem_ctx, this->sampler_map, - int, location + 1); - this->sampler_map_size = location + 1; + if (this->sampler_map == NULL) { + this->sampler_map = hash_table_ctor(0, hash_table_pointer_hash, + hash_table_pointer_compare); } - this->sampler_map[location] = sampler; + hash_table_insert(this->sampler_map, (void *)(uintptr_t)location, sampler); } int -ir_to_mesa_visitor::get_sampler_number(int location) +ir_to_mesa_visitor::get_sampler_location(ir_variable *sampler) { - assert(location < this->sampler_map_size); - return this->sampler_map[location]; + void *result = hash_table_find(this->sampler_map, sampler); + + return (int)(uintptr_t)result; } inline ir_to_mesa_dst_reg @@ -1394,14 +1395,10 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) /* FINISHME: Fix up uniform name for arrays and things */ if (ir->var->type->base_type == GLSL_TYPE_SAMPLER) { - /* FINISHME: we whack the location of the var here, which - * is probably not expected. But we need to communicate - * mesa's sampler number to the tex instruction. - */ int sampler = _mesa_add_sampler(this->prog->Parameters, ir->var->name, ir->var->type->gl_type); - map_sampler(ir->var->location, sampler); + set_sampler_location(ir->var, sampler); entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_SAMPLER, sampler); @@ -2059,7 +2056,7 @@ ir_to_mesa_visitor::visit(ir_texture *ir) */ sampler->accept(this); - inst->sampler = get_sampler_number(sampler->var->location); + inst->sampler = get_sampler_location(sampler->var); switch (sampler->type->sampler_dimensionality) { case GLSL_SAMPLER_DIM_1D: @@ -2166,10 +2163,15 @@ ir_to_mesa_visitor::ir_to_mesa_visitor() next_temp = 1; next_signature_id = 1; sampler_map = NULL; - sampler_map_size = 0; current_function = NULL; } +ir_to_mesa_visitor::~ir_to_mesa_visitor() +{ + if (this->sampler_map) + hash_table_dtor(this->sampler_map); +} + static struct prog_src_register mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg) { -- cgit v1.2.3 From 5a7758efbe14dee026245a4f4f4fb3ccf7b2c23b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 2 Aug 2010 18:48:25 -0700 Subject: glsl2: Add ir_assignment::write_mask and associated methods Replace swizzles on the LHS with additional swizzles on the RHS and a write mask in the assignment instruction. As part of this add ir_assignment::set_lhs. Ideally we'd make ir_assignment::lhs private to prevent erroneous writes, but that would require a lot of code butchery at this point. Add ir_assignment constructor that takes an explicit write mask. This is required for ir_assignment::clone, but it can also be used in other places. Without this, ir_assignment clones lose their write masks, and incorrect IR is generated in optimization passes. Add ir_assignment::whole_variable_written method. This method gets the variable on the LHS if the whole variable is written or NULL otherwise. This is different from ir->lhs->whole_variable_referenced() because the latter has no knowledge of the write mask stored in the ir_assignment. Gut all code from ir_to_mesa that handled swizzles on the LHS of assignments. There is probably some other refactoring that could be done here, but that can be left for another day. --- src/glsl/ir.cpp | 113 ++++++++++++++++++++++++++++++++++- src/glsl/ir.h | 44 +++++++++++++- src/glsl/ir_clone.cpp | 3 +- src/glsl/ir_constant_variable.cpp | 2 +- src/glsl/ir_copy_propagation.cpp | 2 +- src/glsl/ir_dead_code_local.cpp | 2 +- src/glsl/ir_print_visitor.cpp | 14 ++++- src/glsl/ir_tree_grafting.cpp | 2 +- src/glsl/ir_vec_index_to_swizzle.cpp | 2 +- src/mesa/program/ir_to_mesa.cpp | 67 ++++++++------------- 10 files changed, 199 insertions(+), 52 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 79cbaa9ea0..c3bade8d54 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -22,6 +22,7 @@ */ #include #include "main/imports.h" +#include "main/macros.h" #include "ir.h" #include "ir_visitor.h" #include "glsl_types.h" @@ -31,13 +32,121 @@ ir_rvalue::ir_rvalue() this->type = glsl_type::error_type; } +/** + * Modify the swizzle make to move one component to another + * + * \param m IR swizzle to be modified + * \param from Component in the RHS that is to be swizzled + * \param to Desired swizzle location of \c from + */ +static void +update_rhs_swizzle(ir_swizzle_mask &m, unsigned from, unsigned to) +{ + switch (to) { + case 0: m.x = from; break; + case 1: m.y = from; break; + case 2: m.z = from; break; + case 3: m.w = from; break; + default: assert(!"Should not get here."); + } + + m.num_components = MAX2(m.num_components, (to + 1)); +} + +void +ir_assignment::set_lhs(ir_rvalue *lhs) +{ + while (lhs != NULL) { + ir_swizzle *swiz = lhs->as_swizzle(); + + if (swiz == NULL) + break; + + unsigned write_mask = 0; + ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 }; + + for (unsigned i = 0; i < swiz->mask.num_components; i++) { + unsigned c = 0; + + switch (i) { + case 0: c = swiz->mask.x; break; + case 1: c = swiz->mask.y; break; + case 2: c = swiz->mask.z; break; + case 3: c = swiz->mask.w; break; + default: assert(!"Should not get here."); + } + + write_mask |= (((this->write_mask >> i) & 1) << c); + update_rhs_swizzle(rhs_swiz, i, c); + } + + this->write_mask = write_mask; + lhs = swiz->val; + + this->rhs = new(this) ir_swizzle(this->rhs, rhs_swiz); + } + + assert((lhs == NULL) || lhs->as_dereference()); + + this->lhs = (ir_dereference *) lhs; +} + +ir_variable * +ir_assignment::whole_variable_written() +{ + ir_variable *v = this->lhs->whole_variable_referenced(); + + if (v == NULL) + return NULL; + + if (v->type->is_scalar()) + return v; + + if (v->type->is_vector()) { + const unsigned mask = (1U << v->type->vector_elements) - 1; + + if (mask != this->write_mask) + return NULL; + } + + /* Either all the vector components are assigned or the variable is some + * composite type (and the whole thing is assigned. + */ + return v; +} + +ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, + ir_rvalue *condition, unsigned write_mask) +{ + this->ir_type = ir_type_assignment; + this->condition = condition; + this->rhs = rhs; + this->lhs = lhs; + this->write_mask = write_mask; +} + ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition) { this->ir_type = ir_type_assignment; - this->lhs = lhs; - this->rhs = rhs; this->condition = condition; + this->rhs = rhs; + + /* If the RHS is a vector type, assume that all components of the vector + * type are being written to the LHS. The write mask comes from the RHS + * because we can have a case where the LHS is a vec4 and the RHS is a + * vec3. In that case, the assignment is: + * + * (assign (...) (xyz) (var_ref lhs) (var_ref rhs)) + */ + if (rhs->type->is_vector()) + this->write_mask = (1U << rhs->type->vector_elements) - 1; + else if (rhs->type->is_scalar()) + this->write_mask = 1; + else + this->write_mask = 0; + + this->set_lhs(lhs); } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index f964b36083..98789503e0 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -514,6 +514,16 @@ class ir_assignment : public ir_instruction { public: ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition); + /** + * Construct an assignment with an explicit write mask + * + * \note + * Since a write mask is supplied, the LHS must already be a bare + * \c ir_dereference. The cannot be any swizzles in the LHS. + */ + ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, ir_rvalue *condition, + unsigned write_mask); + virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const; virtual ir_constant *constant_expression_value(); @@ -530,10 +540,32 @@ public: return this; } + /** + * Get a whole variable written by an assignment + * + * If the LHS of the assignment writes a whole variable, the variable is + * returned. Otherwise \c NULL is returned. Examples of whole-variable + * assignment are: + * + * - Assigning to a scalar + * - Assigning to all components of a vector + * - Whole array (or matrix) assignment + * - Whole structure assignment + */ + ir_variable *whole_variable_written(); + + /** + * Set the LHS of an assignment + */ + void set_lhs(ir_rvalue *lhs); + /** * Left-hand side of the assignment. + * + * This should be treated as read only. If you need to set the LHS of an + * assignment, use \c ir_assignment::set_lhs. */ - ir_rvalue *lhs; + ir_dereference *lhs; /** * Value being assigned @@ -544,6 +576,16 @@ public: * Optional condition for the assignment. */ ir_rvalue *condition; + + + /** + * Component mask written + * + * For non-vector types in the LHS, this field will be zero. For vector + * types, a bit will be set for each component that is written. Note that + * for \c vec2 and \c vec3 types only the lower bits will ever be set. + */ + unsigned write_mask:4; }; /* Update ir_expression::num_operands() and operator_strs when diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 59831834bd..0e202164b3 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -242,7 +242,8 @@ ir_assignment::clone(void *mem_ctx, struct hash_table *ht) const return new(mem_ctx) ir_assignment(this->lhs->clone(mem_ctx, ht), this->rhs->clone(mem_ctx, ht), - new_condition); + new_condition, + this->write_mask); } ir_function * diff --git a/src/glsl/ir_constant_variable.cpp b/src/glsl/ir_constant_variable.cpp index 749e2cf809..1fb73e765e 100644 --- a/src/glsl/ir_constant_variable.cpp +++ b/src/glsl/ir_constant_variable.cpp @@ -110,7 +110,7 @@ ir_constant_variable_visitor::visit_enter(ir_assignment *ir) return visit_continue; } - ir_variable *var = ir->lhs->whole_variable_referenced(); + ir_variable *var = ir->whole_variable_written(); if (!var) return visit_continue; diff --git a/src/glsl/ir_copy_propagation.cpp b/src/glsl/ir_copy_propagation.cpp index 5712398732..26588a352c 100644 --- a/src/glsl/ir_copy_propagation.cpp +++ b/src/glsl/ir_copy_propagation.cpp @@ -224,7 +224,7 @@ add_copy(void *ctx, ir_assignment *ir, exec_list *acp) return; } - ir_variable *lhs_var = ir->lhs->whole_variable_referenced(); + ir_variable *lhs_var = ir->whole_variable_written(); ir_variable *rhs_var = ir->rhs->whole_variable_referenced(); if ((lhs_var != NULL) && (rhs_var != NULL)) { diff --git a/src/glsl/ir_dead_code_local.cpp b/src/glsl/ir_dead_code_local.cpp index 7a44ec8a4a..b22cc558df 100644 --- a/src/glsl/ir_dead_code_local.cpp +++ b/src/glsl/ir_dead_code_local.cpp @@ -137,7 +137,7 @@ process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments) } /* Now, check if we did a whole-variable assignment. */ - if (always_assign && (ir->lhs->whole_variable_referenced() != NULL)) { + if (always_assign && (ir->whole_variable_written() != NULL)) { /* We did a whole-variable assignment. So, any instruction in * the assignment list with the same LHS is dead. */ diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index 73476e7e9b..39b11bb32c 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -296,7 +296,19 @@ void ir_print_visitor::visit(ir_assignment *ir) else printf("(constant bool (1))"); - printf(" "); + + char mask[5]; + unsigned j = 0; + + for (unsigned i = 0; i < 4; i++) { + if ((ir->write_mask & (1 << i)) != 0) { + mask[j] = "xyzw"[i]; + j++; + } + } + mask[j] = '\0'; + + printf(" (%s) ", mask); ir->lhs->accept(this); diff --git a/src/glsl/ir_tree_grafting.cpp b/src/glsl/ir_tree_grafting.cpp index 6f62de758b..38034a6197 100644 --- a/src/glsl/ir_tree_grafting.cpp +++ b/src/glsl/ir_tree_grafting.cpp @@ -315,7 +315,7 @@ tree_grafting_basic_block(ir_instruction *bb_first, if (!assign) continue; - ir_variable *lhs_var = assign->lhs->whole_variable_referenced(); + ir_variable *lhs_var = assign->whole_variable_written(); if (!lhs_var) continue; diff --git a/src/glsl/ir_vec_index_to_swizzle.cpp b/src/glsl/ir_vec_index_to_swizzle.cpp index 1e170cbae6..b3de91f8ab 100644 --- a/src/glsl/ir_vec_index_to_swizzle.cpp +++ b/src/glsl/ir_vec_index_to_swizzle.cpp @@ -107,7 +107,7 @@ ir_vec_index_to_swizzle_visitor::visit_enter(ir_swizzle *ir) ir_visitor_status ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir) { - ir->lhs = convert_vec_index_to_swizzle(ir->lhs); + ir->set_lhs(convert_vec_index_to_swizzle(ir->lhs)); ir->rhs = convert_vec_index_to_swizzle(ir->rhs); return visit_continue; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 777b4d91f4..1cec4aa621 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -356,6 +356,7 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0) { + assert(dst.writemask != 0); return ir_to_mesa_emit_op3(ir, op, dst, src0, ir_to_mesa_undef, ir_to_mesa_undef); } @@ -1615,21 +1616,17 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) * We want to be careful in assignment setup to hit the actual storage * instead of potentially using a temporary like we might with the * ir_dereference handler. - * - * Thanks to ir_swizzle_swizzle, and ir_vec_index_to_swizzle, we - * should only see potentially one variable array index of a vector, - * and one swizzle, before getting to actual vec4 storage. So handle - * those, then go use ir_dereference to handle the rest. */ static struct ir_to_mesa_dst_reg -get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v, +get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v, ir_to_mesa_src_reg *r) { - struct ir_to_mesa_dst_reg dst_reg; - ir_swizzle *swiz; - + /* The LHS must be a dereference. If the LHS is a variable indexed array + * access of a vector, it must be separated into a series conditional moves + * before reaching this point (see ir_vec_index_to_cond_assign). + */ + assert(ir->as_dereference()); ir_dereference_array *deref_array = ir->as_dereference_array(); - /* This should have been handled by ir_vec_index_to_cond_assign */ if (deref_array) { assert(!deref_array->array->type->is_vector()); } @@ -1638,38 +1635,7 @@ get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v, * swizzles in it and write swizzles using writemask, though. */ ir->accept(v); - dst_reg = ir_to_mesa_dst_reg_from_src(v->result); - - if ((swiz = ir->as_swizzle())) { - int swizzles[4] = { - swiz->mask.x, - swiz->mask.y, - swiz->mask.z, - swiz->mask.w - }; - int new_r_swizzle[4]; - int orig_r_swizzle = r->swizzle; - int i; - - for (i = 0; i < 4; i++) { - new_r_swizzle[i] = GET_SWZ(orig_r_swizzle, 0); - } - - dst_reg.writemask = 0; - for (i = 0; i < 4; i++) { - if (i < swiz->mask.num_components) { - dst_reg.writemask |= 1 << swizzles[i]; - new_r_swizzle[swizzles[i]] = GET_SWZ(orig_r_swizzle, i); - } - } - - r->swizzle = MAKE_SWIZZLE4(new_r_swizzle[0], - new_r_swizzle[1], - new_r_swizzle[2], - new_r_swizzle[3]); - } - - return dst_reg; + return ir_to_mesa_dst_reg_from_src(v->result); } void @@ -1684,6 +1650,23 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) l = get_assignment_lhs(ir->lhs, this, &r); + /* FINISHME: This should really set to the correct maximal writemask for each + * FINISHME: component written (in the loops below). This case can only + * FINISHME: occur for matrices, arrays, and structures. + */ + if (ir->write_mask == 0) { + assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector()); + l.writemask = WRITEMASK_XYZW; + } else if (ir->lhs->type->is_scalar()) { + /* FINISHME: This hack makes writing to gl_FragData, which lives in the + * FINISHME: W component of fragment shader output zero, work correctly. + */ + l.writemask = WRITEMASK_XYZW; + } else { + assert(ir->lhs->type->is_vector()); + l.writemask = ir->write_mask; + } + assert(l.file != PROGRAM_UNDEFINED); assert(r.file != PROGRAM_UNDEFINED); -- cgit v1.2.3 From 455290e4281bf53ce2fe248a2adf5163563c44c8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 19:43:41 -0700 Subject: ir_to_mesa: Print shader source and compiled IR under MESA_GLSL=dump. While the Mesa IR dumping includes some corresponding GLSL IR for correlating Mesa IR to GLSL IR, it doesn't completely express it. This printing includes things like variable declarations and control flow structure that is hard to read otherwise. --- src/mesa/program/ir_to_mesa.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 1cec4aa621..2fd07ca611 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2545,7 +2545,14 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, set_branchtargets(&v, mesa_instructions, num_instructions); if (ctx->Shader.Flags & GLSL_DUMP) { - printf("Mesa %s program:\n", target_string); + printf("\n"); + printf("GLSL IR for linked %s program %d:\n", target_string, + shader_program->Name); + _mesa_print_ir(shader->ir, NULL); + printf("\n"); + printf("\n"); + printf("Mesa IR for linked %s program %d:\n", target_string, + shader_program->Name); print_program(mesa_instructions, mesa_instruction_annotation, num_instructions); } @@ -2635,6 +2642,15 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) _mesa_write_shader_to_file(shader); } + if (ctx->Shader.Flags & GLSL_DUMP) { + printf("GLSL source for shader %d:\n", shader->Name); + printf("%s\n", shader->Source); + + printf("GLSL IR for shader %d:\n", shader->Name); + _mesa_print_ir(shader->ir, NULL); + printf("\n\n"); + } + /* Retain any live IR, but trash the rest. */ reparent_ir(shader->ir, shader); -- cgit v1.2.3 From 9de2c4fc8e620ffe7faecd499c82d9d38ec538a6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 22:35:32 -0700 Subject: ir_to_mesa: Remove debug force-enablement of EmitNoIfs. --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 2fd07ca611..f0e013369a 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2614,7 +2614,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) progress = do_constant_folding(shader->ir) || progress; progress = do_algebraic(shader->ir) || progress; progress = do_if_return(shader->ir) || progress; - if (1 || ctx->Shader.EmitNoIfs) + if (ctx->Shader.EmitNoIfs) progress = do_if_to_cond_assign(shader->ir) || progress; progress = do_vec_index_to_swizzle(shader->ir) || progress; -- cgit v1.2.3 From 8f6a0c9ed985267c2d202cf85d17ac04bddfb9d2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 22:57:08 -0700 Subject: glsl2: Don't try to dump GLSL IR for a shader that didn't compile. --- src/mesa/program/ir_to_mesa.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index f0e013369a..74996ae480 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2646,9 +2646,11 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) printf("GLSL source for shader %d:\n", shader->Name); printf("%s\n", shader->Source); - printf("GLSL IR for shader %d:\n", shader->Name); - _mesa_print_ir(shader->ir, NULL); - printf("\n\n"); + if (shader->CompileStatus) { + printf("GLSL IR for shader %d:\n", shader->Name); + _mesa_print_ir(shader->ir, NULL); + printf("\n\n"); + } } /* Retain any live IR, but trash the rest. */ -- cgit v1.2.3 From e995f0e10c9ee51f7c8f8fa2193ff99e1b49e40d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Aug 2010 10:13:10 -0700 Subject: ir_to_mesa: Don't do function inlining until linking. Optimizations at compile time should generally be done with the goal of reducing instruction count so that other work, particularly linking, is less time-consuming if the shader is used multiple times. However, function inlining increases instruction count for the inlined function bodies without removing the original function body, since we don't know if it will be used at link time or not. Reduces the runtime of linking and executing a Yo Frankie fragment shader from 0.9 seconds to 0.5 seconds (-45.9%, +/- 2.2%, n=5). --- src/mesa/program/ir_to_mesa.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 74996ae480..299b11d274 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2604,7 +2604,6 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) do { progress = false; - progress = do_function_inlining(shader->ir) || progress; progress = do_if_simplification(shader->ir) || progress; progress = do_copy_propagation(shader->ir) || progress; progress = do_dead_code_local(shader->ir) || progress; -- cgit v1.2.3 From bc4034b243975089c06c4415d4e26edaaaec7a46 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Aug 2010 15:22:05 -0700 Subject: glsl2: Add a pass to convert exp and log to exp2 and log2. Fixes ir_to_mesa handling of unop_log, which used the weird ARB_vp LOG opcode that doesn't do what we want. This also lets the multiplication coefficients in there get constant-folded, possibly. Fixes: glsl-fs-log --- src/glsl/Makefile | 1 + src/glsl/ir.h | 4 +- src/glsl/ir_explog_to_explog2.cpp | 85 +++++++++++++++++++++++++++++++++++++++ src/glsl/ir_optimization.h | 1 + src/glsl/ir_validate.cpp | 4 ++ src/glsl/linker.cpp | 1 + src/mesa/program/ir_to_mesa.cpp | 7 +--- 7 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 src/glsl/ir_explog_to_explog2.cpp (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/Makefile b/src/glsl/Makefile index 53567508a0..752e60a79f 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -41,6 +41,7 @@ CXX_SOURCES = \ ir_dead_code_local.cpp \ ir_dead_functions.cpp \ ir_div_to_mul_rcp.cpp \ + ir_explog_to_explog2.cpp \ ir_expression_flattening.cpp \ ir_function_can_inline.cpp \ ir_function.cpp \ diff --git a/src/glsl/ir.h b/src/glsl/ir.h index ef8339ce19..5dc3c6b918 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -593,8 +593,8 @@ enum ir_expression_operation { ir_unop_rcp, ir_unop_rsq, ir_unop_sqrt, - ir_unop_exp, - ir_unop_log, + ir_unop_exp, /**< Log base e on gentype */ + ir_unop_log, /**< Natural log on gentype */ ir_unop_exp2, ir_unop_log2, ir_unop_f2i, /**< Float-to-integer conversion. */ diff --git a/src/glsl/ir_explog_to_explog2.cpp b/src/glsl/ir_explog_to_explog2.cpp new file mode 100644 index 0000000000..4fe1daaee9 --- /dev/null +++ b/src/glsl/ir_explog_to_explog2.cpp @@ -0,0 +1,85 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_explog_to_explog2.cpp + * + * Many GPUs don't have a base e log or exponent instruction, but they + * do have base 2 versions, so this pass converts exp and log to exp2 + * and log2 operations. + */ + +#include +#include "ir.h" +#include "glsl_types.h" + +class ir_explog_to_explog2_visitor : public ir_hierarchical_visitor { +public: + ir_explog_to_explog2_visitor() + { + this->progress = false; + } + + ir_visitor_status visit_leave(ir_expression *); + + bool progress; +}; + +bool +do_explog_to_explog2(exec_list *instructions) +{ + ir_explog_to_explog2_visitor v; + + visit_list_elements(&v, instructions); + return v.progress; +} + +ir_visitor_status +ir_explog_to_explog2_visitor::visit_leave(ir_expression *ir) +{ + if (ir->operation == ir_unop_exp) { + void *mem_ctx = talloc_parent(ir); + ir_constant *log2_e = new(mem_ctx) ir_constant(log2f(M_E)); + + ir->operation = ir_unop_exp2; + ir->operands[0] = new(mem_ctx) ir_expression(ir_binop_mul, + ir->operands[0]->type, + ir->operands[0], + log2_e); + this->progress = true; + } + + if (ir->operation == ir_unop_log) { + void *mem_ctx = talloc_parent(ir); + + ir->operation = ir_binop_mul; + ir->operands[0] = new(mem_ctx) ir_expression(ir_unop_log2, + ir->operands[0]->type, + ir->operands[0], + NULL); + ir->operands[1] = new(mem_ctx) ir_constant(1.0f / log2f(M_E)); + this->progress = true; + } + + return visit_continue; +} diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index eac28dc64c..c6e7beb447 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -38,6 +38,7 @@ bool do_dead_code_local(exec_list *instructions); bool do_dead_code_unlinked(exec_list *instructions); bool do_dead_functions(exec_list *instructions); bool do_div_to_mul_rcp(exec_list *instructions); +bool do_explog_to_explog2(exec_list *instructions); bool do_function_inlining(exec_list *instructions); bool do_if_return(exec_list *instructions); bool do_if_simplification(exec_list *instructions); diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 701bf21ea6..545fe2799f 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -183,10 +183,14 @@ ir_validate::visit_leave(ir_expression *ir) case ir_unop_rcp: case ir_unop_rsq: case ir_unop_sqrt: + assert(ir->type == ir->operands[0]->type); + break; + case ir_unop_exp: case ir_unop_log: case ir_unop_exp2: case ir_unop_log2: + assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); assert(ir->type == ir->operands[0]->type); break; diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 050116954a..9d6de242f5 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1281,6 +1281,7 @@ link_shaders(struct gl_shader_program *prog) do_mat_op_to_vec(ir); do_mod_to_fract(ir); do_div_to_mul_rcp(ir); + do_explog_to_explog2(ir); do { progress = false; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 299b11d274..26fbc4349a 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -752,15 +752,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir) ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[0]); break; - case ir_unop_exp: - ir_to_mesa_emit_scalar_op2(ir, OPCODE_POW, result_dst, - src_reg_for_float(M_E), op[0]); - break; case ir_unop_exp2: ir_to_mesa_emit_scalar_op1(ir, OPCODE_EX2, result_dst, op[0]); break; + case ir_unop_exp: case ir_unop_log: - ir_to_mesa_emit_scalar_op1(ir, OPCODE_LOG, result_dst, op[0]); + assert(!"not reached: should be handled by ir_explog_to_explog2"); break; case ir_unop_log2: ir_to_mesa_emit_scalar_op1(ir, OPCODE_LG2, result_dst, op[0]); -- cgit v1.2.3 From 0a86d766ef0d98abd3373609a637bf137203e994 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 5 Aug 2010 17:57:48 -0700 Subject: ir_to_mesa: Handle texture-array samplers Fixes piglit test array_texture. --- src/mesa/program/ir_to_mesa.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 26fbc4349a..f5e5f7d7b8 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2040,10 +2040,12 @@ ir_to_mesa_visitor::visit(ir_texture *ir) switch (sampler->type->sampler_dimensionality) { case GLSL_SAMPLER_DIM_1D: - inst->tex_target = TEXTURE_1D_INDEX; + inst->tex_target = (sampler->type->sampler_array) + ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX; break; case GLSL_SAMPLER_DIM_2D: - inst->tex_target = TEXTURE_2D_INDEX; + inst->tex_target = (sampler->type->sampler_array) + ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX; break; case GLSL_SAMPLER_DIM_3D: inst->tex_target = TEXTURE_3D_INDEX; -- cgit v1.2.3 From 658e25987fbec3b826f500baa6d4d936b9552b13 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Aug 2010 15:54:56 -0700 Subject: ir_to_mesa: Give the expected size for _mesa_add_attribute(). Fixes a failure in glean shaderAPI. --- src/mesa/program/ir_to_mesa.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index f5e5f7d7b8..9979e6e3e0 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -43,6 +43,7 @@ extern "C" { #include "main/mtypes.h" +#include "main/shaderapi.h" #include "main/shaderobj.h" #include "main/uniforms.h" #include "program/hash_table.h" @@ -1458,7 +1459,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) ir->var->location >= VERT_ATTRIB_GENERIC0) { _mesa_add_attribute(prog->Attributes, ir->var->name, - type_size(ir->var->type) * 4, + _mesa_sizeof_glsl_type(ir->var->type->gl_type), ir->var->type->gl_type, ir->var->location - VERT_ATTRIB_GENERIC0); } -- cgit v1.2.3 From 8d61a23b1a1d0d4b21f0fab64f6d863a8ee3d7f1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Aug 2010 16:00:46 -0700 Subject: glsl2: Don't assert in a couple of places when encountering sampler arrays. Fixes glean shaderAPI. --- src/glsl/linker.cpp | 10 ++++++---- src/mesa/program/ir_to_mesa.cpp | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 9d6de242f5..e93c2f5554 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -793,11 +793,13 @@ assign_uniform_locations(struct gl_shader_program *prog) if ((var == NULL) || (var->mode != ir_var_uniform)) continue; - if (var->type->is_sampler()) - continue; - const unsigned vec4_slots = (var->component_slots() + 3) / 4; - assert(vec4_slots != 0); + if (vec4_slots == 0) { + /* If we've got a sampler or an aggregate of them, the size can + * end up zero. Don't allocate any space. + */ + continue; + } uniform_node *n = (uniform_node *) hash_table_find(ht, var->name); if (n == NULL) { diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 9979e6e3e0..66b1a2f9d9 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -518,6 +518,11 @@ type_size(const struct glsl_type *type) size += type_size(type->fields.structure[i].type); } return size; + case GLSL_TYPE_SAMPLER: + /* Samplers take up no register space, since they're baked in at + * link time. + */ + return 0; default: assert(0); } -- cgit v1.2.3 From c234d0b25f622a7bdd3c40bc72fdbd59d8494c7c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Aug 2010 17:00:12 -0700 Subject: ir_to_mesa: Add support for sampler arrays. Support for samplers in general is still incomplete -- anything in a uniform struct will still be broken. But that doesn't appear to be any different from master. Fixes: glsl-fs-uniform-sampler-array.shader_test --- src/mesa/program/ir_to_mesa.cpp | 47 +++++++++++++++++++++++++++++++-------- src/mesa/program/prog_parameter.c | 7 +++--- src/mesa/program/prog_parameter.h | 2 +- 3 files changed, 43 insertions(+), 13 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 66b1a2f9d9..d8a13220ae 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1398,10 +1398,19 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) break; /* FINISHME: Fix up uniform name for arrays and things */ - if (ir->var->type->base_type == GLSL_TYPE_SAMPLER) { + if (ir->var->type->base_type == GLSL_TYPE_SAMPLER || + (ir->var->type->base_type == GLSL_TYPE_ARRAY && + ir->var->type->fields.array->base_type == GLSL_TYPE_SAMPLER)) { + int array_length; + + if (ir->var->type->base_type == GLSL_TYPE_ARRAY) + array_length = ir->var->type->length; + else + array_length = 1; int sampler = _mesa_add_sampler(this->prog->Parameters, ir->var->name, - ir->var->type->gl_type); + ir->var->type->gl_type, + array_length); set_sampler_location(ir->var, sampler); entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_SAMPLER, @@ -2035,22 +2044,42 @@ ir_to_mesa_visitor::visit(ir_texture *ir) if (ir->shadow_comparitor) inst->tex_shadow = GL_TRUE; - ir_dereference_variable *sampler = ir->sampler->as_dereference_variable(); - assert(sampler); /* FINISHME: sampler arrays */ + ir_variable *sampler = ir->sampler->variable_referenced(); + /* generate the mapping, remove when we generate storage at * declaration time */ - sampler->accept(this); + ir->sampler->accept(this); + + inst->sampler = get_sampler_location(sampler); + + ir_dereference_array *sampler_array = ir->sampler->as_dereference_array(); + if (sampler_array) { + ir_constant *array_index = + sampler_array->array_index->constant_expression_value(); + + /* GLSL 1.10 and 1.20 allowed variable sampler array indices, + * while GLSL 1.30 requires that the array indices be constant + * integer expressions. We don't expect any driver to actually + * work with a really variable array index, and in 1.20 all that + * would work would be an unrolled loop counter, so assert that + * we ended up with a constant at least.. + */ + assert(array_index); + inst->sampler += array_index->value.i[0]; + } - inst->sampler = get_sampler_location(sampler->var); + const glsl_type *sampler_type = sampler->type; + while (sampler_type->base_type == GLSL_TYPE_ARRAY) + sampler_type = sampler_type->fields.array; - switch (sampler->type->sampler_dimensionality) { + switch (sampler_type->sampler_dimensionality) { case GLSL_SAMPLER_DIM_1D: - inst->tex_target = (sampler->type->sampler_array) + inst->tex_target = (sampler_type->sampler_array) ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX; break; case GLSL_SAMPLER_DIM_2D: - inst->tex_target = (sampler->type->sampler_array) + inst->tex_target = (sampler_type->sampler_array) ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX; break; case GLSL_SAMPLER_DIM_3D: diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c index ddbfe95c15..fa5deaf127 100644 --- a/src/mesa/program/prog_parameter.c +++ b/src/mesa/program/prog_parameter.c @@ -344,18 +344,19 @@ _mesa_use_uniform(struct gl_program_parameter_list *paramList, */ GLint _mesa_add_sampler(struct gl_program_parameter_list *paramList, - const char *name, GLenum datatype) + const char *name, GLenum datatype, int array_length) { GLint i = _mesa_lookup_parameter_index(paramList, -1, name); if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) { - ASSERT(paramList->Parameters[i].Size == 1); + ASSERT(paramList->Parameters[i].Size == 4 * array_length); ASSERT(paramList->Parameters[i].DataType == datatype); /* already in list */ return (GLint) paramList->ParameterValues[i][0]; } else { GLuint i; - const GLint size = 1; /* a sampler is basically a texture unit number */ + /* One integer texture unit number goes in each parameter location. */ + const GLint size = 4 * array_length; GLfloat value[4]; GLint numSamplers = 0; for (i = 0; i < paramList->NumParameters; i++) { diff --git a/src/mesa/program/prog_parameter.h b/src/mesa/program/prog_parameter.h index cc3378ae20..1860f31287 100644 --- a/src/mesa/program/prog_parameter.h +++ b/src/mesa/program/prog_parameter.h @@ -142,7 +142,7 @@ _mesa_use_uniform(struct gl_program_parameter_list *paramList, extern GLint _mesa_add_sampler(struct gl_program_parameter_list *paramList, - const char *name, GLenum datatype); + const char *name, GLenum datatype, int array_length); extern GLint _mesa_add_varying(struct gl_program_parameter_list *paramList, -- cgit v1.2.3 From 925b49ff310bf0b307add7c34627cddf87e6a554 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 6 Aug 2010 13:07:25 -0700 Subject: glsl2: Move gl_program->InputsRead/OutputsWritten setting to an ir pass. This lets us handle arrays much better than trying to work backwards from assembly. Fixes fbo-drawbuffers-maxtargets on swrast (i965 needs loop unrolling) --- src/glsl/Makefile | 1 + src/glsl/ir.h | 3 + src/glsl/ir_set_program_inouts.cpp | 167 +++++++++++++++++++++++++++++++++++++ src/mesa/program/ir_to_mesa.cpp | 71 +--------------- 4 files changed, 175 insertions(+), 67 deletions(-) create mode 100644 src/glsl/ir_set_program_inouts.cpp (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/Makefile b/src/glsl/Makefile index 752e60a79f..0f8b290b65 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -56,6 +56,7 @@ CXX_SOURCES = \ ir_mod_to_fract.cpp \ ir_print_visitor.cpp \ ir_reader.cpp \ + ir_set_program_inouts.cpp \ ir_structure_splitting.cpp \ ir_swizzle_swizzle.cpp \ ir_tree_grafting.cpp \ diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 5dc3c6b918..d852a6a93b 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1392,4 +1392,7 @@ import_prototypes(const exec_list *source, exec_list *dest, extern bool ir_has_call(ir_instruction *ir); +extern void +do_set_program_inouts(exec_list *instructions, struct gl_program *prog); + #endif /* IR_H */ diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp new file mode 100644 index 0000000000..658637775a --- /dev/null +++ b/src/glsl/ir_set_program_inouts.cpp @@ -0,0 +1,167 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_set_program_inouts.cpp + * + * Sets the InputsRead and OutputsWritten of Mesa programs. + * + * Mesa programs (gl_program, not gl_shader_program) have a set of + * flags indicating which varyings are read and written. Computing + * which are actually read from some sort of backend code can be + * tricky when variable array indexing involved. So this pass + * provides support for setting InputsRead and OutputsWritten right + * from the GLSL IR. + */ + +extern "C" { +#include "main/mtypes.h" +#include "program/hash_table.h" +} +#include "ir.h" +#include "ir_visitor.h" +#include "glsl_types.h" + +class ir_set_program_inouts_visitor : public ir_hierarchical_visitor { +public: + ir_set_program_inouts_visitor(struct gl_program *prog) + { + this->prog = prog; + this->ht = hash_table_ctor(0, + hash_table_pointer_hash, + hash_table_pointer_compare); + } + ir_set_program_inouts_visitor() + { + hash_table_dtor(this->ht); + } + + virtual ir_visitor_status visit_enter(ir_dereference_array *); + virtual ir_visitor_status visit_enter(ir_function_signature *); + virtual ir_visitor_status visit(ir_dereference_variable *); + virtual ir_visitor_status visit(ir_variable *); + + struct gl_program *prog; + struct hash_table *ht; +}; + +static void +mark(struct gl_program *prog, ir_variable *var, int index) +{ + /* As of GLSL 1.20, varyings can only be floats, floating-point + * vectors or matrices, or arrays of them. For Mesa programs using + * InputsRead/OutputsWritten, everything but matrices uses one + * slot, while matrices use a slot per column. Presumably + * something doing a more clever packing would use something other + * than InputsRead/OutputsWritten. + */ + const glsl_type *element_type; + int element_size; + + if (var->type->is_array()) + element_type = var->type->fields.array; + else + element_type = var->type; + + if (element_type->is_matrix()) + element_size = element_type->matrix_columns; + else + element_size = 1; + + index *= element_size; + for (int i = 0; i < element_size; i++) { + if (var->mode == ir_var_in) + prog->InputsRead |= BITFIELD64_BIT(var->location + index + i); + else + prog->OutputsWritten |= BITFIELD64_BIT(var->location + index + i); + } +} + +/* Default handler: Mark all the locations in the variable as used. */ +ir_visitor_status +ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir) +{ + if (hash_table_find(this->ht, ir->var) == NULL) + return visit_continue; + + if (ir->type->is_array()) { + for (unsigned int i = 0; i < ir->type->length; i++) { + mark(this->prog, ir->var, i); + } + } else { + mark(this->prog, ir->var, 0); + } + + return visit_continue; +} + +ir_visitor_status +ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) +{ + ir_dereference_variable *deref_var; + ir_constant *index = ir->array_index->as_constant(); + deref_var = ir->array->as_dereference_variable(); + ir_variable *var = NULL; + + /* Check that we're dereferencing a shader in or out */ + if (deref_var) + var = (ir_variable *)hash_table_find(this->ht, deref_var->var); + + if (index && var) { + mark(this->prog, var, index->value.i[0]); + return visit_continue_with_parent; + } + + return visit_continue; +} + +ir_visitor_status +ir_set_program_inouts_visitor::visit(ir_variable *ir) +{ + if (ir->mode == ir_var_in || + ir->mode == ir_var_out) { + hash_table_insert(this->ht, ir, ir); + } + + return visit_continue; +} + +ir_visitor_status +ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir) +{ + /* We don't want to descend into the function parameters and + * consider them as shader inputs or outputs. + */ + visit_list_elements(this, &ir->body); + return visit_continue_with_parent; +} + +void +do_set_program_inouts(exec_list *instructions, struct gl_program *prog) +{ + ir_set_program_inouts_visitor v(prog); + + prog->InputsRead = 0; + prog->OutputsWritten = 0; + visit_list_elements(&v, instructions); +} diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index d8a13220ae..c6856eb5a4 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2323,81 +2323,15 @@ print_program(struct prog_instruction *mesa_instructions, } } -static void -mark_input(struct gl_program *prog, - int index, - GLboolean reladdr) -{ - prog->InputsRead |= BITFIELD64_BIT(index); - int i; - - if (reladdr) { - if (index >= FRAG_ATTRIB_TEX0 && index <= FRAG_ATTRIB_TEX7) { - for (i = 0; i < 8; i++) { - prog->InputsRead |= BITFIELD64_BIT(FRAG_ATTRIB_TEX0 + i); - } - } else { - assert(!"FINISHME: Mark InputsRead for varying arrays"); - } - } -} - -static void -mark_output(struct gl_program *prog, - int index, - GLboolean reladdr) -{ - prog->OutputsWritten |= BITFIELD64_BIT(index); - int i; - - if (reladdr) { - if (index >= VERT_RESULT_TEX0 && index <= VERT_RESULT_TEX7) { - for (i = 0; i < 8; i++) { - prog->OutputsWritten |= BITFIELD64_BIT(FRAG_ATTRIB_TEX0 + i); - } - } else { - assert(!"FINISHME: Mark OutputsWritten for varying arrays"); - } - } -} - static void count_resources(struct gl_program *prog) { unsigned int i; - prog->InputsRead = 0; - prog->OutputsWritten = 0; prog->SamplersUsed = 0; for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = &prog->Instructions[i]; - unsigned int reg; - - switch (inst->DstReg.File) { - case PROGRAM_OUTPUT: - mark_output(prog, inst->DstReg.Index, inst->DstReg.RelAddr); - break; - case PROGRAM_INPUT: - mark_input(prog, inst->DstReg.Index, inst->DstReg.RelAddr); - break; - default: - break; - } - - for (reg = 0; reg < _mesa_num_inst_src_regs(inst->Opcode); reg++) { - switch (inst->SrcReg[reg].File) { - case PROGRAM_OUTPUT: - mark_output(prog, inst->SrcReg[reg].Index, - inst->SrcReg[reg].RelAddr); - break; - case PROGRAM_INPUT: - mark_input(prog, inst->SrcReg[reg].Index, inst->SrcReg[reg].RelAddr); - break; - default: - break; - } - } /* Instead of just using the uniform's value to map to a * sampler, Mesa first allocates a separate number for the @@ -2578,6 +2512,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, } set_branchtargets(&v, mesa_instructions, num_instructions); + if (ctx->Shader.Flags & GLSL_DUMP) { printf("\n"); printf("GLSL IR for linked %s program %d:\n", target_string, @@ -2594,6 +2529,9 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, prog->Instructions = mesa_instructions; prog->NumInstructions = num_instructions; + do_set_program_inouts(shader->ir, prog); + count_resources(prog); + _mesa_reference_program(ctx, &shader->Program, prog); if ((ctx->Shader.Flags & GLSL_NO_OPT) == 0) { @@ -2731,7 +2669,6 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); - count_resources(linked_prog); link_uniforms_to_shared_uniform_list(prog->Uniforms, linked_prog); -- cgit v1.2.3 From 8bebbeb7c5b26ec9166a4644a2c051238d18509b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 Aug 2010 17:03:46 -0700 Subject: glsl2: Add constant propagation. Whereas constant folding evaluates constant expressions at rvalue nodes, constant propagation tracks constant components of vectors across execution to replace (possibly swizzled) variable dereferences with constant values, triggering possible constant folding or reduced variable liveness. --- src/glsl/Makefile | 1 + src/glsl/ir_constant_propagation.cpp | 481 +++++++++++++++++++++++++++++++++++ src/glsl/ir_optimization.h | 1 + src/glsl/linker.cpp | 1 + src/glsl/main.cpp | 1 + src/mesa/program/ir_to_mesa.cpp | 1 + 6 files changed, 486 insertions(+) create mode 100644 src/glsl/ir_constant_propagation.cpp (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/Makefile b/src/glsl/Makefile index 0f8b290b65..841e2b9ce9 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -34,6 +34,7 @@ CXX_SOURCES = \ ir_clone.cpp \ ir_constant_expression.cpp \ ir_constant_folding.cpp \ + ir_constant_propagation.cpp \ ir_constant_variable.cpp \ ir_copy_propagation.cpp \ ir.cpp \ diff --git a/src/glsl/ir_constant_propagation.cpp b/src/glsl/ir_constant_propagation.cpp new file mode 100644 index 0000000000..adae0aa117 --- /dev/null +++ b/src/glsl/ir_constant_propagation.cpp @@ -0,0 +1,481 @@ +/* + * Constantright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * constant of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, constant, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above constantright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR CONSTANTRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_constant_propagation.cpp + * + * Tracks assignments of constants to channels of variables, and + * usage of those constant channels with direct usage of the constants. + * + * This can lead to constant folding and algebraic optimizations in + * those later expressions, while causing no increase in instruction + * count (due to constants being generally free to load from a + * constant push buffer or as instruction immediate values) and + * possibly reducing register pressure. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_basic_block.h" +#include "ir_optimization.h" +#include "glsl_types.h" + +class acp_entry : public exec_node +{ +public: + acp_entry(ir_variable *var, unsigned write_mask, ir_constant *constant) + { + assert(var); + assert(constant); + this->var = var; + this->write_mask = write_mask; + this->constant = constant; + } + + ir_variable *var; + ir_constant *constant; + unsigned write_mask; +}; + + +class kill_entry : public exec_node +{ +public: + kill_entry(ir_variable *var, unsigned write_mask) + { + assert(var); + this->var = var; + this->write_mask = write_mask; + } + + ir_variable *var; + unsigned write_mask; +}; + +class ir_constant_propagation_visitor : public ir_hierarchical_visitor { +public: + ir_constant_propagation_visitor() + { + progress = false; + mem_ctx = talloc_new(0); + this->acp = new(mem_ctx) exec_list; + this->kills = new(mem_ctx) exec_list; + } + ~ir_constant_propagation_visitor() + { + talloc_free(mem_ctx); + } + + virtual ir_visitor_status visit_enter(class ir_loop *); + virtual ir_visitor_status visit_enter(class ir_function_signature *); + virtual ir_visitor_status visit_enter(class ir_function *); + virtual ir_visitor_status visit_enter(class ir_assignment *); + virtual ir_visitor_status visit_leave(class ir_assignment *); + virtual ir_visitor_status visit_enter(class ir_expression *); + virtual ir_visitor_status visit_enter(class ir_call *); + virtual ir_visitor_status visit_enter(class ir_if *); + virtual ir_visitor_status visit_enter(class ir_dereference_array *); + virtual ir_visitor_status visit_enter(class ir_texture *); + + void add_constant(ir_assignment *ir); + void kill(ir_variable *ir, unsigned write_mask); + void handle_if_block(exec_list *instructions); + void handle_rvalue(ir_rvalue **rvalue); + + /** List of acp_entry: The available constants to propagate */ + exec_list *acp; + + /** + * List of kill_entry: The masks of variables whose values were + * killed in this block. + */ + exec_list *kills; + + bool progress; + + bool killed_all; + + void *mem_ctx; +}; + + +void +ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (!*rvalue) + return; + + const glsl_type *type = (*rvalue)->type; + if (!type->is_scalar() && !type->is_vector()) + return; + + ir_swizzle *swiz = NULL; + ir_dereference_variable *deref = (*rvalue)->as_dereference_variable(); + if (!deref) { + swiz = (*rvalue)->as_swizzle(); + if (!swiz) + return; + + deref = swiz->val->as_dereference_variable(); + if (!deref) + return; + } + + ir_constant_data data; + memset(&data, 0, sizeof(data)); + + for (unsigned int i = 0; i < type->components(); i++) { + int channel; + acp_entry *found = NULL; + + if (swiz) { + switch (i) { + case 0: channel = swiz->mask.x; break; + case 1: channel = swiz->mask.y; break; + case 2: channel = swiz->mask.z; break; + case 3: channel = swiz->mask.w; break; + default: assert(!"shouldn't be reached"); channel = 0; break; + } + } else { + channel = i; + } + + foreach_iter(exec_list_iterator, iter, *this->acp) { + acp_entry *entry = (acp_entry *)iter.get(); + if (entry->var == deref->var && entry->write_mask & (1 << channel)) { + found = entry; + break; + } + } + + if (!found) + return; + + switch (type->base_type) { + case GLSL_TYPE_FLOAT: + data.f[i] = found->constant->value.f[channel]; + break; + case GLSL_TYPE_INT: + data.i[i] = found->constant->value.i[channel]; + break; + case GLSL_TYPE_UINT: + data.u[i] = found->constant->value.u[channel]; + break; + case GLSL_TYPE_BOOL: + data.b[i] = found->constant->value.b[channel]; + break; + default: + assert(!"not reached"); + break; + } + } + + *rvalue = new(talloc_parent(deref)) ir_constant(type, &data); + this->progress = true; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_function_signature *ir) +{ + /* Treat entry into a function signature as a completely separate + * block. Any instructions at global scope will be shuffled into + * main() at link time, so they're irrelevant to us. + */ + exec_list *orig_acp = this->acp; + exec_list *orig_kills = this->kills; + bool orig_killed_all = this->killed_all; + + this->acp = new(mem_ctx) exec_list; + this->kills = new(mem_ctx) exec_list; + this->killed_all = false; + + visit_list_elements(this, &ir->body); + + this->kills = orig_kills; + this->acp = orig_acp; + this->killed_all = orig_killed_all; + + return visit_continue_with_parent; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_assignment *ir) +{ + handle_rvalue(&ir->condition); + handle_rvalue(&ir->rhs); + + return visit_continue; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_leave(ir_assignment *ir) +{ + kill(ir->lhs->variable_referenced(), ir->write_mask); + + add_constant(ir); + + return visit_continue; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_expression *ir) +{ + for (unsigned int i = 0; i < ir->get_num_operands(); i++) { + handle_rvalue(&ir->operands[i]); + } + + return visit_continue; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_function *ir) +{ + (void) ir; + return visit_continue; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_call *ir) +{ + /* Do constant propagation on call parameters, but skip any out params */ + exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator(); + foreach_iter(exec_list_iterator, iter, ir->actual_parameters) { + ir_variable *sig_param = (ir_variable *)sig_param_iter.get(); + ir_rvalue *param = (ir_rvalue *)iter.get(); + if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) { + ir_rvalue *new_param = param; + handle_rvalue(&new_param); + if (new_param != param) + param->replace_with(new_param); + else + param->accept(this); + } + sig_param_iter.next(); + } + + /* Since we're unlinked, we don't (necssarily) know the side effects of + * this call. So kill all copies. + */ + acp->make_empty(); + this->killed_all = true; + + return visit_continue_with_parent; +} + +void +ir_constant_propagation_visitor::handle_if_block(exec_list *instructions) +{ + exec_list *orig_acp = this->acp; + exec_list *orig_kills = this->kills; + bool orig_killed_all = this->killed_all; + + this->acp = new(mem_ctx) exec_list; + this->kills = new(mem_ctx) exec_list; + this->killed_all = false; + + /* Populate the initial acp with a constant of the original */ + foreach_iter(exec_list_iterator, iter, *orig_acp) { + acp_entry *a = (acp_entry *)iter.get(); + this->acp->push_tail(new(this->mem_ctx) acp_entry(a->var, a->write_mask, + a->constant)); + } + + visit_list_elements(this, instructions); + + if (this->killed_all) { + orig_acp->make_empty(); + } + + exec_list *new_kills = this->kills; + this->kills = orig_kills; + this->acp = orig_acp; + this->killed_all = this->killed_all || orig_killed_all; + + foreach_iter(exec_list_iterator, iter, *new_kills) { + kill_entry *k = (kill_entry *)iter.get(); + kill(k->var, k->write_mask); + } +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_if *ir) +{ + ir->condition->accept(this); + handle_rvalue(&ir->condition); + + handle_if_block(&ir->then_instructions); + handle_if_block(&ir->else_instructions); + + /* handle_if_block() already descended into the children. */ + return visit_continue_with_parent; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_dereference_array *ir) +{ + handle_rvalue(&ir->array_index); + return visit_continue; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_texture *ir) +{ + handle_rvalue(&ir->coordinate); + handle_rvalue(&ir->projector); + handle_rvalue(&ir->shadow_comparitor); + + switch (ir->op) { + case ir_tex: + break; + case ir_txb: + handle_rvalue(&ir->lod_info.bias); + break; + case ir_txf: + case ir_txl: + handle_rvalue(&ir->lod_info.lod); + break; + case ir_txd: + handle_rvalue(&ir->lod_info.grad.dPdx); + handle_rvalue(&ir->lod_info.grad.dPdy); + break; + } + + return visit_continue; +} + +ir_visitor_status +ir_constant_propagation_visitor::visit_enter(ir_loop *ir) +{ + exec_list *orig_acp = this->acp; + exec_list *orig_kills = this->kills; + bool orig_killed_all = this->killed_all; + + /* FINISHME: For now, the initial acp for loops is totally empty. + * We could go through once, then go through again with the acp + * cloned minus the killed entries after the first run through. + */ + this->acp = new(mem_ctx) exec_list; + this->kills = new(mem_ctx) exec_list; + this->killed_all = false; + + visit_list_elements(this, &ir->body_instructions); + + if (this->killed_all) { + orig_acp->make_empty(); + } + + exec_list *new_kills = this->kills; + this->kills = orig_kills; + this->acp = orig_acp; + this->killed_all = this->killed_all || orig_killed_all; + + foreach_iter(exec_list_iterator, iter, *new_kills) { + kill_entry *k = (kill_entry *)iter.get(); + kill(k->var, k->write_mask); + } + + /* already descended into the children. */ + return visit_continue_with_parent; +} + +void +ir_constant_propagation_visitor::kill(ir_variable *var, unsigned write_mask) +{ + assert(var != NULL); + + /* We don't track non-vectors. */ + if (!var->type->is_vector() && !var->type->is_scalar()) + return; + + /* Remove any entries currently in the ACP for this kill. */ + foreach_iter(exec_list_iterator, iter, *this->acp) { + acp_entry *entry = (acp_entry *)iter.get(); + + if (entry->var == var) { + entry->write_mask &= ~write_mask; + if (entry->write_mask == 0) + entry->remove(); + } + } + + /* Add this writemask of the variable to the list of killed + * variables in this block. + */ + foreach_iter(exec_list_iterator, iter, *this->kills) { + kill_entry *entry = (kill_entry *)iter.get(); + + if (entry->var == var) { + entry->write_mask |= write_mask; + return; + } + } + /* Not already in the list. Make new entry. */ + this->kills->push_tail(new(this->mem_ctx) kill_entry(var, write_mask)); +} + +/** + * Adds an entry to the available constant list if it's a plain assignment + * of a variable to a variable. + */ +void +ir_constant_propagation_visitor::add_constant(ir_assignment *ir) +{ + acp_entry *entry; + + if (ir->condition) { + ir_constant *condition = ir->condition->as_constant(); + if (!condition || !condition->value.b[0]) + return; + } + + if (!ir->write_mask) + return; + + ir_dereference_variable *deref = ir->lhs->as_dereference_variable(); + ir_constant *constant = ir->rhs->as_constant(); + + if (!deref || !constant) + return; + + /* Only do constant propagation on vectors. Constant matrices, + * arrays, or structures would require more work elsewhere. + */ + if (!deref->var->type->is_vector() && !deref->var->type->is_scalar()) + return; + + entry = new(this->mem_ctx) acp_entry(deref->var, ir->write_mask, constant); + this->acp->push_tail(entry); +} + +/** + * Does a constant propagation pass on the code present in the instruction stream. + */ +bool +do_constant_propagation(exec_list *instructions) +{ + ir_constant_propagation_visitor v; + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index c6e7beb447..97a0c25216 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -33,6 +33,7 @@ bool do_constant_folding(exec_list *instructions); bool do_constant_variable(exec_list *instructions); bool do_constant_variable_unlinked(exec_list *instructions); bool do_copy_propagation(exec_list *instructions); +bool do_constant_propagation(exec_list *instructions); bool do_dead_code(exec_list *instructions); bool do_dead_code_local(exec_list *instructions); bool do_dead_code_unlinked(exec_list *instructions); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index e93c2f5554..52c9322788 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1296,6 +1296,7 @@ link_shaders(struct gl_shader_program *prog) progress = do_dead_code_local(ir) || progress; progress = do_dead_code(ir) || progress; progress = do_tree_grafting(ir) || progress; + progress = do_constant_propagation(ir) || progress; progress = do_constant_variable(ir) || progress; progress = do_constant_folding(ir) || progress; progress = do_algebraic(ir) || progress; diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index bc7292d155..24d6076d07 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -167,6 +167,7 @@ compile_shader(struct gl_shader *shader) progress = do_dead_code_local(shader->ir) || progress; progress = do_dead_code_unlinked(shader->ir) || progress; progress = do_tree_grafting(shader->ir) || progress; + progress = do_constant_propagation(shader->ir) || progress; progress = do_constant_variable_unlinked(shader->ir) || progress; progress = do_constant_folding(shader->ir) || progress; progress = do_algebraic(shader->ir) || progress; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index c6856eb5a4..5a272ab88a 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2581,6 +2581,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) progress = do_dead_code_local(shader->ir) || progress; progress = do_dead_code_unlinked(shader->ir) || progress; progress = do_tree_grafting(shader->ir) || progress; + progress = do_constant_propagation(shader->ir) || progress; progress = do_constant_variable_unlinked(shader->ir) || progress; progress = do_constant_folding(shader->ir) || progress; progress = do_algebraic(shader->ir) || progress; -- cgit v1.2.3 From 5854d4583c6e8885185e12a0636f77489a62e24c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 Aug 2010 21:22:17 -0700 Subject: glsl2: Add a pass to transform ir_binop_sub to add(op0, neg(op1)) All the current HW backends transform subtract to adding the negation, so I haven't bothered peepholing it back out in Mesa IR. This allows some subtract of subtract to get removed in ir_algebraic. --- src/glsl/Makefile | 1 + src/glsl/ir_optimization.h | 1 + src/glsl/ir_sub_to_add_neg.cpp | 76 +++++++++++++++++++++++++++++++++++++++++ src/glsl/linker.cpp | 1 + src/mesa/program/ir_to_mesa.cpp | 1 + 5 files changed, 80 insertions(+) create mode 100644 src/glsl/ir_sub_to_add_neg.cpp (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/Makefile b/src/glsl/Makefile index 841e2b9ce9..85298d06a0 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -59,6 +59,7 @@ CXX_SOURCES = \ ir_reader.cpp \ ir_set_program_inouts.cpp \ ir_structure_splitting.cpp \ + ir_sub_to_add_neg.cpp \ ir_swizzle_swizzle.cpp \ ir_tree_grafting.cpp \ ir_validate.cpp \ diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 97a0c25216..5997a30eab 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -47,6 +47,7 @@ bool do_if_to_cond_assign(exec_list *instructions); bool do_mat_op_to_vec(exec_list *instructions); bool do_mod_to_fract(exec_list *instructions); bool do_structure_splitting(exec_list *instructions); +bool do_sub_to_add_neg(exec_list *instructions); bool do_swizzle_swizzle(exec_list *instructions); bool do_tree_grafting(exec_list *instructions); bool do_vec_index_to_cond_assign(exec_list *instructions); diff --git a/src/glsl/ir_sub_to_add_neg.cpp b/src/glsl/ir_sub_to_add_neg.cpp new file mode 100644 index 0000000000..7ed8c1495e --- /dev/null +++ b/src/glsl/ir_sub_to_add_neg.cpp @@ -0,0 +1,76 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_sub_to_add_neg.cpp + * + * Breaks an ir_binop_sub expression down to add(op0, neg(op1)) + * + * This simplifies expression reassociation, and for many backends + * there is no subtract operation separate from adding the negation. + * For backends with native subtract operations, they will probably + * want to recognize add(op0, neg(op1)) or the other way around to + * produce a subtract anyway. + */ + +#include "ir.h" + +class ir_sub_to_add_neg_visitor : public ir_hierarchical_visitor { +public: + ir_sub_to_add_neg_visitor() + { + this->progress = false; + } + + ir_visitor_status visit_leave(ir_expression *); + + bool progress; +}; + +bool +do_sub_to_add_neg(exec_list *instructions) +{ + ir_sub_to_add_neg_visitor v; + + visit_list_elements(&v, instructions); + return v.progress; +} + +ir_visitor_status +ir_sub_to_add_neg_visitor::visit_leave(ir_expression *ir) +{ + if (ir->operation != ir_binop_sub) + return visit_continue; + + void *mem_ctx = talloc_parent(ir); + + ir->operation = ir_binop_add; + ir->operands[1] = new(mem_ctx) ir_expression(ir_unop_neg, + ir->operands[1]->type, + ir->operands[1], + NULL); + + this->progress = true; + + return visit_continue; +} diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 52c9322788..c462d31ef3 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1284,6 +1284,7 @@ link_shaders(struct gl_shader_program *prog) do_mod_to_fract(ir); do_div_to_mul_rcp(ir); do_explog_to_explog2(ir); + do_sub_to_add_neg(ir); do { progress = false; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 5a272ab88a..a9a6f977c0 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2570,6 +2570,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) do_mat_op_to_vec(shader->ir); do_mod_to_fract(shader->ir); do_div_to_mul_rcp(shader->ir); + do_sub_to_add_neg(shader->ir); /* Optimization passes */ bool progress; -- cgit v1.2.3 From 261bbc011d11ab9e390cd5fe9f5151821eefaffa Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 12 Aug 2010 15:05:39 -0700 Subject: glsl2: Use Elements from main/compiler.h instead of open-coding --- src/glsl/builtin_function.cpp | 5 +---- src/glsl/builtin_types.h | 4 ---- src/glsl/builtins/tools/generate_builtins.pl | 5 +---- src/glsl/glsl_types.cpp | 1 + src/glsl/ir_variable.cpp | 5 +---- src/mesa/program/ir_to_mesa.cpp | 1 + 6 files changed, 5 insertions(+), 16 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp index 12e6909a28..1d9a58a5ca 100644 --- a/src/glsl/builtin_function.cpp +++ b/src/glsl/builtin_function.cpp @@ -23,6 +23,7 @@ */ #include +#include "main/compiler.h" #include "glsl_parser_extras.h" #include "ir_reader.h" #include "program.h" @@ -4799,10 +4800,6 @@ static const char *functions_for_EXT_texture_array_fs [] = { builtins_EXT_texture_array_fs_textures, }; -#ifndef Elements -#define Elements(x) (sizeof(x)/sizeof(*(x))) -#endif - void *builtin_mem_ctx = NULL; void diff --git a/src/glsl/builtin_types.h b/src/glsl/builtin_types.h index bfa4f3f540..7b94aac666 100644 --- a/src/glsl/builtin_types.h +++ b/src/glsl/builtin_types.h @@ -21,10 +21,6 @@ * DEALINGS IN THE SOFTWARE. */ -#ifndef Elements -#define Elements(x) (sizeof(x)/sizeof(*(x))) -#endif - const glsl_type glsl_type::_error_type = glsl_type(GL_INVALID_ENUM, GLSL_TYPE_ERROR, 0, 0, ""); diff --git a/src/glsl/builtins/tools/generate_builtins.pl b/src/glsl/builtins/tools/generate_builtins.pl index 61d511da1d..91ef8917b0 100755 --- a/src/glsl/builtins/tools/generate_builtins.pl +++ b/src/glsl/builtins/tools/generate_builtins.pl @@ -62,6 +62,7 @@ print << 'EOF'; */ #include +#include "main/compiler.h" #include "glsl_parser_extras.h" #include "ir_reader.h" #include "program.h" @@ -110,10 +111,6 @@ foreach $version (@versions) { } print << 'EOF'; -#ifndef Elements -#define Elements(x) (sizeof(x)/sizeof(*(x))) -#endif - void *builtin_mem_ctx = NULL; void diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index 2aba1e0ac1..8e80cf99e9 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -23,6 +23,7 @@ #include #include +#include "main/compiler.h" #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "glsl_types.h" diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index d88cb515b4..917c06743b 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -21,15 +21,12 @@ * DEALINGS IN THE SOFTWARE. */ +#include "main/compiler.h" #include "ir.h" #include "glsl_parser_extras.h" #include "glsl_symbol_table.h" #include "builtin_variables.h" -#ifndef Elements -#define Elements(x) (sizeof(x)/sizeof(*(x))) -#endif - static void generate_ARB_draw_buffers_variables(exec_list *, struct _mesa_glsl_parse_state *, bool, _mesa_glsl_parser_targets); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index a9a6f977c0..ecb13069cb 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -31,6 +31,7 @@ */ #include +#include "main/compiler.h" #include "ir.h" #include "ir_visitor.h" #include "ir_print_visitor.h" -- cgit v1.2.3 From 2f4fe151681a6f6afe1d452eece6cf4144f44e49 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Aug 2010 13:06:49 -0700 Subject: glsl2: Move the common optimization passes to a helper function. These are passes that we expect all codegen to be happy with. The other lowering passes for Mesa IR are moved to the Mesa IR generator. --- src/glsl/glsl_parser_extras.cpp | 35 +++++++++++++++++++++++ src/glsl/ir_optimization.h | 2 ++ src/glsl/linker.cpp | 47 ++++--------------------------- src/mesa/program/ir_to_mesa.cpp | 61 ++++++++++++++++++++--------------------- 4 files changed, 72 insertions(+), 73 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index dbf6f53156..2ed3905abc 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -33,6 +33,7 @@ extern "C" { #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_parser.h" +#include "ir_optimization.h" _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct __GLcontextRec *ctx, GLenum target, void *mem_ctx) @@ -705,3 +706,37 @@ ast_struct_specifier::ast_struct_specifier(char *identifier, name = identifier; this->declarations.push_degenerate_list_at_head(&declarator_list->link); } + +bool +do_common_optimization(exec_list *ir, bool linked) +{ + GLboolean progress = GL_FALSE; + + progress = do_sub_to_add_neg(ir) || progress; + + if (linked) { + progress = do_function_inlining(ir) || progress; + progress = do_dead_functions(ir) || progress; + } + progress = do_structure_splitting(ir) || progress; + progress = do_if_simplification(ir) || progress; + progress = do_copy_propagation(ir) || progress; + if (linked) + progress = do_dead_code(ir) || progress; + else + progress = do_dead_code_unlinked(ir) || progress; + progress = do_dead_code_local(ir) || progress; + progress = do_tree_grafting(ir) || progress; + progress = do_constant_propagation(ir) || progress; + if (linked) + progress = do_constant_variable(ir) || progress; + else + progress = do_constant_variable_unlinked(ir) || progress; + progress = do_constant_folding(ir) || progress; + progress = do_algebraic(ir) || progress; + progress = do_if_return(ir) || progress; + progress = do_vec_index_to_swizzle(ir) || progress; + progress = do_swizzle_swizzle(ir) || progress; + + return progress; +} diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 5997a30eab..0c4e548e44 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -28,6 +28,8 @@ * Prototypes for optimization passes to be called by the compiler and drivers. */ +bool do_common_optimization(exec_list *ir, bool linked); + bool do_algebraic(exec_list *instructions); bool do_constant_folding(exec_list *instructions); bool do_constant_variable(exec_list *instructions); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 7bff859d55..9931251f40 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1308,48 +1308,13 @@ link_shaders(struct gl_shader_program *prog) prog->LinkStatus = true; } - /* FINISHME: Perform whole-program optimization here. */ + /* Do common optimization before assigning storage for attributes, + * uniforms, and varyings. Later optimization could possibly make + * some of that unused. + */ for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { - /* Optimization passes */ - bool progress; - exec_list *ir = prog->_LinkedShaders[i]->ir; - - /* Lowering */ - do_mat_op_to_vec(ir); - do_mod_to_fract(ir); - do_div_to_mul_rcp(ir); - do_explog_to_explog2(ir); - do_sub_to_add_neg(ir); - - do { - progress = false; - - progress = do_function_inlining(ir) || progress; - progress = do_dead_functions(ir) || progress; - progress = do_structure_splitting(ir) || progress; - progress = do_if_simplification(ir) || progress; - progress = do_copy_propagation(ir) || progress; - progress = do_dead_code_local(ir) || progress; - progress = do_dead_code(ir) || progress; - progress = do_tree_grafting(ir) || progress; - progress = do_constant_propagation(ir) || progress; - progress = do_constant_variable(ir) || progress; - progress = do_constant_folding(ir) || progress; - progress = do_algebraic(ir) || progress; - progress = do_if_return(ir) || progress; -#if 0 - if (ctx->Shader.EmitNoIfs) - progress = do_if_to_cond_assign(ir) || progress; -#endif - - progress = do_vec_index_to_swizzle(ir) || progress; - /* Do this one after the previous to let the easier pass handle - * constant vector indexing. - */ - progress = do_vec_index_to_cond_assign(ir) || progress; - - progress = do_swizzle_swizzle(ir) || progress; - } while (progress); + while (do_common_optimization(prog->_LinkedShaders[i]->ir, true)) + ; } assign_uniform_locations(prog); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index ecb13069cb..c8c655b296 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2567,38 +2567,11 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) if (!state->error && !shader->ir->is_empty()) { validate_ir_tree(shader->ir); - /* Lowering */ - do_mat_op_to_vec(shader->ir); - do_mod_to_fract(shader->ir); - do_div_to_mul_rcp(shader->ir); - do_sub_to_add_neg(shader->ir); - - /* Optimization passes */ - bool progress; - do { - progress = false; - - progress = do_if_simplification(shader->ir) || progress; - progress = do_copy_propagation(shader->ir) || progress; - progress = do_dead_code_local(shader->ir) || progress; - progress = do_dead_code_unlinked(shader->ir) || progress; - progress = do_tree_grafting(shader->ir) || progress; - progress = do_constant_propagation(shader->ir) || progress; - progress = do_constant_variable_unlinked(shader->ir) || progress; - progress = do_constant_folding(shader->ir) || progress; - progress = do_algebraic(shader->ir) || progress; - progress = do_if_return(shader->ir) || progress; - if (ctx->Shader.EmitNoIfs) - progress = do_if_to_cond_assign(shader->ir) || progress; - - progress = do_vec_index_to_swizzle(shader->ir) || progress; - /* Do this one after the previous to let the easier pass handle - * constant vector indexing. - */ - progress = do_vec_index_to_cond_assign(shader->ir) || progress; - - progress = do_swizzle_swizzle(shader->ir) || progress; - } while (progress); + /* Do some optimization at compile time to reduce shader IR size + * and reduce later work if the same shader is linked multiple times + */ + while (do_common_optimization(shader->ir, false)) + ; validate_ir_tree(shader->ir); } @@ -2665,6 +2638,30 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) prog->Uniforms = _mesa_new_uniform_list(); } + if (prog->LinkStatus) { + for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { + bool progress; + exec_list *ir = prog->_LinkedShaders[i]->ir; + + do { + progress = false; + + /* Lowering */ + do_mat_op_to_vec(ir); + do_mod_to_fract(ir); + do_div_to_mul_rcp(ir); + do_explog_to_explog2(ir); + + progress = do_common_optimization(ir, true) || progress; + + if (ctx->Shader.EmitNoIfs) + progress = do_if_to_cond_assign(ir) || progress; + + progress = do_vec_index_to_cond_assign(ir) || progress; + } while (progress); + } + } + if (prog->LinkStatus) { for (i = 0; i < prog->_NumLinkedShaders; i++) { struct gl_program *linked_prog; -- cgit v1.2.3 From d19eecef54384c163af27a470496ed885a5a271b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Aug 2010 20:11:44 -0700 Subject: glsl2: Move ir_to_mesa handling to driver CompileShader and LinkShader hooks. This lets drivers override ir_to_mesa with their own codegen, or at least have a native alternative. --- src/mesa/main/dd.h | 21 +++++++ src/mesa/main/shaderobj.c | 2 + src/mesa/program/ir_to_mesa.cpp | 126 +++++++++++++++++++++++----------------- src/mesa/program/ir_to_mesa.h | 2 + 4 files changed, 99 insertions(+), 52 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 825073ca88..71d0f570e4 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -595,6 +595,27 @@ struct dd_function_table { /*@}*/ + /** + * \name GLSL shader/program functions. + */ + /*@{*/ + /** + * Called when a shader is compiled. + * + * Note that not all shader objects get ShaderCompile called on + * them. Notably, the shaders containing builtin functions do not + * have CompileShader() called, so if lowering passes are done they + * need to also be performed in LinkShader(). + */ + GLboolean (*CompileShader)(GLcontext *ctx, struct gl_shader *shader); + /** + * Called when a shader program is linked. + * + * This gives drivers an opportunity to clone the IR and make their + * own transformations on it for the purposes of code generation. + */ + GLboolean (*LinkShader)(GLcontext *ctx, struct gl_shader_program *shader); + /*@}*/ /** * \name State-changing functions. diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index 129d974224..863d50fbe5 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -387,4 +387,6 @@ _mesa_init_shader_object_functions(struct dd_function_table *driver) driver->DeleteShader = __mesa_delete_shader; driver->NewShaderProgram = _mesa_new_shader_program; driver->DeleteShaderProgram = __mesa_delete_shader_program; + driver->CompileShader = _mesa_ir_compile_shader; + driver->LinkShader = _mesa_ir_link_shader; } diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index c8c655b296..7490ffa4fe 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2543,6 +2543,72 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, } extern "C" { +GLboolean +_mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader) +{ + assert(shader->CompileStatus); + + return GL_TRUE; +} + +GLboolean +_mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog) +{ + assert(prog->LinkStatus); + + for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { + bool progress; + exec_list *ir = prog->_LinkedShaders[i]->ir; + + do { + progress = false; + + /* Lowering */ + do_mat_op_to_vec(ir); + do_mod_to_fract(ir); + do_div_to_mul_rcp(ir); + do_explog_to_explog2(ir); + + progress = do_common_optimization(ir, true) || progress; + + if (ctx->Shader.EmitNoIfs) + progress = do_if_to_cond_assign(ir) || progress; + + progress = do_vec_index_to_cond_assign(ir) || progress; + } while (progress); + + validate_ir_tree(ir); + } + + for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { + struct gl_program *linked_prog; + bool ok = true; + + linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); + + link_uniforms_to_shared_uniform_list(prog->Uniforms, linked_prog); + + switch (prog->_LinkedShaders[i]->Type) { + case GL_VERTEX_SHADER: + _mesa_reference_vertprog(ctx, &prog->VertexProgram, + (struct gl_vertex_program *)linked_prog); + ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, + linked_prog); + break; + case GL_FRAGMENT_SHADER: + _mesa_reference_fragprog(ctx, &prog->FragmentProgram, + (struct gl_fragment_program *)linked_prog); + ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, + linked_prog); + break; + } + if (!ok) { + return GL_FALSE; + } + } + + return GL_TRUE; +} void _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) @@ -2604,7 +2670,12 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) reparent_ir(shader->ir, shader); talloc_free(state); - } + + if (shader->CompileStatus) { + if (!ctx->Driver.CompileShader(ctx, shader)) + shader->CompileStatus = GL_FALSE; + } +} void _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) @@ -2639,57 +2710,8 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) } if (prog->LinkStatus) { - for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { - bool progress; - exec_list *ir = prog->_LinkedShaders[i]->ir; - - do { - progress = false; - - /* Lowering */ - do_mat_op_to_vec(ir); - do_mod_to_fract(ir); - do_div_to_mul_rcp(ir); - do_explog_to_explog2(ir); - - progress = do_common_optimization(ir, true) || progress; - - if (ctx->Shader.EmitNoIfs) - progress = do_if_to_cond_assign(ir) || progress; - - progress = do_vec_index_to_cond_assign(ir) || progress; - } while (progress); - } - } - - if (prog->LinkStatus) { - for (i = 0; i < prog->_NumLinkedShaders; i++) { - struct gl_program *linked_prog; - bool ok = true; - - linked_prog = get_mesa_program(ctx, prog, - prog->_LinkedShaders[i]); - - link_uniforms_to_shared_uniform_list(prog->Uniforms, linked_prog); - - switch (prog->_LinkedShaders[i]->Type) { - case GL_VERTEX_SHADER: - _mesa_reference_vertprog(ctx, &prog->VertexProgram, - (struct gl_vertex_program *)linked_prog); - ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, - linked_prog); - break; - case GL_FRAGMENT_SHADER: - _mesa_reference_fragprog(ctx, &prog->FragmentProgram, - (struct gl_fragment_program *)linked_prog); - ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, - linked_prog); - break; - } - if (!ok) { - prog->LinkStatus = GL_FALSE; - } - } + if (!ctx->Driver.LinkShader(ctx, prog)) + prog->LinkStatus = GL_FALSE; } } diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h index e832f84e75..ecaacde4bb 100644 --- a/src/mesa/program/ir_to_mesa.h +++ b/src/mesa/program/ir_to_mesa.h @@ -30,6 +30,8 @@ extern "C" { void _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *sh); void _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog); +GLboolean _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader); +GLboolean _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog); #ifdef __cplusplus } -- cgit v1.2.3 From 325aa1b3cd3fa2dcfc936d2024a4493c06f3b3f4 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Sat, 14 Aug 2010 14:38:09 +0100 Subject: mesa: Silence gcc warning "missing initializer for member". --- src/mesa/program/ir_to_mesa.cpp | 56 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7490ffa4fe..cf1fb91a70 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -980,51 +980,51 @@ static const struct { bool array_indexed; } statevars[] = { {"gl_DepthRange", "near", - {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX}, + {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX, false}, {"gl_DepthRange", "far", - {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY}, + {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY, false}, {"gl_DepthRange", "diff", - {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ}, + {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ, false}, {"gl_ClipPlane", NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW, true} , {"gl_Point", "size", - {STATE_POINT_SIZE}, SWIZZLE_XXXX}, + {STATE_POINT_SIZE}, SWIZZLE_XXXX, false}, {"gl_Point", "sizeMin", - {STATE_POINT_SIZE}, SWIZZLE_YYYY}, + {STATE_POINT_SIZE}, SWIZZLE_YYYY, false}, {"gl_Point", "sizeMax", - {STATE_POINT_SIZE}, SWIZZLE_ZZZZ}, + {STATE_POINT_SIZE}, SWIZZLE_ZZZZ, false}, {"gl_Point", "fadeThresholdSize", - {STATE_POINT_SIZE}, SWIZZLE_WWWW}, + {STATE_POINT_SIZE}, SWIZZLE_WWWW, false}, {"gl_Point", "distanceConstantAttenuation", - {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX}, + {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX, false}, {"gl_Point", "distanceLinearAttenuation", - {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY}, + {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY, false}, {"gl_Point", "distanceQuadraticAttenuation", - {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ}, + {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ, false}, {"gl_FrontMaterial", "emission", - {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW}, + {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW, false}, {"gl_FrontMaterial", "ambient", - {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, + {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW, false}, {"gl_FrontMaterial", "diffuse", - {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, false}, {"gl_FrontMaterial", "specular", - {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, + {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW, false}, {"gl_FrontMaterial", "shininess", - {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX}, + {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX, false}, {"gl_BackMaterial", "emission", - {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW}, + {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW, false}, {"gl_BackMaterial", "ambient", - {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, + {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW, false}, {"gl_BackMaterial", "diffuse", - {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, false}, {"gl_BackMaterial", "specular", - {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, + {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW, false}, {"gl_BackMaterial", "shininess", - {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX}, + {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX, false}, {"gl_LightSource", "ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true}, @@ -1052,12 +1052,12 @@ static const struct { {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ, true}, {"gl_LightModel", NULL, - {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW}, + {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW, false}, {"gl_FrontLightModelProduct", NULL, - {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW}, + {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW, false}, {"gl_BackLightModelProduct", NULL, - {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW}, + {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW, false}, {"gl_FrontLightProduct", "ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true}, @@ -1095,15 +1095,15 @@ static const struct { {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW, true}, {"gl_Fog", "color", - {STATE_FOG_COLOR}, SWIZZLE_XYZW}, + {STATE_FOG_COLOR}, SWIZZLE_XYZW, false}, {"gl_Fog", "density", - {STATE_FOG_PARAMS}, SWIZZLE_XXXX}, + {STATE_FOG_PARAMS}, SWIZZLE_XXXX, false}, {"gl_Fog", "start", - {STATE_FOG_PARAMS}, SWIZZLE_YYYY}, + {STATE_FOG_PARAMS}, SWIZZLE_YYYY, false}, {"gl_Fog", "end", - {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ}, + {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ, false}, {"gl_Fog", "scale", - {STATE_FOG_PARAMS}, SWIZZLE_WWWW}, + {STATE_FOG_PARAMS}, SWIZZLE_WWWW, false}, }; static ir_to_mesa_src_reg -- cgit v1.2.3 From 19acfa42ed47edb63f5ec3de8051a3102e62e96b Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Sat, 14 Aug 2010 14:40:06 +0100 Subject: mesa: Silence gcc warning "control reaches end of non-void function". --- src/mesa/program/ir_to_mesa.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index cf1fb91a70..2208bc1ce8 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -526,6 +526,7 @@ type_size(const struct glsl_type *type) return 0; default: assert(0); + return 0; } } -- cgit v1.2.3 From 0bf63733e54b47daf9f50c32a1fca4039c82def2 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Aug 2010 09:39:58 -0700 Subject: ir_to_mesa: Support texture rectangle targets --- src/mesa/program/ir_to_mesa.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 2208bc1ce8..b8a35ce162 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2090,6 +2090,9 @@ ir_to_mesa_visitor::visit(ir_texture *ir) case GLSL_SAMPLER_DIM_CUBE: inst->tex_target = TEXTURE_CUBE_INDEX; break; + case GLSL_SAMPLER_DIM_RECT: + inst->tex_target = TEXTURE_RECT_INDEX; + break; default: assert(!"FINISHME: other texture targets"); } -- cgit v1.2.3 From 68772031e6242aa78864dc9c7c1a607aec5ee7b9 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Aug 2010 09:43:00 -0700 Subject: ir_to_mesa: Clean up assertions in ir_to_mesa_visitor::visit(ir_texture *) --- src/mesa/program/ir_to_mesa.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index b8a35ce162..06a6bc3320 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2093,8 +2093,11 @@ ir_to_mesa_visitor::visit(ir_texture *ir) case GLSL_SAMPLER_DIM_RECT: inst->tex_target = TEXTURE_RECT_INDEX; break; + case GLSL_SAMPLER_DIM_BUF: + assert(!"FINISHME: Implement ARB_texture_buffer_object"); + break; default: - assert(!"FINISHME: other texture targets"); + assert(!"Should not get here."); } this->result = result_src; -- cgit v1.2.3 From fc63e37b971b641dfdff000ba353c4810414c20e Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Aug 2010 09:45:01 -0700 Subject: ir_to_mesa: Silence unused variable warnings --- src/mesa/program/ir_to_mesa.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 06a6bc3320..1fb578516c 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1632,8 +1632,7 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) * ir_dereference handler. */ static struct ir_to_mesa_dst_reg -get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v, - ir_to_mesa_src_reg *r) +get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v) { /* The LHS must be a dereference. If the LHS is a variable indexed array * access of a vector, it must be separated into a series conditional moves @@ -1662,7 +1661,7 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) ir->rhs->accept(this); r = this->result; - l = get_assignment_lhs(ir->lhs, this, &r); + l = get_assignment_lhs(ir->lhs, this); /* FINISHME: This should really set to the correct maximal writemask for each * FINISHME: component written (in the loops below). This case can only @@ -2554,6 +2553,7 @@ GLboolean _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader) { assert(shader->CompileStatus); + (void) ctx; return GL_TRUE; } -- cgit v1.2.3 From 1b708d8f4dd1a853de8537e81e6d5bf8c9f2aed1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 17 Aug 2010 12:37:49 -0700 Subject: mesa: Dump shader source before validating the shader. This will make extracting source to produce minimal testcases for shader compile issues easier. --- src/mesa/program/ir_to_mesa.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 1fb578516c..7fff66c78b 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2627,6 +2627,11 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) state->error = preprocess(state, &source, &state->info_log, &ctx->Extensions); + if (ctx->Shader.Flags & GLSL_DUMP) { + printf("GLSL source for shader %d:\n", shader->Name); + printf("%s\n", shader->Source); + } + if (!state->error) { _mesa_glsl_lexer_ctor(state, source); _mesa_glsl_parse(state); @@ -2662,15 +2667,10 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) _mesa_write_shader_to_file(shader); } - if (ctx->Shader.Flags & GLSL_DUMP) { - printf("GLSL source for shader %d:\n", shader->Name); - printf("%s\n", shader->Source); - - if (shader->CompileStatus) { - printf("GLSL IR for shader %d:\n", shader->Name); - _mesa_print_ir(shader->ir, NULL); - printf("\n\n"); - } + if ((ctx->Shader.Flags & GLSL_DUMP) && shader->CompileStatus) { + printf("GLSL IR for shader %d:\n", shader->Name); + _mesa_print_ir(shader->ir, NULL); + printf("\n\n"); } /* Retain any live IR, but trash the rest. */ -- cgit v1.2.3 From 6992c3c3739dad249e8c396057d5cbeedcdf91de Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 17 Aug 2010 17:24:42 -0700 Subject: ir_to_mesa: Fix implementation of ir_binop_equal, ir_binop_notequal. These binops are the vector-to-bool comparisons, not vec-to-bvec. We likely want both operations avilable as expression, since 915 and 965 FS naturally does the vector version, while 965 VS can also naturally do the scalar version. However, we can save that until later. Fixes: glsl-fs-vec4-operator-equal.shader_test glsl-fs-vec4-operator-notequal.shader_test glsl-vs-vec4-operator-equal.shader_test glsl-vs-vec4-operator-notequal.shader_test --- src/mesa/program/ir_to_mesa.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7fff66c78b..7b65fa4203 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -813,10 +813,34 @@ ir_to_mesa_visitor::visit(ir_expression *ir) ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]); break; case ir_binop_equal: - ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]); + /* "==" operator producing a scalar boolean. */ + if (ir->operands[0]->type->is_vector() || + ir->operands[1]->type->is_vector()) { + ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type); + ir_to_mesa_emit_op2(ir, OPCODE_SNE, + ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp); + ir_to_mesa_emit_op2(ir, OPCODE_SEQ, + result_dst, result_src, src_reg_for_float(0.0)); + } else { + ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]); + } break; - case ir_binop_logic_xor: case ir_binop_nequal: + /* "!=" operator producing a scalar boolean. */ + if (ir->operands[0]->type->is_vector() || + ir->operands[1]->type->is_vector()) { + ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type); + ir_to_mesa_emit_op2(ir, OPCODE_SNE, + ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]); + ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp); + ir_to_mesa_emit_op2(ir, OPCODE_SNE, + result_dst, result_src, src_reg_for_float(0.0)); + } else { + ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]); + } + break; + case ir_binop_logic_xor: ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]); break; -- cgit v1.2.3 From 35220fc5981045331b4f048f0fc2e1371a0673ed Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 17 Aug 2010 19:41:27 -0700 Subject: ir_to_mesa: Allow ir_return in main(). I didn't expect that this would really work, but it turns out there are shaders in the wild that do it. Fixes: (with swrast) glsl-fs-main-return glsl-vs-main-return --- src/mesa/program/ir_to_mesa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7b65fa4203..7de1939b63 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2129,12 +2129,12 @@ ir_to_mesa_visitor::visit(ir_texture *ir) void ir_to_mesa_visitor::visit(ir_return *ir) { - assert(current_function); - if (ir->get_value()) { ir_to_mesa_dst_reg l; int i; + assert(current_function); + ir->get_value()->accept(this); ir_to_mesa_src_reg r = this->result; -- cgit v1.2.3 From 0df61bdb669d03d9c25e49d5698f193deca3cf6d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 11:35:15 -0700 Subject: mesa: Make MESA_GLSL=dump include when compile/link fails, and the info log. --- src/mesa/program/ir_to_mesa.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7de1939b63..58d3b41d08 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2691,10 +2691,18 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) _mesa_write_shader_to_file(shader); } - if ((ctx->Shader.Flags & GLSL_DUMP) && shader->CompileStatus) { - printf("GLSL IR for shader %d:\n", shader->Name); - _mesa_print_ir(shader->ir, NULL); - printf("\n\n"); + if (ctx->Shader.Flags & GLSL_DUMP) { + if (shader->CompileStatus) { + printf("GLSL IR for shader %d:\n", shader->Name); + _mesa_print_ir(shader->ir, NULL); + printf("\n\n"); + } else { + printf("GLSL shader %d failed to compile.\n", shader->Name); + } + if (shader->InfoLog && shader->InfoLog[0] != 0) { + printf("GLSL shader %d info log:\n", shader->Name); + printf("%s\n", shader->InfoLog); + } } /* Retain any live IR, but trash the rest. */ @@ -2741,8 +2749,15 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) } if (prog->LinkStatus) { - if (!ctx->Driver.LinkShader(ctx, prog)) + if (!ctx->Driver.LinkShader(ctx, prog)) { prog->LinkStatus = GL_FALSE; + printf("GLSL shader program %d failed to link\n", prog->Name); + } + + if (prog->InfoLog && prog->InfoLog[0] != 0) { + printf("GLSL shader program %d info log:\n", prog->Name); + printf("%s\n", prog->InfoLog); + } } } -- cgit v1.2.3 From 4a6a4316846ead3ec12759c96ecc4b61491aad65 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 11:36:09 -0700 Subject: mesa: Hang the compiled shader off the shader->ir, not the shader. Otherwise, with repeated program recompile, we never free the results of the previous compile. --- src/mesa/program/ir_to_mesa.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 58d3b41d08..8ed3834061 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2662,6 +2662,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) _mesa_glsl_lexer_dtor(state); } + talloc_free(shader->ir); shader->ir = new(shader) exec_list; if (!state->error && !state->translation_unit.is_empty()) _mesa_ast_to_hir(shader->ir, state); @@ -2706,7 +2707,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) } /* Retain any live IR, but trash the rest. */ - reparent_ir(shader->ir, shader); + reparent_ir(shader->ir, shader->ir); talloc_free(state); -- cgit v1.2.3 From abc6d7e0b4b04c75129d24c3cb6f021b92cd46f6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 11:37:18 -0700 Subject: ir_to_mesa: Free the ir_to_mesa temporary storage when we're done. --- src/mesa/program/ir_to_mesa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 8ed3834061..4f4994392d 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2212,10 +2212,12 @@ ir_to_mesa_visitor::ir_to_mesa_visitor() next_signature_id = 1; sampler_map = NULL; current_function = NULL; + mem_ctx = talloc_new(NULL); } ir_to_mesa_visitor::~ir_to_mesa_visitor() { + talloc_free(mem_ctx); if (this->sampler_map) hash_table_dtor(this->sampler_map); } @@ -2445,8 +2447,6 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, v.ctx = ctx; v.prog = prog; - v.mem_ctx = talloc_new(NULL); - /* Emit Mesa IR for main(). */ visit_exec_list(shader->ir, &v); v.ir_to_mesa_emit_op0(NULL, OPCODE_END); -- cgit v1.2.3 From 5d0f430e8ed01db29d11d22e4b6c3760d8c39f8f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 12:02:35 -0700 Subject: mesa: Free old linked shaders when relinking new shaders. --- src/glsl/linker.cpp | 15 ++++++++++----- src/glsl/main.cpp | 6 +++++- src/glsl/program.h | 2 +- src/mesa/program/ir_to_mesa.cpp | 2 +- 4 files changed, 17 insertions(+), 8 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 4172e41910..b256574446 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -674,7 +674,8 @@ get_main_function_signature(gl_shader *sh) * shader is returned. */ static struct gl_shader * -link_intrastage_shaders(struct gl_shader_program *prog, +link_intrastage_shaders(GLcontext *ctx, + struct gl_shader_program *prog, struct gl_shader **shader_list, unsigned num_shaders) { @@ -747,7 +748,7 @@ link_intrastage_shaders(struct gl_shader_program *prog, return NULL; } - gl_shader *const linked = _mesa_new_shader(NULL, 0, main->Type); + gl_shader *const linked = ctx->Driver.NewShader(NULL, 0, main->Type); linked->ir = new(linked) exec_list; clone_ir_list(linked, linked->ir, main->ir); @@ -1212,7 +1213,7 @@ assign_varying_locations(struct gl_shader_program *prog, void -link_shaders(struct gl_shader_program *prog) +link_shaders(GLcontext *ctx, struct gl_shader_program *prog) { prog->LinkStatus = false; prog->Validated = false; @@ -1270,12 +1271,16 @@ link_shaders(struct gl_shader_program *prog) prog->Version = max_version; + for (unsigned int i = 0; i < prog->_NumLinkedShaders; i++) { + ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]); + } + /* Link all shaders for a particular stage and validate the result. */ prog->_NumLinkedShaders = 0; if (num_vert_shaders > 0) { gl_shader *const sh = - link_intrastage_shaders(prog, vert_shader_list, num_vert_shaders); + link_intrastage_shaders(ctx, prog, vert_shader_list, num_vert_shaders); if (sh == NULL) goto done; @@ -1289,7 +1294,7 @@ link_shaders(struct gl_shader_program *prog) if (num_frag_shaders > 0) { gl_shader *const sh = - link_intrastage_shaders(prog, frag_shader_list, num_frag_shaders); + link_intrastage_shaders(ctx, prog, frag_shader_list, num_frag_shaders); if (sh == NULL) goto done; diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index 24d6076d07..cb9f8a5277 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -209,6 +209,10 @@ int main(int argc, char **argv) { int status = EXIT_SUCCESS; + GLcontext local_ctx; + GLcontext *ctx = &local_ctx; + + ctx->Driver.NewShader = _mesa_new_shader; int c; int idx = 0; @@ -265,7 +269,7 @@ main(int argc, char **argv) } if ((status == EXIT_SUCCESS) && do_link) { - link_shaders(whole_program); + link_shaders(ctx, whole_program); status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE; if (strlen(whole_program->InfoLog) > 0) diff --git a/src/glsl/program.h b/src/glsl/program.h index 0a49203d4b..ea2c4ab0dd 100644 --- a/src/glsl/program.h +++ b/src/glsl/program.h @@ -30,4 +30,4 @@ extern "C" { } extern void -link_shaders(struct gl_shader_program *prog); +link_shaders(GLcontext *ctx, struct gl_shader_program *prog); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 4f4994392d..394370d46d 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2740,7 +2740,7 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL); if (prog->LinkStatus) { - link_shaders(prog); + link_shaders(ctx, prog); /* We don't use the linker's uniforms list, and cook up our own at * generate time. -- cgit v1.2.3 From 850c659044d081c53713800cacf8d518fae6cd70 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 13:48:32 -0700 Subject: ir_to_mesa: Stop leaking the ir_instruction * annotation of our compile. --- src/mesa/program/ir_to_mesa.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 394370d46d..5299d7706c 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2412,7 +2412,6 @@ struct gl_program * get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, struct gl_shader *shader) { - void *mem_ctx = shader_program; ir_to_mesa_visitor v; struct prog_instruction *mesa_instructions, *mesa_inst; ir_instruction **mesa_instruction_annotation; @@ -2490,7 +2489,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, mesa_instructions = (struct prog_instruction *)calloc(num_instructions, sizeof(*mesa_instructions)); - mesa_instruction_annotation = talloc_array(mem_ctx, ir_instruction *, + mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *, num_instructions); mesa_inst = mesa_instructions; -- cgit v1.2.3 From 3ef83d270b2c24867a0d020b81bdc6c54cb1c9b0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 14:13:30 -0700 Subject: ir_to_mesa: Fix leak of set_branchtargets temp data. --- src/mesa/program/ir_to_mesa.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 5299d7706c..eb3be913e7 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2266,8 +2266,8 @@ set_branchtargets(ir_to_mesa_visitor *v, } } - if_stack = (int *)calloc(if_count, sizeof(*if_stack)); - loop_stack = (int *)calloc(loop_count, sizeof(*loop_stack)); + if_stack = talloc_zero_array(v->mem_ctx, int, if_count); + loop_stack = talloc_zero_array(v->mem_ctx, int, loop_count); for (i = 0; i < num_instructions; i++) { switch (mesa_instructions[i].Opcode) { @@ -2319,8 +2319,6 @@ set_branchtargets(ir_to_mesa_visitor *v, break; } } - - free(if_stack); } static void -- cgit v1.2.3 From 3cd233eb5714137dccb6218ad78005511bcc02bd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 16:29:02 -0700 Subject: ir_to_mesa: Don't leak the whole linked assembly program. --- src/mesa/program/ir_to_mesa.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index eb3be913e7..b566706d72 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2633,6 +2633,7 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog) if (!ok) { return GL_FALSE; } + _mesa_reference_program(ctx, &linked_prog, NULL); } return GL_TRUE; -- cgit v1.2.3 From 49dfa89873403967d9f99d08d2e25042dea544e0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 17:12:18 -0700 Subject: ir_to_mesa: Fix leak by improper freeing of a uniform list. --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index b566706d72..7b0c28e5be 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2743,7 +2743,7 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) /* We don't use the linker's uniforms list, and cook up our own at * generate time. */ - free(prog->Uniforms); + _mesa_free_uniform_list(prog->Uniforms); prog->Uniforms = _mesa_new_uniform_list(); } -- cgit v1.2.3 From af2ef53a2701426d32382e861d8f238a449e9cd9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Aug 2010 18:01:55 -0700 Subject: mesa: Fix the whining for link failures to actually be under MESA_GLSL=dump. --- src/mesa/program/ir_to_mesa.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7b0c28e5be..fafc6200be 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2750,6 +2750,11 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) if (prog->LinkStatus) { if (!ctx->Driver.LinkShader(ctx, prog)) { prog->LinkStatus = GL_FALSE; + } + } + + if (ctx->Shader.Flags & GLSL_DUMP) { + if (!prog->LinkStatus) { printf("GLSL shader program %d failed to link\n", prog->Name); } -- cgit v1.2.3 From c108a7927d1dad9e0f641a0ec5a7387fb2626156 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 18 Aug 2010 12:52:55 +0200 Subject: glsl: add missing sceneColor field to gl_{Front, Back}LightModelProduct According to both GLSL 1.20 and 4.0, these are a struct with one field called "sceneColor". Fixes a crash on loading in FlightGear. --- src/mesa/program/ir_to_mesa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index fafc6200be..1fbf574bc8 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1079,9 +1079,9 @@ static const struct { {"gl_LightModel", NULL, {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW, false}, - {"gl_FrontLightModelProduct", NULL, + {"gl_FrontLightModelProduct", "sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW, false}, - {"gl_BackLightModelProduct", NULL, + {"gl_BackLightModelProduct", "sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW, false}, {"gl_FrontLightProduct", "ambient", -- cgit v1.2.3 From fc76d7276393a4617f9898214bc397bb65634b02 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 18 Aug 2010 12:52:56 +0200 Subject: glsl: don't crash if a field is specified for a non-struct uniform This was triggered by the previous bug, but is a separate problem in the general sense. --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 1fbf574bc8..fe2d8982d0 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1145,7 +1145,7 @@ get_builtin_uniform_reg(struct gl_program *prog, if (!field && statevars[i].field) { assert(!"FINISHME: whole-structure state var dereference"); } - if (field && strcmp(statevars[i].field, field) != 0) + if (field && (!statevars[i].field || strcmp(statevars[i].field, field) != 0)) continue; break; } -- cgit v1.2.3 From c3e3793c325e36366165a5d1403a8c406ff200db Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 18 Aug 2010 12:52:57 +0200 Subject: glsl: add missing ambient field to gl_LightModel Again, this is a one-element struct that was incorrectly missing the field. --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index fe2d8982d0..58324944fe 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1076,7 +1076,7 @@ static const struct { {"gl_LightSource", "quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ, true}, - {"gl_LightModel", NULL, + {"gl_LightModel", "ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW, false}, {"gl_FrontLightModelProduct", "sceneColor", -- cgit v1.2.3 From d6cc7191daa249463b20e2965dc1006288539b1e Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 20 Aug 2010 12:57:21 -0700 Subject: glsl: Remove bogus "ambient" field from vec4 gl_TextureEnvColor. --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 58324944fe..9fdeaa9be3 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1098,7 +1098,7 @@ static const struct { {"gl_BackLightProduct", "specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW, true}, - {"gl_TextureEnvColor", "ambient", + {"gl_TextureEnvColor", NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW, true}, {"gl_EyePlaneS", NULL, -- cgit v1.2.3 From 405546882a010885d342b0b40392de0da289374e Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Sat, 21 Aug 2010 23:56:24 -0700 Subject: mesa: Initialize variables in mesa_src_reg_from_ir_src_reg. --- src/mesa/program/ir_to_mesa.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 9fdeaa9be3..8df85dc3ea 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2235,6 +2235,8 @@ mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg) mesa_reg.Negate = reg.negate; mesa_reg.Abs = 0; mesa_reg.HasIndex2 = GL_FALSE; + mesa_reg.RelAddr2 = 0; + mesa_reg.Index2 = 0; return mesa_reg; } -- cgit v1.2.3 From 48c289fb552a3d363b505514b6ea22467f00e318 Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Sun, 22 Aug 2010 00:09:43 -0700 Subject: mesa: Initialize member variables in ir_to_mesa_src_reg constructor. The default constructor did not initialize some member variables. --- src/mesa/program/ir_to_mesa.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 8df85dc3ea..676f68e5a0 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -78,6 +78,10 @@ typedef struct ir_to_mesa_src_reg { ir_to_mesa_src_reg() { this->file = PROGRAM_UNDEFINED; + this->index = 0; + this->swizzle = 0; + this->negate = 0; + this->reladdr = NULL; } int file; /**< PROGRAM_* from Mesa */ -- cgit v1.2.3 From ebef04011736ea8e13692fed87623d425c4d1b08 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Aug 2010 10:57:54 -0700 Subject: ir_to_mesa: Fix constant array handling to return the temp we created. We ended up returning CONST[loc] rather than TEMP[loc2]. Things would *usually* end up working out OK, since the constants often ended up getting allocated to CONST[loc..loc+columns] with no swizzle. But for the case where the contigous temporary copy of the swizzled constant vec4 args was actually needed, we'd end up reading some other constant values, possibly including ones not actually allocated. Fixes: glsl-varying-mat3x2. --- src/mesa/program/ir_to_mesa.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 676f68e5a0..17ebdbb220 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1817,6 +1817,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir) } this->result = mat; + return; } src_reg.file = PROGRAM_CONSTANT; -- cgit v1.2.3 From 66afcb560771b6ba6ad668156e9f442e86b9a7a2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Aug 2010 12:53:39 -0700 Subject: ir_to_mesa: Implement f2b by comparing the arg to 0, not the result. Fixes: glsl-fs-any --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 17ebdbb220..7a615f2d58 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -911,7 +911,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_f2b: case ir_unop_i2b: ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, - result_src, src_reg_for_float(0.0)); + op[0], src_reg_for_float(0.0)); break; case ir_unop_trunc: ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]); -- cgit v1.2.3 From 5e9ac94cc44ef4f97063d7b696411b2a4be16f36 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Aug 2010 12:21:33 -0700 Subject: mesa: Add new ir_unop_any() expression operation. The previous any() implementation would generate arg0.x || arg0.y || arg0.z. Having an expression operation for this makes it easy for the backend to generate something easier (DPn + SNE for 915 FS, .any predication on 965 VS) --- src/glsl/README | 1 + src/glsl/builtins/ir/any | 6 +++--- src/glsl/ir.cpp | 2 ++ src/glsl/ir.h | 1 + src/glsl/ir_constant_expression.cpp | 9 +++++++++ src/glsl/ir_validate.cpp | 5 +++++ src/mesa/program/ir_to_mesa.cpp | 20 ++++++++++++++++++++ 7 files changed, 41 insertions(+), 3 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/README b/src/glsl/README index 74520321b2..2e501d6206 100644 --- a/src/glsl/README +++ b/src/glsl/README @@ -180,6 +180,7 @@ ir.h (new enum) ir.cpp:get_num_operands() (used for ir_reader) ir.cpp:operator_strs (used for ir_reader) ir_constant_expression.cpp (you probably want to be able to constant fold) +ir_validate.cpp (check users have the right types) You may also need to update the backends if they will see the new expr type: diff --git a/src/glsl/builtins/ir/any b/src/glsl/builtins/ir/any index f10e8a7b47..cc6038a315 100644 --- a/src/glsl/builtins/ir/any +++ b/src/glsl/builtins/ir/any @@ -2,15 +2,15 @@ (signature bool (parameters (declare (in) bvec2 arg0)) - ((return (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0)))))) + ((return (expression bool any (var_ref arg0))))) (signature bool (parameters (declare (in) bvec3 arg0)) - ((return (expression bool || (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0)))))) + ((return (expression bool any (var_ref arg0))))) (signature bool (parameters (declare (in) bvec4 arg0)) - ((return (expression bool || (expression bool || (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))) (swiz w (var_ref arg0)))))) + ((return (expression bool any (var_ref arg0))))) )) diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index ebb592792b..4622a1f939 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -184,6 +184,7 @@ ir_expression::get_num_operands(ir_expression_operation op) 1, /* ir_unop_i2b */ 1, /* ir_unop_b2i */ 1, /* ir_unop_u2f */ + 1, /* ir_unop_any */ 1, /* ir_unop_trunc */ 1, /* ir_unop_ceil */ @@ -252,6 +253,7 @@ static const char *const operator_strs[] = { "i2b", "b2i", "u2f", + "any", "trunc", "ceil", "floor", diff --git a/src/glsl/ir.h b/src/glsl/ir.h index b04222893c..500b152408 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -604,6 +604,7 @@ enum ir_expression_operation { ir_unop_i2b, /**< int-to-boolean conversion */ ir_unop_b2i, /**< Boolean-to-int conversion */ ir_unop_u2f, /**< Unsigned-to-float conversion. */ + ir_unop_any, /** * \name Unary floating-point rounding operations. diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index 54f14d1a54..942f198360 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -149,6 +149,15 @@ ir_expression::constant_expression_value() } break; + case ir_unop_any: + assert(op[0]->type->is_boolean()); + data.b[0] = false; + for (unsigned c = 0; c < op[0]->type->components(); c++) { + if (op[0]->value.b[c]) + data.b[0] = true; + } + break; + case ir_unop_trunc: assert(op[0]->type->base_type == GLSL_TYPE_FLOAT); for (unsigned c = 0; c < op[0]->type->components(); c++) { diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 6e08fa4025..9ea11dd400 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -223,6 +223,11 @@ ir_validate::visit_leave(ir_expression *ir) assert(ir->type->base_type == GLSL_TYPE_FLOAT); break; + case ir_unop_any: + assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); + assert(ir->type == glsl_type::bool_type); + break; + case ir_unop_trunc: case ir_unop_ceil: case ir_unop_floor: diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7a615f2d58..ea2560af3e 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -844,6 +844,26 @@ ir_to_mesa_visitor::visit(ir_expression *ir) ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]); } break; + + case ir_unop_any: + switch (ir->operands[0]->type->vector_elements) { + case 4: + ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, op[0], op[0]); + break; + case 3: + ir_to_mesa_emit_op2(ir, OPCODE_DP3, result_dst, op[0], op[0]); + break; + case 2: + ir_to_mesa_emit_op2(ir, OPCODE_DP2, result_dst, op[0], op[0]); + break; + default: + assert(!"unreached: ir_unop_any of non-bvec"); + break; + } + ir_to_mesa_emit_op2(ir, OPCODE_SNE, + result_dst, result_src, src_reg_for_float(0.0)); + break; + case ir_binop_logic_xor: ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]); break; -- cgit v1.2.3 From 2f5bf20e44d509fa3afbe2cfbb9bb65347daea6a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Aug 2010 15:43:56 -0700 Subject: glsl: Set up uniform initializers by walking the shaders after linking. Previously, uniform initializers were handled by ir_to_mesa as it made its Parameters list. However, uniform values are global to all shaders, and the value set in one Parameters list wasn't propagated to the other gl_program->Parameters lists. By going back through the general Mesa uniform handling, we make sure that all gl_programs get updated values, and also successfully separate uniform initializer handling from ir_to_mesa gl_program generation. Fixes: glsl-uniform-initializer-5. --- src/mesa/main/uniforms.c | 108 +++++++++++++----------- src/mesa/main/uniforms.h | 15 +++- src/mesa/program/ir_to_mesa.cpp | 180 ++++++++++++++++++++++++---------------- 3 files changed, 181 insertions(+), 122 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index d68a7768df..a5d7da51f0 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -454,17 +454,12 @@ _mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location, * The return value will encode two values, the uniform location and an * offset (used for arrays, structs). */ -static GLint -_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name) +GLint +_mesa_get_uniform_location(GLcontext *ctx, struct gl_shader_program *shProg, + const GLchar *name) { GLint offset = 0, location = -1; - struct gl_shader_program *shProg = - _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation"); - - if (!shProg) - return -1; - if (shProg->LinkStatus == GL_FALSE) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)"); return -1; @@ -751,11 +746,11 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, /** * Called via glUniform*() functions. */ -static void -_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, +void +_mesa_uniform(GLcontext *ctx, struct gl_shader_program *shProg, + GLint location, GLsizei count, const GLvoid *values, GLenum type) { - struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; struct gl_uniform *uniform; GLint elems, offset; @@ -923,12 +918,12 @@ set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program, * Called by glUniformMatrix*() functions. * Note: cols=2, rows=4 ==> array[2] of vec4 */ -static void -_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, +void +_mesa_uniform_matrix(GLcontext *ctx, struct gl_shader_program *shProg, + GLint cols, GLint rows, GLint location, GLsizei count, GLboolean transpose, const GLfloat *values) { - struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; struct gl_uniform *uniform; GLint offset; @@ -999,7 +994,7 @@ void GLAPIENTRY _mesa_Uniform1fARB(GLint location, GLfloat v0) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, 1, &v0, GL_FLOAT); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_FLOAT); } void GLAPIENTRY @@ -1009,7 +1004,7 @@ _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1) GLfloat v[2]; v[0] = v0; v[1] = v1; - _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC2); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC2); } void GLAPIENTRY @@ -1020,7 +1015,7 @@ _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) v[0] = v0; v[1] = v1; v[2] = v2; - _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC3); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC3); } void GLAPIENTRY @@ -1033,14 +1028,14 @@ _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, v[1] = v1; v[2] = v2; v[3] = v3; - _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC4); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC4); } void GLAPIENTRY _mesa_Uniform1iARB(GLint location, GLint v0) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, 1, &v0, GL_INT); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_INT); } void GLAPIENTRY @@ -1050,7 +1045,7 @@ _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1) GLint v[2]; v[0] = v0; v[1] = v1; - _mesa_uniform(ctx, location, 1, v, GL_INT_VEC2); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC2); } void GLAPIENTRY @@ -1061,7 +1056,7 @@ _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2) v[0] = v0; v[1] = v1; v[2] = v2; - _mesa_uniform(ctx, location, 1, v, GL_INT_VEC3); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC3); } void GLAPIENTRY @@ -1073,63 +1068,63 @@ _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) v[1] = v1; v[2] = v2; v[3] = v3; - _mesa_uniform(ctx, location, 1, v, GL_INT_VEC4); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC4); } void GLAPIENTRY _mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_FLOAT); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT); } void GLAPIENTRY _mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC2); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC2); } void GLAPIENTRY _mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC3); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC3); } void GLAPIENTRY _mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC4); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC4); } void GLAPIENTRY _mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_INT); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT); } void GLAPIENTRY _mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_INT_VEC2); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC2); } void GLAPIENTRY _mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_INT_VEC3); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC3); } void GLAPIENTRY _mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_INT_VEC4); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC4); } @@ -1138,7 +1133,7 @@ void GLAPIENTRY _mesa_Uniform1ui(GLint location, GLuint v0) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, 1, &v0, GL_UNSIGNED_INT); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_UNSIGNED_INT); } void GLAPIENTRY @@ -1148,7 +1143,7 @@ _mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1) GLuint v[2]; v[0] = v0; v[1] = v1; - _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC2); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC2); } void GLAPIENTRY @@ -1159,7 +1154,7 @@ _mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) v[0] = v0; v[1] = v1; v[2] = v2; - _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC3); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC3); } void GLAPIENTRY @@ -1171,35 +1166,35 @@ _mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) v[1] = v1; v[2] = v2; v[3] = v3; - _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC4); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC4); } void GLAPIENTRY _mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT); } void GLAPIENTRY _mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC2); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC2); } void GLAPIENTRY _mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC3); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC3); } void GLAPIENTRY _mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC4); + _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC4); } @@ -1209,7 +1204,8 @@ _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 2, 2, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 2, 2, location, count, transpose, value); } void GLAPIENTRY @@ -1217,7 +1213,8 @@ _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 3, 3, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 3, 3, location, count, transpose, value); } void GLAPIENTRY @@ -1225,7 +1222,8 @@ _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 4, 4, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 4, 4, location, count, transpose, value); } @@ -1237,7 +1235,8 @@ _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 2, 3, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 2, 3, location, count, transpose, value); } void GLAPIENTRY @@ -1245,7 +1244,8 @@ _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 3, 2, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 3, 2, location, count, transpose, value); } void GLAPIENTRY @@ -1253,7 +1253,8 @@ _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 2, 4, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 2, 4, location, count, transpose, value); } void GLAPIENTRY @@ -1261,7 +1262,8 @@ _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 4, 2, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 4, 2, location, count, transpose, value); } void GLAPIENTRY @@ -1269,7 +1271,8 @@ _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 3, 4, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 3, 4, location, count, transpose, value); } void GLAPIENTRY @@ -1277,7 +1280,8 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { GET_CURRENT_CONTEXT(ctx); - _mesa_uniform_matrix(ctx, 4, 3, location, count, transpose, value); + _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, + 4, 3, location, count, transpose, value); } @@ -1300,8 +1304,16 @@ _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params) GLint GLAPIENTRY _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name) { + struct gl_shader_program *shProg; + GET_CURRENT_CONTEXT(ctx); - return _mesa_get_uniform_location(ctx, programObj, name); + + shProg = _mesa_lookup_shader_program_err(ctx, programObj, + "glGetUniformLocation"); + if (!shProg) + return -1; + + return _mesa_get_uniform_location(ctx, shProg, name); } diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h index ef98fe16bb..f823c61444 100644 --- a/src/mesa/main/uniforms.h +++ b/src/mesa/main/uniforms.h @@ -150,7 +150,20 @@ _mesa_GetUniformivARB(GLhandleARB, GLint, GLint *); extern GLint GLAPIENTRY _mesa_GetUniformLocationARB(GLhandleARB, const GLcharARB *); - +GLint +_mesa_get_uniform_location(GLcontext *ctx, struct gl_shader_program *shProg, + const GLchar *name); + +void +_mesa_uniform(GLcontext *ctx, struct gl_shader_program *shader_program, + GLint location, GLsizei count, + const GLvoid *values, GLenum type); + +void +_mesa_uniform_matrix(GLcontext *ctx, struct gl_shader_program *shProg, + GLint cols, GLint rows, + GLint location, GLsizei count, + GLboolean transpose, const GLfloat *values); extern void _mesa_update_shader_textures_used(struct gl_program *prog); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index ea2560af3e..da69d26a94 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -261,12 +261,10 @@ public: int mul_operand); int add_uniform(const char *name, - const glsl_type *type, - ir_constant *constant); + const glsl_type *type); void add_aggregate_uniform(ir_instruction *ir, const char *name, const struct glsl_type *type, - ir_constant *constant, struct ir_to_mesa_dst_reg temp); struct hash_table *sampler_map; @@ -1307,8 +1305,7 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var, int ir_to_mesa_visitor::add_uniform(const char *name, - const glsl_type *type, - ir_constant *constant) + const glsl_type *type) { int len; @@ -1319,65 +1316,11 @@ ir_to_mesa_visitor::add_uniform(const char *name, len = type_size(type) * 4; } - float *values = NULL; - if (constant && type->is_array()) { - values = (float *)malloc(type->length * 4 * sizeof(float)); - - assert(type->fields.array->is_scalar() || - type->fields.array->is_vector() || - !"FINISHME: uniform array initializers for non-vector"); - - for (unsigned int i = 0; i < type->length; i++) { - ir_constant *element = constant->array_elements[i]; - unsigned int c; - - for (c = 0; c < type->fields.array->vector_elements; c++) { - switch (type->fields.array->base_type) { - case GLSL_TYPE_FLOAT: - values[4 * i + c] = element->value.f[c]; - break; - case GLSL_TYPE_INT: - values[4 * i + c] = element->value.i[c]; - break; - case GLSL_TYPE_UINT: - values[4 * i + c] = element->value.u[c]; - break; - case GLSL_TYPE_BOOL: - values[4 * i + c] = element->value.b[c]; - break; - default: - assert(!"not reached"); - } - } - } - } else if (constant) { - values = (float *)malloc(16 * sizeof(float)); - for (unsigned int i = 0; i < type->components(); i++) { - switch (type->base_type) { - case GLSL_TYPE_FLOAT: - values[i] = constant->value.f[i]; - break; - case GLSL_TYPE_INT: - values[i] = constant->value.i[i]; - break; - case GLSL_TYPE_UINT: - values[i] = constant->value.u[i]; - break; - case GLSL_TYPE_BOOL: - values[i] = constant->value.b[i]; - break; - default: - assert(!"not reached"); - } - } - } - int loc = _mesa_add_uniform(this->prog->Parameters, name, len, type->gl_type, - values); - free(values); + NULL); return loc; } @@ -1389,17 +1332,12 @@ void ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir, const char *name, const struct glsl_type *type, - ir_constant *constant, struct ir_to_mesa_dst_reg temp) { int loc; if (type->is_record()) { void *mem_ctx = talloc_new(NULL); - ir_constant *field_constant = NULL; - - if (constant) - field_constant = (ir_constant *)constant->components.get_head(); for (unsigned int i = 0; i < type->length; i++) { const glsl_type *field_type = type->fields.structure[i].type; @@ -1407,11 +1345,8 @@ ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir, add_aggregate_uniform(ir, talloc_asprintf(mem_ctx, "%s.%s", name, type->fields.structure[i].name), - field_type, field_constant, temp); + field_type, temp); temp.index += type_size(field_type); - - if (constant) - field_constant = (ir_constant *)field_constant->next; } talloc_free(mem_ctx); @@ -1421,7 +1356,7 @@ ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir, assert(type->is_vector() || type->is_scalar() || !"FINISHME: other types"); - loc = add_uniform(name, type, constant); + loc = add_uniform(name, type); ir_to_mesa_src_reg uniform(PROGRAM_UNIFORM, loc, type); @@ -1485,14 +1420,12 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) this->variables.push_tail(entry); add_aggregate_uniform(ir->var, ir->var->name, ir->var->type, - ir->var->constant_value, ir_to_mesa_dst_reg_from_src(temp)); break; } loc = add_uniform(ir->var->name, - ir->var->type, - ir->var->constant_value); + ir->var->type); /* Always mark the uniform used at this point. If it isn't * used, dead code elimination should have nuked the decl already. @@ -2433,6 +2366,105 @@ link_uniforms_to_shared_uniform_list(struct gl_uniform_list *uniforms, } } +static void +set_uniform_initializer(GLcontext *ctx, void *mem_ctx, + struct gl_shader_program *shader_program, + const char *name, const glsl_type *type, + ir_constant *val) +{ + if (type->is_record()) { + ir_constant *field_constant; + + field_constant = (ir_constant *)val->components.get_head(); + + for (unsigned int i = 0; i < type->length; i++) { + const glsl_type *field_type = type->fields.structure[i].type; + const char *field_name = talloc_asprintf(mem_ctx, "%s.%s", name, + type->fields.structure[i].name); + set_uniform_initializer(ctx, mem_ctx, shader_program, field_name, + field_type, field_constant); + field_constant = (ir_constant *)field_constant->next; + } + return; + } + + int loc = _mesa_get_uniform_location(ctx, shader_program, name); + + if (loc == -1) { + shader_program->InfoLog = + talloc_asprintf_append(shader_program->InfoLog, + "Couldn't find uniform for " + "initializer %s\n", name); + shader_program->LinkStatus = false; + abort(); + } + + for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) { + ir_constant *element; + const glsl_type *element_type; + if (type->is_array()) { + element = val->array_elements[i]; + element_type = type->fields.array; + } else { + element = val; + element_type = type; + } + + void *values; + + if (element_type->base_type == GLSL_TYPE_BOOL) { + int *conv = talloc_array(mem_ctx, int, element_type->components()); + for (unsigned int j = 0; j < element_type->components(); j++) { + conv[j] = element->value.b[j]; + } + values = (void *)conv; + element_type = glsl_type::get_instance(GLSL_TYPE_INT, + element_type->vector_elements, + 1); + } else { + values = &element->value; + } + + if (element_type->is_matrix()) { + _mesa_uniform_matrix(ctx, shader_program, + element_type->matrix_columns, + element_type->vector_elements, + loc, 1, GL_FALSE, (GLfloat *)values); + loc += element_type->matrix_columns; + } else { + _mesa_uniform(ctx, shader_program, loc, element_type->matrix_columns, + values, element_type->gl_type); + loc += type_size(element_type); + } + } +} + +static void +set_uniform_initializers(GLcontext *ctx, + struct gl_shader_program *shader_program) +{ + void *mem_ctx = NULL; + + for (unsigned int i = 0; i < shader_program->_NumLinkedShaders; i++) { + struct gl_shader *shader = shader_program->_LinkedShaders[i]; + foreach_iter(exec_list_iterator, iter, *shader->ir) { + ir_instruction *ir = (ir_instruction *)iter.get(); + ir_variable *var = ir->as_variable(); + + if (!var || var->mode != ir_var_uniform || !var->constant_value) + continue; + + if (!mem_ctx) + mem_ctx = talloc_new(NULL); + + set_uniform_initializer(ctx, mem_ctx, shader_program, var->name, + var->type, var->constant_value); + } + } + + talloc_free(mem_ctx); +} + struct gl_program * get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, struct gl_shader *shader) @@ -2780,6 +2812,8 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) } } + set_uniform_initializers(ctx, prog); + if (ctx->Shader.Flags & GLSL_DUMP) { if (!prog->LinkStatus) { printf("GLSL shader program %d failed to link\n", prog->Name); -- cgit v1.2.3 From 5755d1d6a7ff68c7d690d67c4cd64ef8e01ec2ed Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sun, 22 Aug 2010 03:15:00 +0200 Subject: ir_to_mesa: set IndirectRegisterFiles This fixes relative addressing of temporaries (and maybe others) in all gallium drivers. Acked on irc by Eric Anholt. --- src/mesa/program/ir_to_mesa.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index da69d26a94..fc145b475e 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2569,6 +2569,14 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, mesa_inst->TexShadow = inst->tex_shadow; mesa_instruction_annotation[i] = inst->ir; + /* Set IndirectRegisterFiles. */ + if (mesa_inst->DstReg.RelAddr) + prog->IndirectRegisterFiles |= 1 << mesa_inst->DstReg.File; + + for (unsigned src = 0; src < 3; src++) + if (mesa_inst->SrcReg[src].RelAddr) + prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File; + if (ctx->Shader.EmitNoIfs && mesa_inst->Opcode == OPCODE_IF) { shader_program->InfoLog = talloc_asprintf_append(shader_program->InfoLog, -- cgit v1.2.3 From ea2231ff5e4ced36bdb65ccdd02a1008fb8bfce7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Aug 2010 16:47:09 -0700 Subject: mesa: Remove the "Used" flag in gl_program_parameter. This was in place for uniform handling, but nothing actually needs the value now, since presence in a parameter list indicates that the uniform was used as far as the linker was concerned. --- src/mesa/program/ir_to_mesa.cpp | 5 ----- src/mesa/program/prog_parameter.c | 22 ---------------------- src/mesa/program/prog_parameter.h | 7 +------ 3 files changed, 1 insertion(+), 33 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index fc145b475e..4429b7468d 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1427,11 +1427,6 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) loc = add_uniform(ir->var->name, ir->var->type); - /* Always mark the uniform used at this point. If it isn't - * used, dead code elimination should have nuked the decl already. - */ - this->prog->Parameters->Parameters[loc].Used = GL_TRUE; - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM, loc); this->variables.push_tail(entry); break; diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c index fa5deaf127..7e01f675d3 100644 --- a/src/mesa/program/prog_parameter.c +++ b/src/mesa/program/prog_parameter.c @@ -314,27 +314,6 @@ _mesa_add_uniform(struct gl_program_parameter_list *paramList, } -/** - * Mark the named uniform as 'used'. - */ -void -_mesa_use_uniform(struct gl_program_parameter_list *paramList, - const char *name) -{ - GLuint i; - for (i = 0; i < paramList->NumParameters; i++) { - struct gl_program_parameter *p = paramList->Parameters + i; - if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER) && - strcmp(p->Name, name) == 0) { - p->Used = GL_TRUE; - /* Note that large uniforms may occupy several slots so we're - * not done searching yet. - */ - } - } -} - - /** * Add a sampler to the parameter list. * \param name uniform's name @@ -658,7 +637,6 @@ _mesa_clone_parameter_list(const struct gl_program_parameter_list *list) list->ParameterValues[i], NULL, 0x0); ASSERT(j >= 0); pCopy = clone->Parameters + j; - pCopy->Used = p->Used; pCopy->Flags = p->Flags; /* copy state indexes */ if (p->Type == PROGRAM_STATE_VAR) { diff --git a/src/mesa/program/prog_parameter.h b/src/mesa/program/prog_parameter.h index 1860f31287..5381a6dc0f 100644 --- a/src/mesa/program/prog_parameter.h +++ b/src/mesa/program/prog_parameter.h @@ -64,8 +64,7 @@ struct gl_program_parameter * The next program parameter's Size will be Size-4 of this parameter. */ GLuint Size; - GLboolean Used; /**< Helper flag for GLSL uniform tracking */ - GLboolean Initialized; /**< Has the ParameterValue[] been set? */ + GLboolean Initialized; /**< debug: Has the ParameterValue[] been set? */ GLbitfield Flags; /**< Bitmask of PROG_PARAM_*_BIT */ /** * A sequence of STATE_* tokens and integers to identify GL state. @@ -136,10 +135,6 @@ _mesa_add_uniform(struct gl_program_parameter_list *paramList, const char *name, GLuint size, GLenum datatype, const GLfloat *values); -extern void -_mesa_use_uniform(struct gl_program_parameter_list *paramList, - const char *name); - extern GLint _mesa_add_sampler(struct gl_program_parameter_list *paramList, const char *name, GLenum datatype, int array_length); -- cgit v1.2.3 From 0924ba0c3496160a134d37cec800f902ae805b9c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Aug 2010 14:27:27 -0700 Subject: ir_to_mesa: Convert this code to using linker.cpp's uniform locations. Fixes: glsl-fs-uniform-array-4. --- src/glsl/linker.cpp | 1 + src/mesa/program/ir_to_mesa.cpp | 199 +++++++++++++++------------------------- src/mesa/program/prog_uniform.h | 5 +- 3 files changed, 78 insertions(+), 127 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index cb06036ef2..0348bd01e8 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -929,6 +929,7 @@ add_uniform(void *mem_ctx, exec_list *uniforms, struct hash_table *ht, n->slots = vec4_slots; n->u->Name = strdup(name); + n->u->Type = type; n->u->VertPos = -1; n->u->FragPos = -1; n->u->GeomPos = -1; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 4429b7468d..4a4278eb1a 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -260,13 +260,6 @@ public: GLboolean try_emit_mad(ir_expression *ir, int mul_operand); - int add_uniform(const char *name, - const glsl_type *type); - void add_aggregate_uniform(ir_instruction *ir, - const char *name, - const struct glsl_type *type, - struct ir_to_mesa_dst_reg temp); - struct hash_table *sampler_map; void set_sampler_location(ir_variable *sampler, int location); @@ -522,10 +515,10 @@ type_size(const struct glsl_type *type) } return size; case GLSL_TYPE_SAMPLER: - /* Samplers take up no register space, since they're baked in at - * link time. + /* Samplers take up one slot in UNIFORMS[], but they're baked in + * at link time. */ - return 0; + return 1; default: assert(0); return 0; @@ -1290,7 +1283,6 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var, tokens[1] = 0; /* unused array index */ base_pos = add_matrix_ref(prog, tokens); } - tokens[4] = matrices[i].modifier; entry = new(mem_ctx) variable_storage(var, PROGRAM_STATE_VAR, @@ -1303,76 +1295,10 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var, return NULL; } -int -ir_to_mesa_visitor::add_uniform(const char *name, - const glsl_type *type) -{ - int len; - - if (type->is_vector() || - type->is_scalar()) { - len = type->vector_elements; - } else { - len = type_size(type) * 4; - } - - int loc = _mesa_add_uniform(this->prog->Parameters, - name, - len, - type->gl_type, - NULL); - - return loc; -} - -/* Recursively add all the members of the aggregate uniform as uniform names - * to Mesa, moving those uniforms to our structured temporary. - */ -void -ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir, - const char *name, - const struct glsl_type *type, - struct ir_to_mesa_dst_reg temp) -{ - int loc; - - if (type->is_record()) { - void *mem_ctx = talloc_new(NULL); - - for (unsigned int i = 0; i < type->length; i++) { - const glsl_type *field_type = type->fields.structure[i].type; - - add_aggregate_uniform(ir, - talloc_asprintf(mem_ctx, "%s.%s", name, - type->fields.structure[i].name), - field_type, temp); - temp.index += type_size(field_type); - } - - talloc_free(mem_ctx); - - return; - } - - assert(type->is_vector() || type->is_scalar() || !"FINISHME: other types"); - - loc = add_uniform(name, type); - - ir_to_mesa_src_reg uniform(PROGRAM_UNIFORM, loc, type); - - for (int i = 0; i < type_size(type); i++) { - ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, uniform); - temp.index++; - uniform.index++; - } -} - - void ir_to_mesa_visitor::visit(ir_dereference_variable *ir) { variable_storage *entry = find_variable_storage(ir->var); - unsigned int loc; if (!entry) { switch (ir->var->mode) { @@ -1382,7 +1308,6 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) if (entry) break; - /* FINISHME: Fix up uniform name for arrays and things */ if (ir->var->type->base_type == GLSL_TYPE_SAMPLER || (ir->var->type->base_type == GLSL_TYPE_ARRAY && ir->var->type->fields.array->base_type == GLSL_TYPE_SAMPLER)) { @@ -1404,30 +1329,8 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) break; } - assert(ir->var->type->gl_type != 0 && - ir->var->type->gl_type != GL_INVALID_ENUM); - - /* Oh, the joy of aggregate types in Mesa. Like constants, - * we can only really do vec4s. So, make a temp, chop the - * aggregate up into vec4s, and move those vec4s to the temp. - */ - if (ir->var->type->is_record()) { - ir_to_mesa_src_reg temp = get_temp(ir->var->type); - - entry = new(mem_ctx) variable_storage(ir->var, - temp.file, - temp.index); - this->variables.push_tail(entry); - - add_aggregate_uniform(ir->var, ir->var->name, ir->var->type, - ir_to_mesa_dst_reg_from_src(temp)); - break; - } - - loc = add_uniform(ir->var->name, - ir->var->type); - - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM, loc); + entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM, + ir->var->location); this->variables.push_tail(entry); break; case ir_var_in: @@ -2338,25 +2241,81 @@ count_resources(struct gl_program *prog) _mesa_update_shader_textures_used(prog); } -/* Each stage has some uniforms in its Parameters list. The Uniforms - * list for the linked shader program has a pointer to these uniforms - * in each of the stage's Parameters list, so that their values can be - * updated when a uniform is set. +/* Add the uniforms to the parameters. The linker chose locations + * in our parameters lists (which weren't created yet), which the + * uniforms code will use to poke values into our parameters list + * when uniforms are updated. */ static void -link_uniforms_to_shared_uniform_list(struct gl_uniform_list *uniforms, - struct gl_program *prog) +add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, + struct gl_shader *shader, + struct gl_program *prog) { unsigned int i; - for (i = 0; i < prog->Parameters->NumParameters; i++) { - const struct gl_program_parameter *p = prog->Parameters->Parameters + i; + for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) { + struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i; + const glsl_type *type = uniform->Type; + unsigned int size; + int parameter_index = -1; + + switch (shader->Type) { + case GL_VERTEX_SHADER: + parameter_index = uniform->VertPos; + break; + case GL_FRAGMENT_SHADER: + parameter_index = uniform->FragPos; + break; + case GL_GEOMETRY_SHADER: + parameter_index = uniform->GeomPos; + break; + } + + /* Only add uniforms used in our target. */ + if (parameter_index == -1) + continue; + + if (type->is_vector() || + type->is_scalar()) { + size = type->vector_elements; + } else { + size = type_size(type) * 4; + } + + if (type->is_sampler() || + (type->is_array() && type->fields.array->is_sampler())) { + int array_length; - if (p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER) { - struct gl_uniform *uniform = - _mesa_append_uniform(uniforms, p->Name, prog->Target, i); - if (uniform) - uniform->Initialized = p->Initialized; + if (type->is_array()) + array_length = type->length; + else + array_length = 1; + + (void)_mesa_add_sampler(prog->Parameters, + uniform->Name, + type->gl_type, + array_length); + } else { + GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1, + uniform->Name); + + if (index < 0) { + index = _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM, + uniform->Name, size, type->gl_type, + NULL, NULL, 0x0); + + /* The location chosen in the Parameters list here (returned + * from _mesa_add_uniform) has to match what the linker chose. + */ + if (index != parameter_index) { + shader_program->InfoLog = + talloc_asprintf_append(shader_program->InfoLog, + "Allocation of uniform `%s' to target " + "failed (%d vs %d)\n", uniform->Name, + index, parameter_index); + shader_program->LinkStatus = false; + } + } } } } @@ -2498,6 +2457,8 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, v.ctx = ctx; v.prog = prog; + add_uniforms_to_parameters_list(shader_program, shader, prog); + /* Emit Mesa IR for main(). */ visit_exec_list(shader->ir, &v); v.ir_to_mesa_emit_op0(NULL, OPCODE_END); @@ -2676,8 +2637,6 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog) linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); - link_uniforms_to_shared_uniform_list(prog->Uniforms, linked_prog); - switch (prog->_LinkedShaders[i]->Type) { case GL_VERTEX_SHADER: _mesa_reference_vertprog(ctx, &prog->VertexProgram, @@ -2801,12 +2760,6 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) if (prog->LinkStatus) { link_shaders(ctx, prog); - - /* We don't use the linker's uniforms list, and cook up our own at - * generate time. - */ - _mesa_free_uniform_list(prog->Uniforms); - prog->Uniforms = _mesa_new_uniform_list(); } if (prog->LinkStatus) { diff --git a/src/mesa/program/prog_uniform.h b/src/mesa/program/prog_uniform.h index 7988d534a7..67f78006ea 100644 --- a/src/mesa/program/prog_uniform.h +++ b/src/mesa/program/prog_uniform.h @@ -51,10 +51,7 @@ struct gl_uniform GLint FragPos; GLint GeomPos; GLboolean Initialized; /**< For debug. Has this uniform been set? */ -#if 0 - GLenum DataType; /**< GL_FLOAT, GL_FLOAT_VEC2, etc */ - GLuint Size; /**< Number of components (1..4) */ -#endif + const struct glsl_type *Type; }; -- cgit v1.2.3 From aa452e20bff9aea2ecb994c9f7b413b0726a04f3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Aug 2010 21:43:07 -0700 Subject: ir_to_mesa: Add support for samplers in structures. Fixes: glsl-fs-uniform-sampler-struct glsl-fs-sampler-numbering-3 Bug #29690 --- src/mesa/program/ir_to_mesa.cpp | 231 +++++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 109 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 4a4278eb1a..7fb5974946 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -173,6 +173,7 @@ public: GLcontext *ctx; struct gl_program *prog; + struct gl_shader_program *shader_program; int next_temp; @@ -260,10 +261,7 @@ public: GLboolean try_emit_mad(ir_expression *ir, int mul_operand); - struct hash_table *sampler_map; - - void set_sampler_location(ir_variable *sampler, int location); - int get_sampler_location(ir_variable *sampler); + int get_sampler_uniform_value(ir_dereference *deref); void *mem_ctx; }; @@ -368,25 +366,6 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op0(ir_instruction *ir, ir_to_mesa_undef); } -void -ir_to_mesa_visitor::set_sampler_location(ir_variable *sampler, int location) -{ - if (this->sampler_map == NULL) { - this->sampler_map = hash_table_ctor(0, hash_table_pointer_hash, - hash_table_pointer_compare); - } - - hash_table_insert(this->sampler_map, (void *)(uintptr_t)location, sampler); -} - -int -ir_to_mesa_visitor::get_sampler_location(ir_variable *sampler) -{ - void *result = hash_table_find(this->sampler_map, sampler); - - return (int)(uintptr_t)result; -} - inline ir_to_mesa_dst_reg ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg) { @@ -1308,27 +1287,6 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) if (entry) break; - if (ir->var->type->base_type == GLSL_TYPE_SAMPLER || - (ir->var->type->base_type == GLSL_TYPE_ARRAY && - ir->var->type->fields.array->base_type == GLSL_TYPE_SAMPLER)) { - int array_length; - - if (ir->var->type->base_type == GLSL_TYPE_ARRAY) - array_length = ir->var->type->length; - else - array_length = 1; - int sampler = _mesa_add_sampler(this->prog->Parameters, - ir->var->name, - ir->var->type->gl_type, - array_length); - set_sampler_location(ir->var, sampler); - - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_SAMPLER, - sampler); - this->variables.push_tail(entry); - break; - } - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM, ir->var->location); this->variables.push_tail(entry); @@ -1825,6 +1783,91 @@ ir_to_mesa_visitor::visit(ir_call *ir) this->result = entry->return_reg; } +class get_sampler_name : public ir_hierarchical_visitor +{ +public: + get_sampler_name(ir_to_mesa_visitor *mesa, ir_dereference *last) + { + this->mem_ctx = mesa->mem_ctx; + this->mesa = mesa; + this->name = NULL; + this->offset = 0; + this->last = last; + } + + virtual ir_visitor_status visit(ir_dereference_variable *ir) + { + this->name = ir->var->name; + return visit_continue; + } + + virtual ir_visitor_status visit_leave(ir_dereference_record *ir) + { + this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field); + return visit_continue; + } + + virtual ir_visitor_status visit_leave(ir_dereference_array *ir) + { + ir_constant *index = ir->array_index->as_constant(); + int i; + + if (index) { + i = index->value.i[0]; + } else { + /* GLSL 1.10 and 1.20 allowed variable sampler array indices, + * while GLSL 1.30 requires that the array indices be + * constant integer expressions. We don't expect any driver + * to actually work with a really variable array index, so + * all that would work would be an unrolled loop counter that ends + * up being constant above. + */ + mesa->shader_program->InfoLog = + talloc_asprintf_append(mesa->shader_program->InfoLog, + "warning: Variable sampler array index " + "unsupported.\nThis feature of the language " + "was removed in GLSL 1.20 and is unlikely " + "to be supported for 1.10 in Mesa.\n"); + i = 0; + } + if (ir != last) { + this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i); + } else { + offset = i; + } + return visit_continue; + } + + ir_to_mesa_visitor *mesa; + const char *name; + void *mem_ctx; + int offset; + ir_dereference *last; +}; + +int +ir_to_mesa_visitor::get_sampler_uniform_value(ir_dereference *sampler) +{ + get_sampler_name getname(this, sampler); + + sampler->accept(&getname); + + GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1, + getname.name); + + if (index < 0) { + this->shader_program->InfoLog = + talloc_asprintf_append(this->shader_program->InfoLog, + "failed to find sampler named %s.\n", + getname.name); + this->shader_program->LinkStatus = GL_FALSE; + return 0; + } + + index += getname.offset; + + return this->prog->Parameters->ParameterValues[index][0]; +} void ir_to_mesa_visitor::visit(ir_texture *ir) @@ -1925,34 +1968,9 @@ ir_to_mesa_visitor::visit(ir_texture *ir) if (ir->shadow_comparitor) inst->tex_shadow = GL_TRUE; - ir_variable *sampler = ir->sampler->variable_referenced(); + inst->sampler = get_sampler_uniform_value(ir->sampler); - /* generate the mapping, remove when we generate storage at - * declaration time - */ - ir->sampler->accept(this); - - inst->sampler = get_sampler_location(sampler); - - ir_dereference_array *sampler_array = ir->sampler->as_dereference_array(); - if (sampler_array) { - ir_constant *array_index = - sampler_array->array_index->constant_expression_value(); - - /* GLSL 1.10 and 1.20 allowed variable sampler array indices, - * while GLSL 1.30 requires that the array indices be constant - * integer expressions. We don't expect any driver to actually - * work with a really variable array index, and in 1.20 all that - * would work would be an unrolled loop counter, so assert that - * we ended up with a constant at least.. - */ - assert(array_index); - inst->sampler += array_index->value.i[0]; - } - - const glsl_type *sampler_type = sampler->type; - while (sampler_type->base_type == GLSL_TYPE_ARRAY) - sampler_type = sampler_type->fields.array; + const glsl_type *sampler_type = ir->sampler->type; switch (sampler_type->sampler_dimensionality) { case GLSL_SAMPLER_DIM_1D: @@ -2066,7 +2084,6 @@ ir_to_mesa_visitor::ir_to_mesa_visitor() result.file = PROGRAM_UNDEFINED; next_temp = 1; next_signature_id = 1; - sampler_map = NULL; current_function = NULL; mem_ctx = talloc_new(NULL); } @@ -2074,8 +2091,6 @@ ir_to_mesa_visitor::ir_to_mesa_visitor() ir_to_mesa_visitor::~ir_to_mesa_visitor() { talloc_free(mem_ctx); - if (this->sampler_map) - hash_table_dtor(this->sampler_map); } static struct prog_src_register @@ -2222,12 +2237,6 @@ count_resources(struct gl_program *prog) for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = &prog->Instructions[i]; - /* Instead of just using the uniform's value to map to a - * sampler, Mesa first allocates a separate number for the - * sampler (_mesa_add_sampler), then we reindex it down to a - * small integer (sampler_map[], SamplersUsed), then that gets - * mapped to the uniform's value, and we get an actual sampler. - */ if (_mesa_is_tex_instruction(inst->Opcode)) { prog->SamplerTargets[inst->TexSrcUnit] = (gl_texture_index)inst->TexSrcTarget; @@ -2252,6 +2261,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, struct gl_program *prog) { unsigned int i; + unsigned int next_sampler = 0; for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) { struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i; @@ -2282,39 +2292,41 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, size = type_size(type) * 4; } + gl_register_file file; if (type->is_sampler() || (type->is_array() && type->fields.array->is_sampler())) { - int array_length; + file = PROGRAM_SAMPLER; + } else { + file = PROGRAM_UNIFORM; + } - if (type->is_array()) - array_length = type->length; - else - array_length = 1; + GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1, + uniform->Name); - (void)_mesa_add_sampler(prog->Parameters, - uniform->Name, - type->gl_type, - array_length); - } else { - GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1, - uniform->Name); - - if (index < 0) { - index = _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM, - uniform->Name, size, type->gl_type, - NULL, NULL, 0x0); - - /* The location chosen in the Parameters list here (returned - * from _mesa_add_uniform) has to match what the linker chose. - */ - if (index != parameter_index) { - shader_program->InfoLog = - talloc_asprintf_append(shader_program->InfoLog, - "Allocation of uniform `%s' to target " - "failed (%d vs %d)\n", uniform->Name, - index, parameter_index); - shader_program->LinkStatus = false; - } + if (index < 0) { + index = _mesa_add_parameter(prog->Parameters, file, + uniform->Name, size, type->gl_type, + NULL, NULL, 0x0); + + /* Sampler uniform values are stored in prog->SamplerUnits, + * and the entry in that array is selected by this index we + * store in ParameterValues[]. + */ + if (file == PROGRAM_SAMPLER) { + for (unsigned int j = 0; j < size / 4; j++) + prog->Parameters->ParameterValues[index + j][0] = next_sampler++; + } + + /* The location chosen in the Parameters list here (returned + * from _mesa_add_uniform) has to match what the linker chose. + */ + if (index != parameter_index) { + shader_program->InfoLog = + talloc_asprintf_append(shader_program->InfoLog, + "Allocation of uniform `%s' to target " + "failed (%d vs %d)\n", uniform->Name, + index, parameter_index); + shader_program->LinkStatus = false; } } } @@ -2456,6 +2468,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, prog->Attributes = _mesa_new_parameter_list(); v.ctx = ctx; v.prog = prog; + v.shader_program = shader_program; add_uniforms_to_parameters_list(shader_program, shader, prog); -- cgit v1.2.3 From 264ba1ab88f273dc92add8018f24edcdd67fa5e5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 26 Aug 2010 11:23:09 -0700 Subject: ir_to_mesa: Don't assume that an ir_dereference_array is of a variable. Fixes: glsl-array-bounds-02 (software) glsl-array-bounds-04 glsl-array-bounds-06 (software) glsl-array-bounds-08 --- src/mesa/program/ir_to_mesa.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7fb5974946..948f09a851 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1382,7 +1382,8 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir) return; } - if (strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform && + if (var && + strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform && !var->type->is_matrix()) { ir_dereference_record *record = NULL; if (ir->array->ir_type == ir_type_dereference_record) -- cgit v1.2.3 From 0a46497a4ee3325fab47929cb17cfe2525e1fc33 Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Sun, 29 Aug 2010 11:31:33 -0700 Subject: ir_to_mesa: Initialize variable in ir_to_mesa_visitor::visit. Fixes piglit glsl-fs-loop valgrind uninitialized value error on softpipe and llvmpipe. --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 948f09a851..19f3847ab5 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1553,7 +1553,7 @@ void ir_to_mesa_visitor::visit(ir_constant *ir) { ir_to_mesa_src_reg src_reg; - GLfloat stack_vals[4]; + GLfloat stack_vals[4] = { 0 }; GLfloat *values = stack_vals; unsigned int i; -- cgit v1.2.3 From 4841c0a15adcc722e67d7d246987cd686d3f7a17 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Mon, 30 Aug 2010 13:59:24 +0100 Subject: mesa: Return after assertion failure. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the warnings: warning: ‘target’ may be used uninitialized in this function warning: ‘target_string’ may be used uninitialized in this function --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 19f3847ab5..af6d7345a5 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2456,7 +2456,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, break; default: assert(!"should not be reached"); - break; + return NULL; } validate_ir_tree(shader->ir); -- cgit v1.2.3 From 4f189b3bf57a6500953dac49105f160af5fa6468 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Tue, 31 Aug 2010 05:38:50 +0200 Subject: ir_to_mesa: use RSQ+MUL instead of RSQ+RCP for SQRT sqrt(x) = 1/rsq(x) = x*rsq(x) This optimization already was in the old GLSL compiler. Acked on irc by Eric Anholt. --- src/mesa/program/ir_to_mesa.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index af6d7345a5..516c991855 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -880,8 +880,9 @@ ir_to_mesa_visitor::visit(ir_expression *ir) break; case ir_unop_sqrt: + /* sqrt(x) = x * rsq(x). */ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); - ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, result_src); + ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, result_src, op[0]); /* For incoming channels < 0, set the result to 0. */ ir_to_mesa_emit_op3(ir, OPCODE_CMP, result_dst, op[0], src_reg_for_float(0.0), result_src); -- cgit v1.2.3 From 7406898441bfec937840d575500fb6d43192310d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Aug 2010 14:42:27 -0700 Subject: ir_to_mesa: Set up our instruction nodes with zeroed data. cond_update wasn't being set by emit_op3, leading to valgrind complaints, and failures in several piglit tests when built with clang. --- src/mesa/program/ir_to_mesa.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 516c991855..768c11e3bf 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -105,6 +105,18 @@ extern ir_to_mesa_src_reg ir_to_mesa_undef; class ir_to_mesa_instruction : public exec_node { public: + /* Callers of this talloc-based new need not call delete. It's + * easier to just talloc_free 'ctx' (or any of its ancestors). */ + static void* operator new(size_t size, void *ctx) + { + void *node; + + node = talloc_zero_size(ctx, size); + assert(node != NULL); + + return node; + } + enum prog_opcode op; ir_to_mesa_dst_reg dst_reg; ir_to_mesa_src_reg src_reg[3]; -- cgit v1.2.3 From 2a78807db7a3bc852da0cda1e933a157204c3a47 Mon Sep 17 00:00:00 2001 From: nobled Date: Sun, 22 Aug 2010 05:16:53 +0000 Subject: ir_to_mesa: Fix struct/class confusion --- src/mesa/program/ir_to_mesa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 768c11e3bf..337ecbaa93 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1369,7 +1369,7 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir) if (deref_var && strncmp(deref_var->var->name, "gl_TextureMatrix", strlen("gl_TextureMatrix")) == 0) { - struct variable_storage *entry; + variable_storage *entry; entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, deref_var->var, ir->array_index); -- cgit v1.2.3 From 99f3c9caa39fbe9dfa7561c919202395720e9472 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Aug 2010 11:16:09 -0700 Subject: ir_to_mesa: Sort the uniform list we're adding to Parameters[] order. Fixes glsl-uniform-linking-1 and failure to link a shader in Unigine. An alternative here would be to just ditch using _mesa_add_parameter and build the initial params list on our own, but that would require two walks of the list as well. Bug #29822 --- src/mesa/program/ir_to_mesa.cpp | 46 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 337ecbaa93..8f39a225af 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2264,6 +2264,25 @@ count_resources(struct gl_program *prog) _mesa_update_shader_textures_used(prog); } +struct uniform_sort { + struct gl_uniform *u; + int pos; +}; + +/* The shader_program->Uniforms list is almost sorted in increasing + * uniform->{Frag,Vert}Pos locations, but not quite when there are + * uniforms shared between targets. We need to add parameters in + * increasing order for the targets. + */ +static int +sort_uniforms(const void *a, const void *b) +{ + struct uniform_sort *u1 = (struct uniform_sort *)a; + struct uniform_sort *u2 = (struct uniform_sort *)b; + + return u1->pos - u2->pos; +} + /* Add the uniforms to the parameters. The linker chose locations * in our parameters lists (which weren't created yet), which the * uniforms code will use to poke values into our parameters list @@ -2275,12 +2294,14 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, struct gl_program *prog) { unsigned int i; - unsigned int next_sampler = 0; + unsigned int next_sampler = 0, num_uniforms = 0; + struct uniform_sort *sorted_uniforms; + + sorted_uniforms = talloc_array(NULL, struct uniform_sort, + shader_program->Uniforms->NumUniforms); for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) { struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i; - const glsl_type *type = uniform->Type; - unsigned int size; int parameter_index = -1; switch (shader->Type) { @@ -2296,8 +2317,21 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, } /* Only add uniforms used in our target. */ - if (parameter_index == -1) - continue; + if (parameter_index != -1) { + sorted_uniforms[num_uniforms].pos = parameter_index; + sorted_uniforms[num_uniforms].u = uniform; + num_uniforms++; + } + } + + qsort(sorted_uniforms, num_uniforms, sizeof(struct uniform_sort), + sort_uniforms); + + for (i = 0; i < num_uniforms; i++) { + struct gl_uniform *uniform = sorted_uniforms[i].u; + int parameter_index = sorted_uniforms[i].pos; + const glsl_type *type = uniform->Type; + unsigned int size; if (type->is_vector() || type->is_scalar()) { @@ -2344,6 +2378,8 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, } } } + + talloc_free(sorted_uniforms); } static void -- cgit v1.2.3 From 9b075cb9fa9eb6a95d0816283ef01ae72dafa680 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Aug 2010 13:02:59 -0700 Subject: ir_to_mesa: When emitting a pixel kill, flag that we did so. Both i965 and swrast rely on UsesKill to determine whether to do early depth writes. Fixes glsl-fs-discard-02. Bug #29835. --- src/mesa/program/ir_to_mesa.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 8f39a225af..57458d0281 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2041,9 +2041,12 @@ ir_to_mesa_visitor::visit(ir_return *ir) void ir_to_mesa_visitor::visit(ir_discard *ir) { + struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; + assert(ir->condition == NULL); /* FINISHME */ ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV); + fp->UsesKill = GL_TRUE; } void -- cgit v1.2.3 From 500e7b75995460537b0e682e5bde4c32eb40b85c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Sep 2010 14:56:43 -0700 Subject: ir_to_mesa: Add a little helper for emitting link failure messages. --- src/mesa/program/ir_to_mesa.cpp | 46 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 57458d0281..2b833702e9 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -288,6 +288,18 @@ ir_to_mesa_dst_reg ir_to_mesa_address_reg = { PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL }; +static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3); + +static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) + { + va_list args; + va_start(args, fmt); + prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args); + va_end(args); + + prog->LinkStatus = GL_FALSE; + } + static int swizzle_for_size(int size) { int size_swizzles[4] = { @@ -1870,11 +1882,8 @@ ir_to_mesa_visitor::get_sampler_uniform_value(ir_dereference *sampler) getname.name); if (index < 0) { - this->shader_program->InfoLog = - talloc_asprintf_append(this->shader_program->InfoLog, - "failed to find sampler named %s.\n", - getname.name); - this->shader_program->LinkStatus = GL_FALSE; + fail_link(this->shader_program, + "failed to find sampler named %s.\n", getname.name); return 0; } @@ -2372,12 +2381,9 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, * from _mesa_add_uniform) has to match what the linker chose. */ if (index != parameter_index) { - shader_program->InfoLog = - talloc_asprintf_append(shader_program->InfoLog, - "Allocation of uniform `%s' to target " - "failed (%d vs %d)\n", uniform->Name, - index, parameter_index); - shader_program->LinkStatus = false; + fail_link(shader_program, "Allocation of uniform `%s' to target " + "failed (%d vs %d)\n", + uniform->Name, index, parameter_index); } } } @@ -2410,12 +2416,9 @@ set_uniform_initializer(GLcontext *ctx, void *mem_ctx, int loc = _mesa_get_uniform_location(ctx, shader_program, name); if (loc == -1) { - shader_program->InfoLog = - talloc_asprintf_append(shader_program->InfoLog, - "Couldn't find uniform for " - "initializer %s\n", name); - shader_program->LinkStatus = false; - abort(); + fail_link(shader_program, + "Couldn't find uniform for initializer %s\n", name); + return; } for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) { @@ -2600,10 +2603,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File; if (ctx->Shader.EmitNoIfs && mesa_inst->Opcode == OPCODE_IF) { - shader_program->InfoLog = - talloc_asprintf_append(shader_program->InfoLog, - "Couldn't flatten if statement\n"); - shader_program->LinkStatus = false; + fail_link(shader_program, "Couldn't flatten if statement\n"); } switch (mesa_inst->Opcode) { @@ -2813,9 +2813,7 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) for (i = 0; i < prog->NumShaders; i++) { if (!prog->Shaders[i]->CompileStatus) { - prog->InfoLog = - talloc_asprintf_append(prog->InfoLog, - "linking with uncompiled shader"); + fail_link(prog, "linking with uncompiled shader"); prog->LinkStatus = GL_FALSE; } } -- cgit v1.2.3 From 5ad74779cea07cc6a19a52874cdaef8b018e2f1b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Sep 2010 16:06:32 -0700 Subject: ir_to_mesa: Load all the STATE_VAR elements of a builtin uniform to a temp. Like the constant handling and the handling of other uniforms, we add the whole thing to the Parameters, avoiding messy, incomplete logic for adding just the elements of a builting uniform that get used. This means that a driver that relies only on ParameterValues[] for its parameters will have an increased parameter load, but drivers generally don't do that (since they have other params they need to handle, too). Fixes glsl-fs-statevar-call (testcase for Ember). Bug #29687. Regresses glsl-vs-array-04 on 965. Thanks to a slight change in register allocation, this test of undefined behavior now wraps around the register space and unexpectedly reads the constant value it's trying to compare to. The test should probably not look at the resulting color, since behavior is undefined. --- src/mesa/program/ir_to_mesa.cpp | 636 ++++++++++++++++++---------------------- 1 file changed, 291 insertions(+), 345 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 2b833702e9..b2ba9a2fbc 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -577,6 +577,239 @@ ir_to_mesa_visitor::find_variable_storage(ir_variable *var) return NULL; } +struct statevar_element { + const char *field; + int tokens[STATE_LENGTH]; + int swizzle; + bool array_indexed; +}; + +static struct statevar_element gl_DepthRange_elements[] = { + {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX}, + {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY}, + {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ}, +}; + +static struct statevar_element gl_ClipPlane_elements[] = { + {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW} +}; + +static struct statevar_element gl_Point_elements[] = { + {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX}, + {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY}, + {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ}, + {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW}, + {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX}, + {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY}, + {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ}, +}; + +static struct statevar_element gl_FrontMaterial_elements[] = { + {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW}, + {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, + {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX}, +}; + +static struct statevar_element gl_BackMaterial_elements[] = { + {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW}, + {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, + {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX}, +}; + +static struct statevar_element gl_LightSource_elements[] = { + {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, + {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW}, + {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW}, + {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW}, + {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW}, + {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX}, + {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW}, + {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX}, + {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY}, + {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ}, +}; + +static struct statevar_element gl_LightModel_elements[] = { + {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_FrontLightModelProduct_elements[] = { + {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_BackLightModelProduct_elements[] = { + {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_FrontLightProduct_elements[] = { + {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_BackLightProduct_elements[] = { + {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, + {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, + {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_TextureEnvColor_elements[] = { + {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_EyePlaneS_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_EyePlaneT_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_EyePlaneR_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_EyePlaneQ_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_ObjectPlaneS_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_ObjectPlaneT_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_ObjectPlaneR_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_ObjectPlaneQ_elements[] = { + {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW}, +}; + +static struct statevar_element gl_Fog_elements[] = { + {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW}, + {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX}, + {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY}, + {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ}, + {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW}, +}; + +#define MATRIX(name, statevar, modifier) \ + static struct statevar_element name ## _elements[] = { \ + { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \ + { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \ + { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \ + { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW }, \ + } + +MATRIX(gl_ModelViewMatrix, + STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE); +MATRIX(gl_ModelViewMatrixInverse, + STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS); +MATRIX(gl_ModelViewMatrixTranspose, + STATE_MODELVIEW_MATRIX, 0); +MATRIX(gl_ModelViewMatrixInverseTranspose, + STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE); + +MATRIX(gl_ProjectionMatrix, + STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE); +MATRIX(gl_ProjectionMatrixInverse, + STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS); +MATRIX(gl_ProjectionMatrixTranspose, + STATE_PROJECTION_MATRIX, 0); +MATRIX(gl_ProjectionMatrixInverseTranspose, + STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE); + +MATRIX(gl_ModelViewProjectionMatrix, + STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE); +MATRIX(gl_ModelViewProjectionMatrixInverse, + STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS); +MATRIX(gl_ModelViewProjectionMatrixTranspose, + STATE_MVP_MATRIX, 0); +MATRIX(gl_ModelViewProjectionMatrixInverseTranspose, + STATE_MVP_MATRIX, STATE_MATRIX_INVERSE); + +MATRIX(gl_TextureMatrix, + STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE); +MATRIX(gl_TextureMatrixInverse, + STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS); +MATRIX(gl_TextureMatrixTranspose, + STATE_TEXTURE_MATRIX, 0); +MATRIX(gl_TextureMatrixInverseTranspose, + STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE); + +static struct statevar_element gl_NormalMatrix_elements[] = { + { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE}, + SWIZZLE_XYZW }, + { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE}, + SWIZZLE_XYZW }, + { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE}, + SWIZZLE_XYZW }, +}; + +#undef MATRIX + +#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)} + +static struct { + const char *name; + struct statevar_element *elements; + int num_elements; +} statevars[] = { + STATEVAR(gl_DepthRange), + STATEVAR(gl_ClipPlane), + STATEVAR(gl_Point), + STATEVAR(gl_FrontMaterial), + STATEVAR(gl_BackMaterial), + STATEVAR(gl_LightSource), + STATEVAR(gl_LightModel), + STATEVAR(gl_FrontLightModelProduct), + STATEVAR(gl_BackLightModelProduct), + STATEVAR(gl_FrontLightProduct), + STATEVAR(gl_BackLightProduct), + STATEVAR(gl_TextureEnvColor), + STATEVAR(gl_EyePlaneS), + STATEVAR(gl_EyePlaneT), + STATEVAR(gl_EyePlaneR), + STATEVAR(gl_EyePlaneQ), + STATEVAR(gl_ObjectPlaneS), + STATEVAR(gl_ObjectPlaneT), + STATEVAR(gl_ObjectPlaneR), + STATEVAR(gl_ObjectPlaneQ), + STATEVAR(gl_Fog), + + STATEVAR(gl_ModelViewMatrix), + STATEVAR(gl_ModelViewMatrixInverse), + STATEVAR(gl_ModelViewMatrixTranspose), + STATEVAR(gl_ModelViewMatrixInverseTranspose), + + STATEVAR(gl_ProjectionMatrix), + STATEVAR(gl_ProjectionMatrixInverse), + STATEVAR(gl_ProjectionMatrixTranspose), + STATEVAR(gl_ProjectionMatrixInverseTranspose), + + STATEVAR(gl_ModelViewProjectionMatrix), + STATEVAR(gl_ModelViewProjectionMatrixInverse), + STATEVAR(gl_ModelViewProjectionMatrixTranspose), + STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose), + + STATEVAR(gl_TextureMatrix), + STATEVAR(gl_TextureMatrixInverse), + STATEVAR(gl_TextureMatrixTranspose), + STATEVAR(gl_TextureMatrixInverseTranspose), + + STATEVAR(gl_NormalMatrix), +}; + void ir_to_mesa_visitor::visit(ir_variable *ir) { @@ -586,6 +819,64 @@ ir_to_mesa_visitor::visit(ir_variable *ir) fp->OriginUpperLeft = ir->origin_upper_left; fp->PixelCenterInteger = ir->pixel_center_integer; } + + if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { + unsigned int i; + + struct variable_storage *entry; + entry = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY, + this->next_temp); + this->variables.push_tail(entry); + this->next_temp += type_size(ir->type); + + for (i = 0; i < Elements(statevars); i++) { + if (strcmp(ir->name, statevars[i].name) == 0) + break; + } + + if (i == Elements(statevars)) { + fail_link(this->shader_program, + "Failed to find builtin uniform `%s'\n", ir->name); + return; + } + + ir_to_mesa_dst_reg dst = + ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY, + entry->index, NULL)); + + int array_count; + if (ir->type->is_array()) { + array_count = ir->type->length; + } else { + array_count = 1; + } + + for (int a = 0; a < array_count; a++) { + for (int j = 0; j < statevars[i].num_elements; j++) { + struct statevar_element *element = &statevars[i].elements[j]; + int tokens[STATE_LENGTH]; + + memcpy(tokens, element->tokens, sizeof(element->tokens)); + if (ir->type->is_array()) { + tokens[1] = a; + } + + int index = _mesa_add_state_reference(this->prog->Parameters, + (gl_state_index *)tokens); + ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL); + src.swizzle = element->swizzle; + ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src); + /* even a float takes up a whole vec4 reg in a struct/array. */ + dst.index++; + } + } + if (dst.index != entry->index + type_size(ir->type)) { + fail_link(this->shader_program, + "failed to load builtin uniform `%s' (%d/%d regs loaded)\n", + ir->name, dst.index - entry->index, + type_size(ir->type)); + } + } } void @@ -1016,289 +1307,6 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir) this->result = src_reg; } -static const struct { - const char *name; - const char *field; - int tokens[STATE_LENGTH]; - int swizzle; - bool array_indexed; -} statevars[] = { - {"gl_DepthRange", "near", - {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX, false}, - {"gl_DepthRange", "far", - {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY, false}, - {"gl_DepthRange", "diff", - {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ, false}, - - {"gl_ClipPlane", NULL, - {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW, true} -, - {"gl_Point", "size", - {STATE_POINT_SIZE}, SWIZZLE_XXXX, false}, - {"gl_Point", "sizeMin", - {STATE_POINT_SIZE}, SWIZZLE_YYYY, false}, - {"gl_Point", "sizeMax", - {STATE_POINT_SIZE}, SWIZZLE_ZZZZ, false}, - {"gl_Point", "fadeThresholdSize", - {STATE_POINT_SIZE}, SWIZZLE_WWWW, false}, - {"gl_Point", "distanceConstantAttenuation", - {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX, false}, - {"gl_Point", "distanceLinearAttenuation", - {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY, false}, - {"gl_Point", "distanceQuadraticAttenuation", - {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ, false}, - - {"gl_FrontMaterial", "emission", - {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW, false}, - {"gl_FrontMaterial", "ambient", - {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW, false}, - {"gl_FrontMaterial", "diffuse", - {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, false}, - {"gl_FrontMaterial", "specular", - {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW, false}, - {"gl_FrontMaterial", "shininess", - {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX, false}, - - {"gl_BackMaterial", "emission", - {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW, false}, - {"gl_BackMaterial", "ambient", - {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW, false}, - {"gl_BackMaterial", "diffuse", - {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, false}, - {"gl_BackMaterial", "specular", - {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW, false}, - {"gl_BackMaterial", "shininess", - {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX, false}, - - {"gl_LightSource", "ambient", - {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true}, - {"gl_LightSource", "diffuse", - {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true}, - {"gl_LightSource", "specular", - {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true}, - {"gl_LightSource", "position", - {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW, true}, - {"gl_LightSource", "halfVector", - {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW, true}, - {"gl_LightSource", "spotDirection", - {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW, true}, - {"gl_LightSource", "spotCosCutoff", - {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW, true}, - {"gl_LightSource", "spotCutoff", - {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX, true}, - {"gl_LightSource", "spotExponent", - {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW, true}, - {"gl_LightSource", "constantAttenuation", - {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX, true}, - {"gl_LightSource", "linearAttenuation", - {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY, true}, - {"gl_LightSource", "quadraticAttenuation", - {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ, true}, - - {"gl_LightModel", "ambient", - {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW, false}, - - {"gl_FrontLightModelProduct", "sceneColor", - {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW, false}, - {"gl_BackLightModelProduct", "sceneColor", - {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW, false}, - - {"gl_FrontLightProduct", "ambient", - {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true}, - {"gl_FrontLightProduct", "diffuse", - {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true}, - {"gl_FrontLightProduct", "specular", - {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true}, - - {"gl_BackLightProduct", "ambient", - {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW, true}, - {"gl_BackLightProduct", "diffuse", - {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, true}, - {"gl_BackLightProduct", "specular", - {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW, true}, - - {"gl_TextureEnvColor", NULL, - {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW, true}, - - {"gl_EyePlaneS", NULL, - {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW, true}, - {"gl_EyePlaneT", NULL, - {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW, true}, - {"gl_EyePlaneR", NULL, - {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW, true}, - {"gl_EyePlaneQ", NULL, - {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW, true}, - - {"gl_ObjectPlaneS", NULL, - {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW, true}, - {"gl_ObjectPlaneT", NULL, - {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW, true}, - {"gl_ObjectPlaneR", NULL, - {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW, true}, - {"gl_ObjectPlaneQ", NULL, - {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW, true}, - - {"gl_Fog", "color", - {STATE_FOG_COLOR}, SWIZZLE_XYZW, false}, - {"gl_Fog", "density", - {STATE_FOG_PARAMS}, SWIZZLE_XXXX, false}, - {"gl_Fog", "start", - {STATE_FOG_PARAMS}, SWIZZLE_YYYY, false}, - {"gl_Fog", "end", - {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ, false}, - {"gl_Fog", "scale", - {STATE_FOG_PARAMS}, SWIZZLE_WWWW, false}, -}; - -static ir_to_mesa_src_reg -get_builtin_uniform_reg(struct gl_program *prog, - const char *name, int array_index, const char *field) -{ - unsigned int i; - ir_to_mesa_src_reg src_reg; - int tokens[STATE_LENGTH]; - - for (i = 0; i < Elements(statevars); i++) { - if (strcmp(statevars[i].name, name) != 0) - continue; - if (!field && statevars[i].field) { - assert(!"FINISHME: whole-structure state var dereference"); - } - if (field && (!statevars[i].field || strcmp(statevars[i].field, field) != 0)) - continue; - break; - } - - if (i == Elements(statevars)) { - printf("builtin uniform %s%s%s not found\n", - name, - field ? "." : "", - field ? field : ""); - abort(); - } - - memcpy(&tokens, statevars[i].tokens, sizeof(tokens)); - if (statevars[i].array_indexed) - tokens[1] = array_index; - - src_reg.file = PROGRAM_STATE_VAR; - src_reg.index = _mesa_add_state_reference(prog->Parameters, - (gl_state_index *)tokens); - src_reg.swizzle = statevars[i].swizzle; - src_reg.negate = 0; - src_reg.reladdr = false; - - return src_reg; -} - -static int -add_matrix_ref(struct gl_program *prog, int *tokens) -{ - int base_pos = -1; - int i; - - /* Add a ref for each column. It looks like the reason we do - * it this way is that _mesa_add_state_reference doesn't work - * for things that aren't vec4s, so the tokens[2]/tokens[3] - * range has to be equal. - */ - for (i = 0; i < 4; i++) { - tokens[2] = i; - tokens[3] = i; - int pos = _mesa_add_state_reference(prog->Parameters, - (gl_state_index *)tokens); - if (base_pos == -1) - base_pos = pos; - else - assert(base_pos + i == pos); - } - - return base_pos; -} - -static variable_storage * -get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var, - ir_rvalue *array_index) -{ - /* - * NOTE: The ARB_vertex_program extension specified that matrices get - * loaded in registers in row-major order. With GLSL, we want column- - * major order. So, we need to transpose all matrices here... - */ - static const struct { - const char *name; - int matrix; - int modifier; - } matrices[] = { - { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE }, - { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS }, - { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 }, - { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE }, - - { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE }, - { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS }, - { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 }, - { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE }, - - { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE }, - { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS }, - { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 }, - { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE }, - - { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE }, - { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS }, - { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 }, - { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE }, - - { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE }, - - }; - unsigned int i; - variable_storage *entry; - - /* C++ gets angry when we try to use an int as a gl_state_index, so we use - * ints for gl_state_index. Make sure they're compatible. - */ - assert(sizeof(gl_state_index) == sizeof(int)); - - for (i = 0; i < Elements(matrices); i++) { - if (strcmp(var->name, matrices[i].name) == 0) { - int tokens[STATE_LENGTH]; - int base_pos = -1; - - tokens[0] = matrices[i].matrix; - tokens[4] = matrices[i].modifier; - if (matrices[i].matrix == STATE_TEXTURE_MATRIX) { - ir_constant *index = array_index->constant_expression_value(); - if (index) { - tokens[1] = index->value.i[0]; - base_pos = add_matrix_ref(prog, tokens); - } else { - for (i = 0; i < var->type->length; i++) { - tokens[1] = i; - int pos = add_matrix_ref(prog, tokens); - if (base_pos == -1) - base_pos = pos; - else - assert(base_pos + (int)i * 4 == pos); - } - } - } else { - tokens[1] = 0; /* unused array index */ - base_pos = add_matrix_ref(prog, tokens); - } - - entry = new(mem_ctx) variable_storage(var, - PROGRAM_STATE_VAR, - base_pos); - - return entry; - } - } - - return NULL; -} - void ir_to_mesa_visitor::visit(ir_dereference_variable *ir) { @@ -1307,11 +1315,6 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) if (!entry) { switch (ir->var->mode) { case ir_var_uniform: - entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, ir->var, - NULL); - if (entry) - break; - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM, ir->var->location); this->variables.push_tail(entry); @@ -1370,58 +1373,12 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) void ir_to_mesa_visitor::visit(ir_dereference_array *ir) { - ir_variable *var = ir->variable_referenced(); ir_constant *index; ir_to_mesa_src_reg src_reg; - ir_dereference_variable *deref_var = ir->array->as_dereference_variable(); int element_size = type_size(ir->type); index = ir->array_index->constant_expression_value(); - if (deref_var && strncmp(deref_var->var->name, - "gl_TextureMatrix", - strlen("gl_TextureMatrix")) == 0) { - variable_storage *entry; - - entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, deref_var->var, - ir->array_index); - assert(entry); - - ir_to_mesa_src_reg src_reg(entry->file, entry->index, ir->type); - - if (index) { - src_reg.reladdr = NULL; - } else { - ir_to_mesa_src_reg index_reg = get_temp(glsl_type::float_type); - - ir->array_index->accept(this); - ir_to_mesa_emit_op2(ir, OPCODE_MUL, - ir_to_mesa_dst_reg_from_src(index_reg), - this->result, src_reg_for_float(element_size)); - - src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg); - memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg)); - } - - this->result = src_reg; - return; - } - - if (var && - strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform && - !var->type->is_matrix()) { - ir_dereference_record *record = NULL; - if (ir->array->ir_type == ir_type_dereference_record) - record = (ir_dereference_record *)ir->array; - - assert(index || !"FINISHME: variable-indexed builtin uniform access"); - - this->result = get_builtin_uniform_reg(prog, - var->name, - index->value.i[0], - record ? record->field : NULL); - } - ir->array->accept(this); src_reg = this->result; @@ -1466,17 +1423,6 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) unsigned int i; const glsl_type *struct_type = ir->record->type; int offset = 0; - ir_variable *var = ir->record->variable_referenced(); - - if (strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform) { - assert(var); - - this->result = get_builtin_uniform_reg(prog, - var->name, - 0, - ir->field); - return; - } ir->record->accept(this); -- cgit v1.2.3 From c9039fdb167865547dc9b3828d69b99209344999 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 2 Sep 2010 07:58:28 -0600 Subject: mesa: fix code generation for ir_unop_sqrt The CMP instruction needed to be flipped to properly handle operand==0. Fixes fd.o bug 29923. --- src/mesa/program/ir_to_mesa.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/mesa/program/ir_to_mesa.cpp') diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index b2ba9a2fbc..f0e14b8ece 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1198,9 +1198,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir) /* sqrt(x) = x * rsq(x). */ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, result_src, op[0]); - /* For incoming channels < 0, set the result to 0. */ + /* For incoming channels <= 0, set the result to 0. */ + op[0].negate = ~op[0].negate; ir_to_mesa_emit_op3(ir, OPCODE_CMP, result_dst, - op[0], src_reg_for_float(0.0), result_src); + op[0], result_src, src_reg_for_float(0.0)); break; case ir_unop_rsq: ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); -- cgit v1.2.3