X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fprogram%2Fir_to_mesa.cpp;h=85e6e92a2d55d02a1e90a02b912823043dd615fd;hb=8ce53d4a2f3f44b8fa00a6a04ec0816f38d788db;hp=a0a42daaac5d9ac8cae844e154a19b3701cba8fd;hpb=8343583557fbbf0e04ce8e834a71f00b219232ce;p=mesa.git diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index a0a42daaac5..85e6e92a2d5 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -31,27 +31,27 @@ #include #include "main/compiler.h" +#include "main/macros.h" #include "main/mtypes.h" #include "main/shaderapi.h" #include "main/shaderobj.h" #include "main/uniforms.h" -#include "glsl/ast.h" -#include "glsl/ir.h" -#include "glsl/ir_expression_flattening.h" -#include "glsl/ir_visitor.h" -#include "glsl/ir_optimization.h" -#include "glsl/ir_uniform.h" -#include "glsl/glsl_parser_extras.h" -#include "glsl/nir/glsl_types.h" -#include "glsl/linker.h" -#include "glsl/program.h" -#include "program/hash_table.h" +#include "compiler/glsl/ast.h" +#include "compiler/glsl/ir.h" +#include "compiler/glsl/ir_expression_flattening.h" +#include "compiler/glsl/ir_visitor.h" +#include "compiler/glsl/ir_optimization.h" +#include "compiler/glsl/ir_uniform.h" +#include "compiler/glsl/glsl_parser_extras.h" +#include "compiler/glsl_types.h" +#include "compiler/glsl/linker.h" +#include "compiler/glsl/program.h" #include "program/prog_instruction.h" #include "program/prog_optimize.h" #include "program/prog_print.h" #include "program/program.h" #include "program/prog_parameter.h" -#include "program/sampler.h" +#include "util/string_to_uint_map.h" static int swizzle_for_size(int size); @@ -105,7 +105,6 @@ public: this->file = file; this->index = 0; this->writemask = writemask; - this->cond_mask = COND_TR; this->reladdr = NULL; } @@ -114,7 +113,6 @@ public: this->file = PROGRAM_UNDEFINED; this->index = 0; this->writemask = 0; - this->cond_mask = COND_TR; this->reladdr = NULL; } @@ -123,7 +121,6 @@ public: gl_register_file file; /**< PROGRAM_* from Mesa */ int index; /**< temporary index, VERT_ATTRIB_*, VARYING_SLOT_*, etc. */ int writemask; /**< Bitfield of WRITEMASK_[XYZW] */ - GLuint cond_mask:4; /** Register index should be offset by the integer in this reg. */ src_reg *reladdr; }; @@ -144,7 +141,6 @@ dst_reg::dst_reg(src_reg reg) this->file = reg.file; this->index = reg.index; this->writemask = WRITEMASK_XYZW; - this->cond_mask = COND_TR; this->reladdr = reg.reladdr; } @@ -159,7 +155,6 @@ public: src_reg src[3]; /** Pointer to the ir source this tree came from for debugging */ ir_instruction *ir; - GLboolean cond_update; bool saturate; int sampler; /**< sampler index */ int tex_target; /**< One of TEXTURE_*_INDEX */ @@ -309,6 +304,22 @@ public: void emit_swz(ir_expression *ir); + void emit_equality_comparison(ir_expression *ir, enum prog_opcode op, + dst_reg dst, + const src_reg &src0, const src_reg &src1); + + inline void emit_sne(ir_expression *ir, dst_reg dst, + const src_reg &src0, const src_reg &src1) + { + emit_equality_comparison(ir, OPCODE_SLT, dst, src0, src1); + } + + inline void emit_seq(ir_expression *ir, dst_reg dst, + const src_reg &src0, const src_reg &src1) + { + emit_equality_comparison(ir, OPCODE_SGE, dst, src0, src1); + } + bool process_move_condition(ir_rvalue *ir); void copy_propagate(void); @@ -521,6 +532,12 @@ type_size(const struct glsl_type *type) return 1; } break; + case GLSL_TYPE_UINT64: + case GLSL_TYPE_INT64: + if (type->vector_elements > 2) + return 2; + else + return 1; case GLSL_TYPE_ARRAY: assert(type->length > 0); return type_size(type->fields.array) * type->length; @@ -541,6 +558,7 @@ type_size(const struct glsl_type *type) case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: case GLSL_TYPE_INTERFACE: + case GLSL_TYPE_FUNCTION: assert(!"Invalid type in type_size"); break; } @@ -589,10 +607,8 @@ void ir_to_mesa_visitor::visit(ir_variable *ir) { if (strcmp(ir->name, "gl_FragCoord") == 0) { - struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; - - fp->OriginUpperLeft = ir->data.origin_upper_left; - fp->PixelCenterInteger = ir->data.pixel_center_integer; + this->prog->OriginUpperLeft = ir->data.origin_upper_left; + this->prog->PixelCenterInteger = ir->data.pixel_center_integer; } if (ir->data.mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { @@ -916,6 +932,46 @@ ir_to_mesa_visitor::emit_swz(ir_expression *ir) this->result = result_src; } +void +ir_to_mesa_visitor::emit_equality_comparison(ir_expression *ir, + enum prog_opcode op, + dst_reg dst, + const src_reg &src0, + const src_reg &src1) +{ + src_reg difference; + src_reg abs_difference = get_temp(glsl_type::vec4_type); + const src_reg zero = src_reg_for_float(0.0); + + /* x == y is equivalent to -abs(x-y) >= 0. Since all of the code that + * consumes the generated IR is pretty dumb, take special care when one + * of the operands is zero. + * + * Similarly, x != y is equivalent to -abs(x-y) < 0. + */ + if (src0.file == zero.file && + src0.index == zero.index && + src0.swizzle == zero.swizzle) { + difference = src1; + } else if (src1.file == zero.file && + src1.index == zero.index && + src1.swizzle == zero.swizzle) { + difference = src0; + } else { + difference = get_temp(glsl_type::vec4_type); + + src_reg tmp_src = src0; + tmp_src.negate = ~tmp_src.negate; + + emit(ir, OPCODE_ADD, dst_reg(difference), tmp_src, src1); + } + + emit(ir, OPCODE_ABS, dst_reg(abs_difference), difference); + + abs_difference.negate = ~abs_difference.negate; + emit(ir, op, dst, abs_difference, zero); +} + void ir_to_mesa_visitor::visit(ir_expression *ir) { @@ -1071,26 +1127,36 @@ ir_to_mesa_visitor::visit(ir_expression *ir) emit(ir, OPCODE_SLT, result_dst, op[0], op[1]); break; case ir_binop_greater: - emit(ir, OPCODE_SGT, result_dst, op[0], op[1]); + /* Negating the operands (as opposed to switching the order of the + * operands) produces the correct result when both are +/-Inf. + */ + op[0].negate = ~op[0].negate; + op[1].negate = ~op[1].negate; + emit(ir, OPCODE_SLT, result_dst, op[0], op[1]); break; case ir_binop_lequal: - emit(ir, OPCODE_SLE, result_dst, op[0], op[1]); + /* Negating the operands (as opposed to switching the order of the + * operands) produces the correct result when both are +/-Inf. + */ + op[0].negate = ~op[0].negate; + op[1].negate = ~op[1].negate; + emit(ir, OPCODE_SGE, result_dst, op[0], op[1]); break; case ir_binop_gequal: emit(ir, OPCODE_SGE, result_dst, op[0], op[1]); break; case ir_binop_equal: - emit(ir, OPCODE_SEQ, result_dst, op[0], op[1]); + emit_seq(ir, result_dst, op[0], op[1]); break; case ir_binop_nequal: - emit(ir, OPCODE_SNE, result_dst, op[0], op[1]); + emit_sne(ir, result_dst, op[0], op[1]); break; case ir_binop_all_equal: /* "==" operator producing a scalar boolean. */ if (ir->operands[0]->type->is_vector() || ir->operands[1]->type->is_vector()) { src_reg temp = get_temp(glsl_type::vec4_type); - emit(ir, OPCODE_SNE, dst_reg(temp), op[0], op[1]); + emit_sne(ir, dst_reg(temp), op[0], op[1]); /* After the dot-product, the value will be an integer on the * range [0,4]. Zero becomes 1.0, and positive values become zero. @@ -1105,7 +1171,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) sge_src.negate = ~sge_src.negate; emit(ir, OPCODE_SGE, result_dst, sge_src, src_reg_for_float(0.0)); } else { - emit(ir, OPCODE_SEQ, result_dst, op[0], op[1]); + emit_seq(ir, result_dst, op[0], op[1]); } break; case ir_binop_any_nequal: @@ -1113,7 +1179,13 @@ ir_to_mesa_visitor::visit(ir_expression *ir) if (ir->operands[0]->type->is_vector() || ir->operands[1]->type->is_vector()) { src_reg temp = get_temp(glsl_type::vec4_type); - emit(ir, OPCODE_SNE, dst_reg(temp), op[0], op[1]); + if (ir->operands[0]->type->is_boolean() && + ir->operands[1]->as_constant() && + ir->operands[1]->as_constant()->is_zero()) { + temp = op[0]; + } else { + emit_sne(ir, dst_reg(temp), op[0], op[1]); + } /* After the dot-product, the value will be an integer on the * range [0,4]. Zero stays zero, and positive values become 1.0. @@ -1135,59 +1207,29 @@ ir_to_mesa_visitor::visit(ir_expression *ir) emit(ir, OPCODE_SLT, result_dst, slt_src, src_reg_for_float(0.0)); } } else { - emit(ir, OPCODE_SNE, result_dst, op[0], op[1]); + emit_sne(ir, result_dst, op[0], op[1]); } break; - case ir_unop_any: { - assert(ir->operands[0]->type->is_vector()); - - /* After the dot-product, the value will be an integer on the - * range [0,4]. Zero stays zero, and positive values become 1.0. - */ - ir_to_mesa_instruction *const dp = - emit_dp(ir, result_dst, op[0], op[0], - ir->operands[0]->type->vector_elements); - if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB) { - /* The clamping to [0,1] can be done for free in the fragment - * shader with a saturate. - */ - dp->saturate = true; - } else { - /* Negating the result of the dot-product gives values on the range - * [-4, 0]. Zero stays zero, and negative values become 1.0. This - * is achieved using SLT. - */ - src_reg slt_src = result_src; - slt_src.negate = ~slt_src.negate; - emit(ir, OPCODE_SLT, result_dst, slt_src, src_reg_for_float(0.0)); - } - break; - } - case ir_binop_logic_xor: - emit(ir, OPCODE_SNE, result_dst, op[0], op[1]); + emit_sne(ir, result_dst, op[0], op[1]); break; case ir_binop_logic_or: { - /* After the addition, the value will be an integer on the - * range [0,2]. Zero stays zero, and positive values become 1.0. - */ - ir_to_mesa_instruction *add = - emit(ir, OPCODE_ADD, result_dst, op[0], op[1]); if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB) { - /* The clamping to [0,1] can be done for free in the fragment - * shader with a saturate. - */ + /* After the addition, the value will be an integer on the + * range [0,2]. Zero stays zero, and positive values become 1.0. + */ + ir_to_mesa_instruction *add = + emit(ir, OPCODE_ADD, result_dst, op[0], op[1]); add->saturate = true; } else { - /* Negating the result of the addition gives values on the range - * [-2, 0]. Zero stays zero, and negative values become 1.0. This - * is achieved using SLT. - */ - src_reg slt_src = result_src; - slt_src.negate = ~slt_src.negate; - emit(ir, OPCODE_SLT, result_dst, slt_src, src_reg_for_float(0.0)); + /* The Boolean arguments are stored as float 0.0 and 1.0. If either + * value is 1.0, the result of the logcal-or should be 1.0. If both + * values are 0.0, the result should be 0.0. This is exactly what + * MAX does. + */ + emit(ir, OPCODE_MAX, result_dst, op[0], op[1]); } break; } @@ -1231,8 +1273,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) break; case ir_unop_f2b: case ir_unop_i2b: - emit(ir, OPCODE_SNE, result_dst, - op[0], src_reg_for_float(0.0)); + emit_sne(ir, result_dst, op[0], src_reg_for_float(0.0)); break; case ir_unop_bitcast_f2i: // Ignore these 4, they can't happen here anyway case ir_unop_bitcast_f2u: @@ -1264,10 +1305,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_unpack_unorm_2x16: case ir_unop_unpack_unorm_4x8: case ir_unop_unpack_half_2x16: - case ir_unop_unpack_half_2x16_split_x: - case ir_unop_unpack_half_2x16_split_y: case ir_unop_unpack_double_2x32: - case ir_binop_pack_half_2x16_split: case ir_unop_bitfield_reverse: case ir_unop_bit_count: case ir_unop_find_msb: @@ -1323,9 +1361,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) break; case ir_binop_vector_extract: - case ir_binop_bfm: case ir_triop_fma: - case ir_triop_bfi: case ir_triop_bitfield_extract: case ir_triop_vector_insert: case ir_quadop_bitfield_insert: @@ -1343,6 +1379,9 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_dFdy_fine: case ir_unop_subroutine_to_int: case ir_unop_get_buffer_size: + case ir_unop_vote_any: + case ir_unop_vote_all: + case ir_unop_vote_eq: assert(!"not supported"); break; @@ -1414,7 +1453,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) switch (var->data.mode) { case ir_var_uniform: entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM, - var->data.location); + var->data.param_index); this->variables.push_tail(entry); break; case ir_var_shader_in: @@ -1564,6 +1603,82 @@ get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v) return dst_reg(v->result); } +/* Calculate the sampler index and also calculate the base uniform location + * for struct members. + */ +static void +calc_sampler_offsets(struct gl_shader_program *prog, ir_dereference *deref, + unsigned *offset, unsigned *array_elements, + unsigned *location) +{ + if (deref->ir_type == ir_type_dereference_variable) + return; + + switch (deref->ir_type) { + case ir_type_dereference_array: { + ir_dereference_array *deref_arr = deref->as_dereference_array(); + ir_constant *array_index = + deref_arr->array_index->constant_expression_value(); + + if (!array_index) { + /* GLSL 1.10 and 1.20 allowed variable sampler array indices, + * while GLSL 1.30 requires that the array indices be + * constant integer expressions. We don't expect any driver + * to actually work with a really variable array index, so + * all that would work would be an unrolled loop counter that ends + * up being constant above. + */ + ralloc_strcat(&prog->data->InfoLog, + "warning: Variable sampler array index unsupported.\n" + "This feature of the language was removed in GLSL 1.20 " + "and is unlikely to be supported for 1.10 in Mesa.\n"); + } else { + *offset += array_index->value.u[0] * *array_elements; + } + + *array_elements *= deref_arr->array->type->length; + + calc_sampler_offsets(prog, deref_arr->array->as_dereference(), + offset, array_elements, location); + break; + } + + case ir_type_dereference_record: { + ir_dereference_record *deref_record = deref->as_dereference_record(); + unsigned field_index = + deref_record->record->type->field_index(deref_record->field); + *location += + deref_record->record->type->record_location_offset(field_index); + calc_sampler_offsets(prog, deref_record->record->as_dereference(), + offset, array_elements, location); + break; + } + + default: + unreachable("Invalid deref type"); + break; + } +} + +static int +get_sampler_uniform_value(class ir_dereference *sampler, + struct gl_shader_program *shader_program, + const struct gl_program *prog) +{ + GLuint shader = _mesa_program_enum_to_shader_stage(prog->Target); + ir_variable *var = sampler->variable_referenced(); + unsigned location = var->data.location; + unsigned array_elements = 1; + unsigned offset = 0; + + calc_sampler_offsets(shader_program, sampler, &offset, &array_elements, + &location); + + assert(shader_program->data->UniformStorage[location].opaque[shader].active); + return shader_program->data->UniformStorage[location].opaque[shader].index + + offset; +} + /** * Process the condition of a conditional assignment * @@ -1864,7 +1979,7 @@ ir_to_mesa_visitor::visit(ir_texture *ir) ir->coordinate->accept(this); /* Put our coords in a temp. We'll need to modify them for shadow, - * projection, or LOD, so the only case we'd use it as is is if + * projection, or LOD, so the only case we'd use it as-is is if * we're doing plain old texturing. Mesa IR optimization should * handle cleaning up our mess in that case. */ @@ -1946,14 +2061,14 @@ ir_to_mesa_visitor::visit(ir_texture *ir) emit(ir, OPCODE_RCP, coord_dst, projector); /* In the case where we have to project the coordinates "by hand," - * the shadow comparitor value must also be projected. + * the shadow comparator value must also be projected. */ src_reg tmp_src = coord; - if (ir->shadow_comparitor) { + if (ir->shadow_comparator) { /* Slot the shadow value in as the second to last component of the * coord. */ - ir->shadow_comparitor->accept(this); + ir->shadow_comparator->accept(this); tmp_src = get_temp(glsl_type::vec4_type); dst_reg tmp_dst = dst_reg(tmp_src); @@ -1977,14 +2092,14 @@ ir_to_mesa_visitor::visit(ir_texture *ir) } /* If projection is done and the opcode is not OPCODE_TXP, then the shadow - * comparitor was put in the correct place (and projected) by the code, + * comparator was put in the correct place (and projected) by the code, * above, that handles by-hand projection. */ - if (ir->shadow_comparitor && (!ir->projector || opcode == OPCODE_TXP)) { + if (ir->shadow_comparator && (!ir->projector || opcode == OPCODE_TXP)) { /* Slot the shadow value in as the second to last component of the * coord. */ - ir->shadow_comparitor->accept(this); + ir->shadow_comparator->accept(this); /* XXX This will need to be updated for cubemap array samplers. */ if (sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D && @@ -2010,12 +2125,11 @@ ir_to_mesa_visitor::visit(ir_texture *ir) else inst = emit(ir, opcode, result_dst, coord); - if (ir->shadow_comparitor) + if (ir->shadow_comparator) inst->tex_shadow = GL_TRUE; - inst->sampler = _mesa_get_sampler_uniform_value(ir->sampler, - this->shader_program, - this->prog); + inst->sampler = get_sampler_uniform_value(ir->sampler, shader_program, + prog); switch (sampler_type->sampler_dimensionality) { case GLSL_SAMPLER_DIM_1D: @@ -2061,44 +2175,23 @@ ir_to_mesa_visitor::visit(ir_return *ir) void ir_to_mesa_visitor::visit(ir_discard *ir) { - if (ir->condition) { - ir->condition->accept(this); - this->result.negate = ~this->result.negate; - emit(ir, OPCODE_KIL, undef_dst, this->result); - } else { - emit(ir, OPCODE_KIL_NV); - } + if (!ir->condition) + ir->condition = new(mem_ctx) ir_constant(true); + + ir->condition->accept(this); + this->result.negate = ~this->result.negate; + emit(ir, OPCODE_KIL, undef_dst, this->result); } void ir_to_mesa_visitor::visit(ir_if *ir) { - ir_to_mesa_instruction *cond_inst, *if_inst; - ir_to_mesa_instruction *prev_inst; - - prev_inst = (ir_to_mesa_instruction *)this->instructions.get_tail(); + ir_to_mesa_instruction *if_inst; ir->condition->accept(this); assert(this->result.file != PROGRAM_UNDEFINED); - if (this->options->EmitCondCodes) { - cond_inst = (ir_to_mesa_instruction *)this->instructions.get_tail(); - - /* See if we actually generated any instruction for generating - * the condition. If not, then cook up a move to a temp so we - * have something to set cond_update on. - */ - if (cond_inst == prev_inst) { - src_reg temp = get_temp(glsl_type::bool_type); - cond_inst = emit(ir->condition, OPCODE_MOV, dst_reg(temp), result); - } - cond_inst->cond_update = GL_TRUE; - - if_inst = emit(ir->condition, OPCODE_IF); - if_inst->dst.cond_mask = COND_NE; - } else { - if_inst = emit(ir->condition, OPCODE_IF, undef_dst, this->result); - } + if_inst = emit(ir->condition, OPCODE_IF, undef_dst, this->result); this->instructions.push_tail(if_inst); @@ -2155,10 +2248,6 @@ mesa_src_reg_from_ir_src_reg(src_reg reg) mesa_reg.Swizzle = reg.swizzle; mesa_reg.RelAddr = reg.reladdr != NULL; mesa_reg.Negate = reg.negate; - mesa_reg.Abs = 0; - mesa_reg.HasIndex2 = GL_FALSE; - mesa_reg.RelAddr2 = 0; - mesa_reg.Index2 = 0; return mesa_reg; } @@ -2293,13 +2382,14 @@ public: { this->idx = -1; this->program_resource_visitor::process(var); - - var->data.location = this->idx; + var->data.param_index = this->idx; } private: virtual void visit_field(const glsl_type *type, const char *name, - bool row_major); + bool row_major, const glsl_type *record_type, + const enum glsl_interface_packing packing, + bool last_field); struct gl_shader_program *shader_program; struct gl_program_parameter_list *params; @@ -2311,15 +2401,20 @@ private: void add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, - bool row_major) + bool /* row_major */, + const glsl_type * /* record_type */, + const enum glsl_interface_packing, + bool /* last_field */) { unsigned int size; - (void) row_major; + /* atomics don't get real storage */ + if (type->contains_atomic()) + return; if (type->is_vector() || type->is_scalar()) { size = type->vector_elements; - if (type->is_double()) + if (type->is_64bit()) size *= 2; } else { size = type_size(type) * 4; @@ -2332,7 +2427,7 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, file = PROGRAM_UNIFORM; } - int index = _mesa_lookup_parameter_index(params, -1, name); + int index = _mesa_lookup_parameter_index(params, name); if (index < 0) { index = _mesa_add_parameter(params, file, name, size, type->gl_type, NULL, NULL); @@ -2352,7 +2447,7 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, return; struct gl_uniform_storage *storage = - &this->shader_program->UniformStorage[location]; + &this->shader_program->data->UniformStorage[location]; assert(storage->type->is_sampler() && storage->opaque[shader_type].active); @@ -2381,7 +2476,7 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, void _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program *shader_program, - struct gl_shader *sh, + struct gl_linked_shader *sh, struct gl_program_parameter_list *params) { @@ -2421,7 +2516,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, continue; struct gl_uniform_storage *storage = - &shader_program->UniformStorage[location]; + &shader_program->data->UniformStorage[location]; /* Do not associate any uniform storage to built-in uniforms */ if (storage->builtin) @@ -2433,11 +2528,19 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, unsigned columns = 0; int dmul = 4 * sizeof(float); switch (storage->type->base_type) { + case GLSL_TYPE_UINT64: + if (storage->type->vector_elements > 2) + dmul *= 2; + /* fallthrough */ case GLSL_TYPE_UINT: assert(ctx->Const.NativeIntegers); format = uniform_native; columns = 1; break; + case GLSL_TYPE_INT64: + if (storage->type->vector_elements > 2) + dmul *= 2; + /* fallthrough */ case GLSL_TYPE_INT: format = (ctx->Const.NativeIntegers) ? uniform_native : uniform_int_float; @@ -2468,6 +2571,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, case GLSL_TYPE_STRUCT: case GLSL_TYPE_ERROR: case GLSL_TYPE_INTERFACE: + case GLSL_TYPE_FUNCTION: assert(!"Should not get here."); break; } @@ -2690,7 +2794,7 @@ ir_to_mesa_visitor::copy_propagate(void) static struct gl_program * get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program, - struct gl_shader *shader) + struct gl_linked_shader *shader) { ir_to_mesa_visitor v; struct prog_instruction *mesa_instructions, *mesa_inst; @@ -2704,9 +2808,7 @@ get_mesa_program(struct gl_context *ctx, validate_ir_tree(shader->ir); - prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name); - if (!prog) - return NULL; + prog = shader->Program; prog->Parameters = _mesa_new_parameter_list(); v.ctx = ctx; v.prog = prog; @@ -2720,13 +2822,12 @@ get_mesa_program(struct gl_context *ctx, visit_exec_list(shader->ir, &v); v.emit(NULL, OPCODE_END); - prog->NumTemporaries = v.next_temp; + prog->arb.NumTemporaries = v.next_temp; unsigned num_instructions = v.instructions.length(); - mesa_instructions = - (struct prog_instruction *)calloc(num_instructions, - sizeof(*mesa_instructions)); + mesa_instructions = rzalloc_array(prog, struct prog_instruction, + num_instructions); mesa_instruction_annotation = ralloc_array(v.mem_ctx, ir_instruction *, num_instructions); @@ -2738,12 +2839,10 @@ get_mesa_program(struct gl_context *ctx, i = 0; foreach_in_list(const ir_to_mesa_instruction, inst, &v.instructions) { mesa_inst->Opcode = inst->op; - mesa_inst->CondUpdate = inst->cond_update; if (inst->saturate) mesa_inst->Saturate = GL_TRUE; mesa_inst->DstReg.File = inst->dst.file; mesa_inst->DstReg.Index = inst->dst.index; - mesa_inst->DstReg.CondMask = inst->dst.cond_mask; mesa_inst->DstReg.WriteMask = inst->dst.writemask; mesa_inst->DstReg.RelAddr = inst->dst.reladdr != NULL; mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src[0]); @@ -2756,12 +2855,12 @@ get_mesa_program(struct gl_context *ctx, /* Set IndirectRegisterFiles. */ if (mesa_inst->DstReg.RelAddr) - prog->IndirectRegisterFiles |= 1 << mesa_inst->DstReg.File; + prog->arb.IndirectRegisterFiles |= 1 << mesa_inst->DstReg.File; /* Update program's bitmask of indirectly accessed register files */ for (unsigned src = 0; src < 3; src++) if (mesa_inst->SrcReg[src].RelAddr) - prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File; + prog->arb.IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File; switch (mesa_inst->Opcode) { case OPCODE_IF: @@ -2789,7 +2888,7 @@ get_mesa_program(struct gl_context *ctx, } break; case OPCODE_ARL: - prog->NumAddressRegs = 1; + prog->arb.NumAddressRegs = 1; break; default: break; @@ -2798,11 +2897,11 @@ get_mesa_program(struct gl_context *ctx, mesa_inst++; i++; - if (!shader_program->LinkStatus) + if (!shader_program->data->LinkStatus) break; } - if (!shader_program->LinkStatus) { + if (!shader_program->data->LinkStatus) { goto fail_exit; } @@ -2822,8 +2921,8 @@ get_mesa_program(struct gl_context *ctx, fflush(stderr); } - prog->Instructions = mesa_instructions; - prog->NumInstructions = num_instructions; + prog->arb.Instructions = mesa_instructions; + prog->arb.NumInstructions = num_instructions; /* Setting this to NULL prevents a possible double free in the fail_exit * path (far below). @@ -2832,20 +2931,17 @@ get_mesa_program(struct gl_context *ctx, do_set_program_inouts(shader->ir, prog, shader->Stage); - prog->SamplersUsed = shader->active_samplers; prog->ShadowSamplers = shader->shadow_samplers; + prog->ExternalSamplersUsed = gl_external_samplers(prog); _mesa_update_shader_textures_used(shader_program, prog); /* Set the gl_FragDepth layout. */ if (target == GL_FRAGMENT_PROGRAM_ARB) { - struct gl_fragment_program *fp = (struct gl_fragment_program *)prog; - fp->FragDepthLayout = shader_program->FragDepthLayout; + prog->info.fs.depth_layout = shader_program->FragDepthLayout; } - _mesa_reference_program(ctx, &shader->Program, prog); - if ((ctx->_Shader->Flags & GLSL_NO_OPT) == 0) { - _mesa_optimize_program(ctx, prog); + _mesa_optimize_program(ctx, prog, prog); } /* This has to be done last. Any operation that can cause @@ -2853,14 +2949,14 @@ get_mesa_program(struct gl_context *ctx, * program constant) has to happen before creating this linkage. */ _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters); - if (!shader_program->LinkStatus) { + if (!shader_program->data->LinkStatus) { goto fail_exit; } return prog; fail_exit: - free(mesa_instructions); + ralloc_free(mesa_instructions); _mesa_reference_program(ctx, &shader->Program, NULL); return NULL; } @@ -2876,7 +2972,7 @@ extern "C" { GLboolean _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) { - assert(prog->LinkStatus); + assert(prog->data->LinkStatus); for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { if (prog->_LinkedShaders[i] == NULL) @@ -2896,8 +2992,6 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) | LOG_TO_LOG2 | INT_DIV_TO_MUL_RCP | ((options->EmitNoPow) ? POW_TO_EXP2 : 0))); - progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; - progress = do_common_optimization(ir, true, true, options, ctx->Const.NativeIntegers) || progress; @@ -2907,10 +3001,10 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) if (options->MaxIfDepth == 0) progress = lower_discard(ir) || progress; - progress = lower_if_to_cond_assign(ir, options->MaxIfDepth) || progress; + progress = lower_if_to_cond_assign((gl_shader_stage)i, ir, + options->MaxIfDepth) || progress; - if (options->EmitNoNoise) - progress = lower_noise(ir) || progress; + progress = lower_noise(ir) || progress; /* If there are forms of indirect addressing that the driver * cannot handle, perform the lowering pass. @@ -2941,21 +3035,20 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); if (linked_prog) { - _mesa_copy_linked_program_data((gl_shader_stage) i, prog, linked_prog); + _mesa_copy_linked_program_data(prog, prog->_LinkedShaders[i]); - _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, - linked_prog); if (!ctx->Driver.ProgramStringNotify(ctx, _mesa_shader_stage_to_program(i), linked_prog)) { + _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, + NULL); return GL_FALSE; } } - - _mesa_reference_program(ctx, &linked_prog, NULL); } - return prog->LinkStatus; + build_program_resource_list(ctx, prog); + return prog->data->LinkStatus; } /** @@ -2966,9 +3059,9 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) { unsigned int i; - _mesa_clear_shader_program_data(prog); + _mesa_clear_shader_program_data(ctx, prog); - prog->LinkStatus = GL_TRUE; + prog->data->LinkStatus = GL_TRUE; for (i = 0; i < prog->NumShaders; i++) { if (!prog->Shaders[i]->CompileStatus) { @@ -2976,26 +3069,24 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) } } - if (prog->LinkStatus) { + if (prog->data->LinkStatus) { link_shaders(ctx, prog); } - if (prog->LinkStatus) { + if (prog->data->LinkStatus) { if (!ctx->Driver.LinkShader(ctx, prog)) { - prog->LinkStatus = GL_FALSE; - } else { - build_program_resource_list(prog); + prog->data->LinkStatus = GL_FALSE; } } if (ctx->_Shader->Flags & GLSL_DUMP) { - if (!prog->LinkStatus) { + if (!prog->data->LinkStatus) { fprintf(stderr, "GLSL shader program %d failed to link\n", prog->Name); } - if (prog->InfoLog && prog->InfoLog[0] != 0) { + if (prog->data->InfoLog && prog->data->InfoLog[0] != 0) { fprintf(stderr, "GLSL shader program %d info log:\n", prog->Name); - fprintf(stderr, "%s\n", prog->InfoLog); + fprintf(stderr, "%s\n", prog->data->InfoLog); } } }