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') 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') 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') 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') 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') 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') 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 8bbdf6e7cdfc3265439761a06eea79627f4ee2fa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jul 2010 11:45:27 -0700 Subject: mesa: Allow large temporary indices coming into the temporary reg allocator. This gets glsl-vs-raytrace, glsl-fs-raytrace running on the new compiler. --- src/mesa/program/prog_optimize.c | 48 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'src/mesa/program') diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c index bd120b8643..457ace14c6 100644 --- a/src/mesa/program/prog_optimize.c +++ b/src/mesa/program/prog_optimize.c @@ -34,7 +34,12 @@ #define MAX_LOOP_NESTING 50 - +/* MAX_PROGRAM_TEMPS is a low number (256), and we want to be able to + * register allocate many temporary values into that small number of + * temps. So allow large temporary indices coming into the register + * allocator. + */ +#define REG_ALLOCATE_MAX_PROGRAM_TEMPS ((1 << INST_INDEX_BITS) - 1) static GLboolean dbg = GL_FALSE; @@ -154,8 +159,8 @@ replace_regs(struct gl_program *prog, gl_register_file file, const GLint map[]) static void _mesa_consolidate_registers(struct gl_program *prog) { - GLboolean tempUsed[MAX_PROGRAM_TEMPS]; - GLint tempMap[MAX_PROGRAM_TEMPS]; + GLboolean tempUsed[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; + GLint tempMap[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; GLuint tempMax = 0, i; if (dbg) { @@ -164,7 +169,7 @@ _mesa_consolidate_registers(struct gl_program *prog) memset(tempUsed, 0, sizeof(tempUsed)); - for (i = 0; i < MAX_PROGRAM_TEMPS; i++) { + for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++) { tempMap[i] = -1; } @@ -176,7 +181,7 @@ _mesa_consolidate_registers(struct gl_program *prog) for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) { const GLuint index = inst->SrcReg[j].Index; - ASSERT(index < MAX_PROGRAM_TEMPS); + ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); tempUsed[index] = GL_TRUE; tempMax = MAX2(tempMax, index); break; @@ -184,7 +189,7 @@ _mesa_consolidate_registers(struct gl_program *prog) } if (inst->DstReg.File == PROGRAM_TEMPORARY) { const GLuint index = inst->DstReg.Index; - ASSERT(index < MAX_PROGRAM_TEMPS); + ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); tempUsed[index] = GL_TRUE; tempMax = MAX2(tempMax, index); } @@ -225,7 +230,7 @@ _mesa_consolidate_registers(struct gl_program *prog) static void _mesa_remove_dead_code(struct gl_program *prog) { - GLboolean tempRead[MAX_PROGRAM_TEMPS][4]; + GLboolean tempRead[REG_ALLOCATE_MAX_PROGRAM_TEMPS][4]; GLboolean *removeInst; /* per-instruction removal flag */ GLuint i, rem = 0, comp; @@ -250,7 +255,7 @@ _mesa_remove_dead_code(struct gl_program *prog) if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) { const GLuint index = inst->SrcReg[j].Index; GLuint read_mask; - ASSERT(index < MAX_PROGRAM_TEMPS); + ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); read_mask = get_src_arg_mask(inst, j); if (inst->SrcReg[j].RelAddr) { @@ -286,7 +291,7 @@ _mesa_remove_dead_code(struct gl_program *prog) /* check dst reg */ if (inst->DstReg.File == PROGRAM_TEMPORARY) { const GLuint index = inst->DstReg.Index; - ASSERT(index < MAX_PROGRAM_TEMPS); + ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); if (inst->DstReg.RelAddr) { if (dbg) @@ -642,7 +647,7 @@ struct interval struct interval_list { GLuint Num; - struct interval Intervals[MAX_PROGRAM_TEMPS]; + struct interval Intervals[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; }; @@ -754,7 +759,7 @@ update_interval(GLint intBegin[], GLint intEnd[], } } - ASSERT(index < MAX_PROGRAM_TEMPS); + ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); if (intBegin[index] == -1) { ASSERT(intEnd[index] == -1); intBegin[index] = intEnd[index] = ic; @@ -771,14 +776,14 @@ update_interval(GLint intBegin[], GLint intEnd[], GLboolean _mesa_find_temp_intervals(const struct prog_instruction *instructions, GLuint numInstructions, - GLint intBegin[MAX_PROGRAM_TEMPS], - GLint intEnd[MAX_PROGRAM_TEMPS]) + GLint intBegin[REG_ALLOCATE_MAX_PROGRAM_TEMPS], + GLint intEnd[REG_ALLOCATE_MAX_PROGRAM_TEMPS]) { struct loop_info loopStack[MAX_LOOP_NESTING]; GLuint loopStackDepth = 0; GLuint i; - for (i = 0; i < MAX_PROGRAM_TEMPS; i++){ + for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){ intBegin[i] = intEnd[i] = -1; } @@ -833,7 +838,8 @@ static GLboolean find_live_intervals(struct gl_program *prog, struct interval_list *liveIntervals) { - GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS]; + GLint intBegin[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; + GLint intEnd[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; GLuint i; /* @@ -853,7 +859,7 @@ find_live_intervals(struct gl_program *prog, /* Build live intervals list from intermediate arrays */ liveIntervals->Num = 0; - for (i = 0; i < MAX_PROGRAM_TEMPS; i++) { + for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++) { if (intBegin[i] >= 0) { struct interval inv; inv.Reg = i; @@ -889,10 +895,10 @@ find_live_intervals(struct gl_program *prog, /** Scan the array of used register flags to find free entry */ static GLint -alloc_register(GLboolean usedRegs[MAX_PROGRAM_TEMPS]) +alloc_register(GLboolean usedRegs[REG_ALLOCATE_MAX_PROGRAM_TEMPS]) { GLuint k; - for (k = 0; k < MAX_PROGRAM_TEMPS; k++) { + for (k = 0; k < REG_ALLOCATE_MAX_PROGRAM_TEMPS; k++) { if (!usedRegs[k]) { usedRegs[k] = GL_TRUE; return k; @@ -914,8 +920,8 @@ static void _mesa_reallocate_registers(struct gl_program *prog) { struct interval_list liveIntervals; - GLint registerMap[MAX_PROGRAM_TEMPS]; - GLboolean usedRegs[MAX_PROGRAM_TEMPS]; + GLint registerMap[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; + GLboolean usedRegs[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; GLuint i; GLint maxTemp = -1; @@ -924,7 +930,7 @@ _mesa_reallocate_registers(struct gl_program *prog) _mesa_print_program(prog); } - for (i = 0; i < MAX_PROGRAM_TEMPS; i++){ + for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){ registerMap[i] = -1; usedRegs[i] = GL_FALSE; } -- 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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 955ceef47f2bb8b5005abf11d4a8580c71f19e1b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 2 Aug 2010 12:49:20 -0700 Subject: Keep a local copy of the symbol name in the symbol table The symbol_header structure that tracks symbols with a particular name may have a different (longer) life time than the symbols it tracks. Not keeping a local copy of the name can lead to use-after-free errors. For example, the following sequence would trigger such an error: char *copy = strdup(name); _mesa_symbol_table_push_scope(st); _mesa_symbol_table_add_symbol(st, 0, name, NULL); _mesa_symbol_table_pop_scope(st); free(name); _mesa_symbol_table_find_symbol(st, 0, copy); With this change, the symbol table keeps a local copy of the name that has the same life time as the symbol_header for that name. This resolves some use-after-free errors with built-in functions in the GLSL compiler. --- src/mesa/program/symbol_table.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/mesa/program') diff --git a/src/mesa/program/symbol_table.c b/src/mesa/program/symbol_table.c index 3fea5ee1f1..09e7cb44ef 100644 --- a/src/mesa/program/symbol_table.c +++ b/src/mesa/program/symbol_table.c @@ -75,7 +75,7 @@ struct symbol_header { struct symbol_header *next; /** Symbol name. */ - const char *name; + char *name; /** Linked list of symbols with the same name. */ struct symbol *symbols; @@ -337,9 +337,9 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table, if (hdr == NULL) { hdr = calloc(1, sizeof(*hdr)); - hdr->name = name; + hdr->name = strdup(name); - hash_table_insert(table->ht, hdr, name); + hash_table_insert(table->ht, hdr, hdr->name); hdr->next = table->hdr; table->hdr = hdr; } @@ -404,6 +404,7 @@ _mesa_symbol_table_dtor(struct _mesa_symbol_table *table) for (hdr = table->hdr; hdr != NULL; hdr = next) { next = hdr->next; + free(hdr->name); free(hdr); } -- 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') 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') 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') 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') 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') 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 8e181b629f97ada65cc1b8a17ba42edc2ea77254 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 14:13:08 -0700 Subject: mesa: Don't null deref looking for Mesa IR code at compile time. The new compiler doesn't generate Mesa IR at compile time, and that compile time code previously wouldn't have reflected the link time code that actually got used. But do dump the info log of the compile regardless. --- src/mesa/program/prog_print.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/mesa/program') diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index 6ab199aa02..b66d709d50 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -1031,11 +1031,9 @@ _mesa_write_shader_to_file(const struct gl_shader *shader) fprintf(f, "/* Compile status: %s */\n", shader->CompileStatus ? "ok" : "fail"); - if (!shader->CompileStatus) { - fprintf(f, "/* Log Info: */\n"); - fputs(shader->InfoLog, f); - } - else { + fprintf(f, "/* Log Info: */\n"); + fputs(shader->InfoLog, f); + if (shader->CompileStatus && shader->Program) { fprintf(f, "/* GPU code */\n"); fprintf(f, "/*\n"); _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE); -- 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') 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') 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') 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 72fd0568db0ce5f25a1eee0266ec1e7cb3dafab0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 19:55:52 -0700 Subject: i965: Settle on printing our program debug to stdout. Mixing stderr (_mesa_print_program, _mesa_print_instruction, _mesa_print_alu) with stdout means that when writing both to a file, there isn't a consistent ordering between the two. --- src/mesa/drivers/dri/i965/brw_vs.c | 8 ++++---- src/mesa/drivers/dri/i965/brw_vs_emit.c | 3 ++- src/mesa/drivers/dri/i965/brw_wm_fp.c | 10 +++++----- src/mesa/program/prog_print.c | 32 ++++++++++++++++---------------- src/mesa/program/prog_print.h | 7 +++++++ 5 files changed, 34 insertions(+), 26 deletions(-) (limited to 'src/mesa/program') diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c index 9a832af9a9..9f90e1e5e5 100644 --- a/src/mesa/drivers/dri/i965/brw_vs.c +++ b/src/mesa/drivers/dri/i965/brw_vs.c @@ -75,10 +75,10 @@ static void do_vs_prog( struct brw_context *brw, c.prog_data.outputs_written |= BITFIELD64_BIT(VERT_RESULT_TEX0 + i); } - if (0) - _mesa_print_program(&c.vp->program.Base); - - + if (0) { + _mesa_fprint_program_opt(stdout, &c.vp->program.Base, PROG_PRINT_DEBUG, + GL_TRUE); + } /* Emit GEN4 code. */ diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c index c1d6525e9b..d2bd2c7f79 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c @@ -1564,7 +1564,8 @@ void brw_vs_emit(struct brw_vs_compile *c ) if (INTEL_DEBUG & DEBUG_VS) { printf("vs-mesa:\n"); - _mesa_print_program(&c->vp->program.Base); + _mesa_fprint_program_opt(stdout, &c->vp->program.Base, PROG_PRINT_DEBUG, + GL_TRUE); printf("\n"); } diff --git a/src/mesa/drivers/dri/i965/brw_wm_fp.c b/src/mesa/drivers/dri/i965/brw_wm_fp.c index df9e54c6b4..3870bf10fc 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_fp.c +++ b/src/mesa/drivers/dri/i965/brw_wm_fp.c @@ -1037,13 +1037,12 @@ static void print_insns( const struct prog_instruction *insn, for (i = 0; i < nr; i++, insn++) { printf("%3d: ", i); if (insn->Opcode < MAX_OPCODE) - _mesa_print_instruction(insn); + _mesa_fprint_instruction_opt(stdout, insn, 0, PROG_PRINT_DEBUG, NULL); else if (insn->Opcode < MAX_WM_OPCODE) { GLuint idx = insn->Opcode - MAX_OPCODE; - _mesa_print_alu_instruction(insn, - wm_opcode_strings[idx], - 3); + _mesa_fprint_alu_instruction(stdout, insn, wm_opcode_strings[idx], + 3, PROG_PRINT_DEBUG, NULL); } else printf("965 Opcode %d\n", insn->Opcode); @@ -1062,7 +1061,8 @@ void brw_wm_pass_fp( struct brw_wm_compile *c ) if (INTEL_DEBUG & DEBUG_WM) { printf("pre-fp:\n"); - _mesa_print_program(&fp->program.Base); + _mesa_fprint_program_opt(stdout, &fp->program.Base, PROG_PRINT_DEBUG, + GL_TRUE); printf("\n"); } diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index b66d709d50..1ce1bf2f4e 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -540,12 +540,12 @@ fprint_comment(FILE *f, const struct prog_instruction *inst) } -static void -fprint_alu_instruction(FILE *f, - const struct prog_instruction *inst, - const char *opcode_string, GLuint numRegs, - gl_prog_print_mode mode, - const struct gl_program *prog) +void +_mesa_fprint_alu_instruction(FILE *f, + const struct prog_instruction *inst, + const char *opcode_string, GLuint numRegs, + gl_prog_print_mode mode, + const struct gl_program *prog) { GLuint j; @@ -582,8 +582,8 @@ void _mesa_print_alu_instruction(const struct prog_instruction *inst, const char *opcode_string, GLuint numRegs) { - fprint_alu_instruction(stderr, inst, opcode_string, - numRegs, PROG_PRINT_DEBUG, NULL); + _mesa_fprint_alu_instruction(stderr, inst, opcode_string, + numRegs, PROG_PRINT_DEBUG, NULL); } @@ -791,16 +791,16 @@ _mesa_fprint_instruction_opt(FILE *f, default: if (inst->Opcode < MAX_OPCODE) { /* typical alu instruction */ - fprint_alu_instruction(f, inst, - _mesa_opcode_string(inst->Opcode), - _mesa_num_inst_src_regs(inst->Opcode), - mode, prog); + _mesa_fprint_alu_instruction(f, inst, + _mesa_opcode_string(inst->Opcode), + _mesa_num_inst_src_regs(inst->Opcode), + mode, prog); } else { - fprint_alu_instruction(f, inst, - _mesa_opcode_string(inst->Opcode), - 3/*_mesa_num_inst_src_regs(inst->Opcode)*/, - mode, prog); + _mesa_fprint_alu_instruction(f, inst, + _mesa_opcode_string(inst->Opcode), + 3/*_mesa_num_inst_src_regs(inst->Opcode)*/, + mode, prog); } break; } diff --git a/src/mesa/program/prog_print.h b/src/mesa/program/prog_print.h index 9ab7456016..4ffd5ab96c 100644 --- a/src/mesa/program/prog_print.h +++ b/src/mesa/program/prog_print.h @@ -55,6 +55,13 @@ _mesa_writemask_string(GLuint writeMask); extern void _mesa_print_swizzle(GLuint swizzle); +extern void +_mesa_fprint_alu_instruction(FILE *f, + const struct prog_instruction *inst, + const char *opcode_string, GLuint numRegs, + gl_prog_print_mode mode, + const struct gl_program *prog); + extern void _mesa_print_alu_instruction(const struct prog_instruction *inst, const char *opcode_string, GLuint numRegs); -- 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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 30d083903f28965122800cc6ba3dc1ad08aff47f Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 11 Aug 2010 14:00:02 -0600 Subject: glsl2: remove stray semicolon --- src/mesa/program/hash_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/program') diff --git a/src/mesa/program/hash_table.h b/src/mesa/program/hash_table.h index 228ab948ff..ec088c7dde 100644 --- a/src/mesa/program/hash_table.h +++ b/src/mesa/program/hash_table.h @@ -147,6 +147,6 @@ int hash_table_pointer_compare(const void *key1, const void *key2); #ifdef __cplusplus -}; +} #endif #endif /* HASH_TABLE_H */ -- cgit v1.2.3 From 2d83e3fa0de6e0b39307cdc67725ca88855d68d2 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 12 Aug 2010 15:57:54 -0600 Subject: mesa: check for null shader->InfoLog before printing --- src/mesa/program/prog_print.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/mesa/program') diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index 1ce1bf2f4e..95db9b0eb3 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -1032,7 +1032,9 @@ _mesa_write_shader_to_file(const struct gl_shader *shader) fprintf(f, "/* Compile status: %s */\n", shader->CompileStatus ? "ok" : "fail"); fprintf(f, "/* Log Info: */\n"); - fputs(shader->InfoLog, f); + if (shader->InfoLog) { + fputs(shader->InfoLog, f); + } if (shader->CompileStatus && shader->Program) { fprintf(f, "/* GPU code */\n"); fprintf(f, "/*\n"); -- 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') 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') 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') 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') 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') 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') 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') 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') 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