X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fprogram%2Fir_to_mesa.cpp;h=c833a12f2aab1608d8b1c7c02d5a9882973231a7;hb=135b7e72601ab0c3923cafedcd30bb505e54f624;hp=1bdfa2e10b74d88f5f6a4eacbde0f70de5bd36d4;hpb=d7a7e4fc99888da424f324d1fc7e066673e804c2;p=mesa.git diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 1bdfa2e10b7..c833a12f2aa 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -33,8 +33,8 @@ #include "main/compiler.h" #include "ir.h" #include "ir_visitor.h" -#include "ir_print_visitor.h" #include "ir_expression_flattening.h" +#include "ir_uniform.h" #include "glsl_types.h" #include "glsl_parser_extras.h" #include "../glsl/program.h" @@ -44,25 +44,26 @@ #include "main/mtypes.h" #include "main/shaderobj.h" +#include "main/uniforms.h" #include "program/hash_table.h" extern "C" { #include "main/shaderapi.h" -#include "main/uniforms.h" #include "program/prog_instruction.h" #include "program/prog_optimize.h" #include "program/prog_print.h" #include "program/program.h" -#include "program/prog_uniform.h" #include "program/prog_parameter.h" #include "program/sampler.h" } +static int swizzle_for_size(int size); + +namespace { + class src_reg; class dst_reg; -static int swizzle_for_size(int size); - /** * This struct is a corresponding struct to Mesa prog_src_register, with * wider fields. @@ -93,7 +94,7 @@ public: explicit src_reg(dst_reg reg); gl_register_file file; /**< PROGRAM_* from Mesa */ - int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */ + int index; /**< temporary index, VERT_ATTRIB_*, VARYING_SLOT_*, etc. */ GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */ int negate; /**< NEGATE_XYZW mask from mesa */ /** Register index should be offset by the integer in this reg. */ @@ -123,13 +124,15 @@ public: explicit dst_reg(src_reg reg); gl_register_file file; /**< PROGRAM_* from Mesa */ - int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */ + 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; }; +} /* anonymous namespace */ + src_reg::src_reg(dst_reg reg) { this->file = reg.file; @@ -148,19 +151,11 @@ dst_reg::dst_reg(src_reg reg) this->reladdr = reg.reladdr; } +namespace { + class ir_to_mesa_instruction : public exec_node { public: - /* Callers of this ralloc-based new need not call delete. It's - * easier to just ralloc_free 'ctx' (or any of its ancestors). */ - static void* operator new(size_t size, void *ctx) - { - void *node; - - node = rzalloc_size(ctx, size); - assert(node != NULL); - - return node; - } + DECLARE_RALLOC_CXX_OPERATORS(ir_to_mesa_instruction) enum prog_opcode op; dst_reg dst; @@ -172,8 +167,6 @@ public: int sampler; /**< sampler index */ int tex_target; /**< One of TEXTURE_*_INDEX */ GLboolean tex_shadow; - - class function_entry *function; /* Set on OPCODE_CAL or OPCODE_BGNSUB */ }; class variable_storage : public exec_node { @@ -238,8 +231,6 @@ public: variable_storage *find_variable_storage(ir_variable *var); - function_entry *get_function_signature(ir_function_signature *sig); - src_reg get_temp(const glsl_type *type); void reladdr_to_temp(ir_instruction *ir, src_reg *reg, int *num_reladdr); @@ -270,6 +261,8 @@ public: virtual void visit(ir_discard *); virtual void visit(ir_texture *); virtual void visit(ir_if *); + virtual void visit(ir_emit_vertex *); + virtual void visit(ir_end_primitive *); /*@}*/ src_reg result; @@ -329,16 +322,18 @@ public: void *mem_ctx; }; -src_reg undef_src = src_reg(PROGRAM_UNDEFINED, 0, NULL); +} /* anonymous namespace */ + +static src_reg undef_src = src_reg(PROGRAM_UNDEFINED, 0, NULL); -dst_reg undef_dst = dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP); +static dst_reg undef_dst = dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP); -dst_reg address_reg = dst_reg(PROGRAM_ADDRESS, WRITEMASK_X); +static dst_reg address_reg = dst_reg(PROGRAM_ADDRESS, WRITEMASK_X); static int swizzle_for_size(int size) { - int size_swizzles[4] = { + static const int size_swizzles[4] = { MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X), MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y), MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z), @@ -383,8 +378,6 @@ ir_to_mesa_visitor::emit(ir_instruction *ir, enum prog_opcode op, inst->src[2] = src2; inst->ir = ir; - inst->function = NULL; - this->instructions.push_tail(inst); return inst; @@ -629,10 +622,15 @@ type_size(const struct glsl_type *type) * at link time. */ return 1; - default: - assert(0); - return 0; + case GLSL_TYPE_ATOMIC_UINT: + case GLSL_TYPE_VOID: + case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: + assert(!"Invalid type in type_size"); + break; } + + return 0; } /** @@ -685,29 +683,6 @@ ir_to_mesa_visitor::visit(ir_variable *ir) fp->OriginUpperLeft = ir->origin_upper_left; fp->PixelCenterInteger = ir->pixel_center_integer; - - } else if (strcmp(ir->name, "gl_FragDepth") == 0) { - struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; - switch (ir->depth_layout) { - case ir_depth_layout_none: - fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE; - break; - case ir_depth_layout_any: - fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_ANY; - break; - case ir_depth_layout_greater: - fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_GREATER; - break; - case ir_depth_layout_less: - fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_LESS; - break; - case ir_depth_layout_unchanged: - fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_UNCHANGED; - break; - default: - assert(0); - break; - } } if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { @@ -861,7 +836,7 @@ ir_to_mesa_visitor::visit(ir_function *ir) const ir_function_signature *sig; exec_list empty; - sig = ir->matching_signature(&empty); + sig = ir->matching_signature(NULL, &empty); assert(sig); @@ -1082,9 +1057,9 @@ ir_to_mesa_visitor::emit_swz(ir_expression *ir) this->result.file = PROGRAM_UNDEFINED; deref->accept(this); if (this->result.file == PROGRAM_UNDEFINED) { - ir_print_visitor v; printf("Failed to get tree for expression operand:\n"); - deref->accept(&v); + deref->print(); + printf("\n"); exit(1); } @@ -1154,9 +1129,9 @@ ir_to_mesa_visitor::visit(ir_expression *ir) this->result.file = PROGRAM_UNDEFINED; ir->operands[operand]->accept(this); if (this->result.file == PROGRAM_UNDEFINED) { - ir_print_visitor v; printf("Failed to get tree for expression operand:\n"); - ir->operands[operand]->accept(&v); + ir->operands[operand]->print(); + printf("\n"); exit(1); } op[operand] = this->result; @@ -1429,6 +1404,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) result_src = op[0]; break; case ir_unop_f2i: + case ir_unop_f2u: emit(ir, OPCODE_TRUNC, result_dst, op[0]); break; case ir_unop_f2b: @@ -1436,6 +1412,11 @@ ir_to_mesa_visitor::visit(ir_expression *ir) emit(ir, OPCODE_SNE, 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: + case ir_unop_bitcast_i2f: + case ir_unop_bitcast_u2f: + break; case ir_unop_trunc: emit(ir, OPCODE_TRUNC, result_dst, op[0]); break; @@ -1450,7 +1431,25 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_fract: emit(ir, OPCODE_FRC, result_dst, op[0]); break; - + case ir_unop_pack_snorm_2x16: + case ir_unop_pack_snorm_4x8: + case ir_unop_pack_unorm_2x16: + case ir_unop_pack_unorm_4x8: + case ir_unop_pack_half_2x16: + case ir_unop_unpack_snorm_2x16: + case ir_unop_unpack_snorm_4x8: + 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_binop_pack_half_2x16_split: + case ir_unop_bitfield_reverse: + case ir_unop_bit_count: + case ir_unop_find_msb: + case ir_unop_find_lsb: + assert(!"not supported"); + break; case ir_binop_min: emit(ir, OPCODE_MIN, result_dst, op[0], op[1]); break; @@ -1479,6 +1478,32 @@ ir_to_mesa_visitor::visit(ir_expression *ir) emit(ir, OPCODE_MOV, result_dst, op[0]); break; + case ir_binop_ubo_load: + assert(!"not supported"); + break; + + case ir_triop_lrp: + /* ir_triop_lrp operands are (x, y, a) while + * OPCODE_LRP operands are (a, y, x) to match ARB_fragment_program. + */ + emit(ir, OPCODE_LRP, result_dst, op[2], op[1], op[0]); + 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: + case ir_binop_ldexp: + case ir_triop_csel: + case ir_binop_carry: + case ir_binop_borrow: + case ir_binop_imul_high: + assert(!"not supported"); + break; + case ir_quadop_vector: /* This operation should have already been handled. */ @@ -1548,21 +1573,18 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) var->location); this->variables.push_tail(entry); break; - case ir_var_in: - case ir_var_inout: + case ir_var_shader_in: /* The linker assigns locations for varyings and attributes, * including deprecated builtins (like gl_Color), * user-assigned generic attributes (glBindVertexLocation), * and user-defined varyings. - * - * FINISHME: We would hit this path for function arguments. Fix! */ assert(var->location != -1); entry = new(mem_ctx) variable_storage(var, PROGRAM_INPUT, var->location); break; - case ir_var_out: + case ir_var_shader_out: assert(var->location != -1); entry = new(mem_ctx) variable_storage(var, PROGRAM_OUTPUT, @@ -1979,126 +2001,10 @@ ir_to_mesa_visitor::visit(ir_constant *ir) &this->result.swizzle); } -function_entry * -ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig) -{ - function_entry *entry; - - foreach_iter(exec_list_iterator, iter, this->function_signatures) { - entry = (function_entry *)iter.get(); - - if (entry->sig == sig) - return entry; - } - - entry = ralloc(mem_ctx, function_entry); - entry->sig = sig; - entry->sig_id = this->next_signature_id++; - entry->bgn_inst = NULL; - - /* Allocate storage for all the parameters. */ - foreach_iter(exec_list_iterator, iter, sig->parameters) { - ir_variable *param = (ir_variable *)iter.get(); - variable_storage *storage; - - storage = find_variable_storage(param); - assert(!storage); - - storage = new(mem_ctx) variable_storage(param, PROGRAM_TEMPORARY, - this->next_temp); - this->variables.push_tail(storage); - - this->next_temp += type_size(param->type); - } - - if (!sig->return_type->is_void()) { - entry->return_reg = get_temp(sig->return_type); - } else { - entry->return_reg = undef_src; - } - - this->function_signatures.push_tail(entry); - return entry; -} - void ir_to_mesa_visitor::visit(ir_call *ir) { - ir_to_mesa_instruction *call_inst; - ir_function_signature *sig = ir->get_callee(); - function_entry *entry = get_function_signature(sig); - int i; - - /* Process in parameters. */ - exec_list_iterator sig_iter = sig->parameters.iterator(); - foreach_iter(exec_list_iterator, iter, *ir) { - ir_rvalue *param_rval = (ir_rvalue *)iter.get(); - ir_variable *param = (ir_variable *)sig_iter.get(); - - if (param->mode == ir_var_in || - param->mode == ir_var_inout) { - variable_storage *storage = find_variable_storage(param); - assert(storage); - - param_rval->accept(this); - src_reg r = this->result; - - dst_reg l; - l.file = storage->file; - l.index = storage->index; - l.reladdr = NULL; - l.writemask = WRITEMASK_XYZW; - l.cond_mask = COND_TR; - - for (i = 0; i < type_size(param->type); i++) { - emit(ir, OPCODE_MOV, l, r); - l.index++; - r.index++; - } - } - - sig_iter.next(); - } - assert(!sig_iter.has_next()); - - /* Emit call instruction */ - call_inst = emit(ir, OPCODE_CAL); - call_inst->function = entry; - - /* Process out parameters. */ - sig_iter = sig->parameters.iterator(); - foreach_iter(exec_list_iterator, iter, *ir) { - ir_rvalue *param_rval = (ir_rvalue *)iter.get(); - ir_variable *param = (ir_variable *)sig_iter.get(); - - if (param->mode == ir_var_out || - param->mode == ir_var_inout) { - variable_storage *storage = find_variable_storage(param); - assert(storage); - - src_reg r; - r.file = storage->file; - r.index = storage->index; - r.reladdr = NULL; - r.swizzle = SWIZZLE_NOOP; - r.negate = 0; - - param_rval->accept(this); - dst_reg l = dst_reg(this->result); - - for (i = 0; i < type_size(param->type); i++) { - emit(ir, OPCODE_MOV, l, r); - l.index++; - r.index++; - } - } - - sig_iter.next(); - } - assert(!sig_iter.has_next()); - - /* Process return value. */ - this->result = entry->return_reg; + assert(!"ir_to_mesa: All function calls should have been inlined by now."); } void @@ -2158,6 +2064,18 @@ ir_to_mesa_visitor::visit(ir_texture *ir) ir->lod_info.grad.dPdy->accept(this); dy = this->result; break; + case ir_txf_ms: + assert(!"Unexpected ir_txf_ms opcode"); + break; + case ir_lod: + assert(!"Unexpected ir_lod opcode"); + break; + case ir_tg4: + assert(!"Unexpected ir_tg4 opcode"); + break; + case ir_query_levels: + assert(!"Unexpected ir_query_levels opcode"); + break; } const glsl_type *sampler_type = ir->sampler->type; @@ -2286,32 +2204,16 @@ ir_to_mesa_visitor::visit(ir_texture *ir) void ir_to_mesa_visitor::visit(ir_return *ir) { - if (ir->get_value()) { - dst_reg l; - int i; - - assert(current_function); - - ir->get_value()->accept(this); - src_reg r = this->result; - - l = dst_reg(current_function->return_reg); - - for (i = 0; i < type_size(current_function->sig->return_type); i++) { - emit(ir, OPCODE_MOV, l, r); - l.index++; - r.index++; - } - } - + /* Non-void functions should have been inlined. We may still emit RETs + * from main() unless the EmitNoMainReturn option is set. + */ + assert(!ir->get_value()); emit(ir, OPCODE_RET); } void ir_to_mesa_visitor::visit(ir_discard *ir) { - struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; - if (ir->condition) { ir->condition->accept(this); this->result.negate = ~this->result.negate; @@ -2319,8 +2221,6 @@ ir_to_mesa_visitor::visit(ir_discard *ir) } else { emit(ir, OPCODE_KIL_NV); } - - fp->UsesKill = GL_TRUE; } void @@ -2362,7 +2262,19 @@ ir_to_mesa_visitor::visit(ir_if *ir) visit_exec_list(&ir->else_instructions, this); } - if_inst = emit(ir->condition, OPCODE_ENDIF); + emit(ir->condition, OPCODE_ENDIF); +} + +void +ir_to_mesa_visitor::visit(ir_emit_vertex *ir) +{ + assert(!"Geometry shaders not supported."); +} + +void +ir_to_mesa_visitor::visit(ir_end_primitive *ir) +{ + assert(!"Geometry shaders not supported."); } ir_to_mesa_visitor::ir_to_mesa_visitor() @@ -2513,117 +2425,47 @@ print_program(struct prog_instruction *mesa_instructions, } } +namespace { -/** - * Count resources used by the given gpu program (number of texture - * samplers, etc). - */ -static void -count_resources(struct gl_program *prog) -{ - unsigned int i; - - prog->SamplersUsed = 0; - - for (i = 0; i < prog->NumInstructions; i++) { - struct prog_instruction *inst = &prog->Instructions[i]; - - if (_mesa_is_tex_instruction(inst->Opcode)) { - prog->SamplerTargets[inst->TexSrcUnit] = - (gl_texture_index)inst->TexSrcTarget; - prog->SamplersUsed |= 1 << inst->TexSrcUnit; - if (inst->TexShadow) { - prog->ShadowSamplers |= 1 << inst->TexSrcUnit; - } - } - } - - _mesa_update_shader_textures_used(prog); -} - - -/** - * Check if the given vertex/fragment/shader program is within the - * resource limits of the context (number of texture units, etc). - * If any of those checks fail, record a linker error. - * - * XXX more checks are needed... - */ -static bool -check_resources(const struct gl_context *ctx, - struct gl_shader_program *shader_program, - struct gl_program *prog) -{ - switch (prog->Target) { - case GL_VERTEX_PROGRAM_ARB: - if (_mesa_bitcount(prog->SamplersUsed) > - ctx->Const.MaxVertexTextureImageUnits) { - linker_error(shader_program, - "Too many vertex shader texture samplers"); - } - if (prog->Parameters->NumParameters > MAX_UNIFORMS) { - linker_error(shader_program, "Too many vertex shader constants"); - } - break; - case MESA_GEOMETRY_PROGRAM: - if (_mesa_bitcount(prog->SamplersUsed) > - ctx->Const.MaxGeometryTextureImageUnits) { - linker_error(shader_program, - "Too many geometry shader texture samplers"); - } - if (prog->Parameters->NumParameters > - MAX_GEOMETRY_UNIFORM_COMPONENTS / 4) { - linker_error(shader_program, "Too many geometry shader constants"); - } - break; - case GL_FRAGMENT_PROGRAM_ARB: - if (_mesa_bitcount(prog->SamplersUsed) > - ctx->Const.MaxTextureImageUnits) { - linker_error(shader_program, - "Too many fragment shader texture samplers"); - } - if (prog->Parameters->NumParameters > MAX_UNIFORMS) { - linker_error(shader_program, "Too many fragment shader constants"); - } - break; - default: - _mesa_problem(ctx, "unexpected program type in check_resources()"); - } - - return shader_program->LinkStatus; -} - -class add_uniform_to_shader : public uniform_field_visitor { +class add_uniform_to_shader : public program_resource_visitor { public: add_uniform_to_shader(struct gl_shader_program *shader_program, - struct gl_program_parameter_list *params) - : shader_program(shader_program), params(params), next_sampler(0) + struct gl_program_parameter_list *params, + gl_shader_type shader_type) + : shader_program(shader_program), params(params), idx(-1), + shader_type(shader_type) { /* empty */ } - int process(ir_variable *var) + void process(ir_variable *var) { this->idx = -1; - this->uniform_field_visitor::process(var); + this->program_resource_visitor::process(var); - return this->idx; + var->location = this->idx; } private: - virtual void visit_field(const glsl_type *type, const char *name); + virtual void visit_field(const glsl_type *type, const char *name, + bool row_major); struct gl_shader_program *shader_program; struct gl_program_parameter_list *params; - int next_sampler; int idx; + gl_shader_type shader_type; }; +} /* anonymous namespace */ + void -add_uniform_to_shader::visit_field(const glsl_type *type, const char *name) +add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, + bool row_major) { unsigned int size; + (void) row_major; + if (type->is_vector() || type->is_scalar()) { size = type->vector_elements; } else { @@ -2641,15 +2483,30 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name) int index = _mesa_lookup_parameter_index(params, -1, name); if (index < 0) { index = _mesa_add_parameter(params, file, name, size, type->gl_type, - NULL, NULL, 0x0); + NULL, NULL); /* Sampler uniform values are stored in prog->SamplerUnits, * and the entry in that array is selected by this index we * store in ParameterValues[]. */ if (file == PROGRAM_SAMPLER) { + unsigned location; + const bool found = + this->shader_program->UniformHash->get(location, + params->Parameters[index].Name); + assert(found); + + if (!found) + return; + + struct gl_uniform_storage *storage = + &this->shader_program->UniformStorage[location]; + + assert(storage->sampler[shader_type].active); + for (unsigned int j = 0; j < size / 4; j++) - params->ParameterValues[index + j][0].f = this->next_sampler++; + params->ParameterValues[index + j][0].f = + storage->sampler[shader_type].index + j; } } @@ -2675,26 +2532,17 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program struct gl_program_parameter_list *params) { - add_uniform_to_shader add(shader_program, params); + add_uniform_to_shader add(shader_program, params, + _mesa_shader_type_to_index(sh->Type)); foreach_list(node, sh->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); if ((var == NULL) || (var->mode != ir_var_uniform) - || (strncmp(var->name, "gl_", 3) == 0)) + || var->is_in_uniform_block() || (strncmp(var->name, "gl_", 3) == 0)) continue; - int loc = add.process(var); - - /* The location chosen in the Parameters list here (returned from - * _mesa_add_parameter) has to match what the linker chose. - */ - if (var->location != loc) { - linker_error(shader_program, - "Allocation of uniform `%s' to target failed " - "(%d vs %d)\n", - var->name, loc, var->location); - } + add.process(var); } } @@ -2754,7 +2602,12 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, format = uniform_native; columns = 1; break; - default: + case GLSL_TYPE_ATOMIC_UINT: + case GLSL_TYPE_ARRAY: + case GLSL_TYPE_VOID: + case GLSL_TYPE_STRUCT: + case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: assert(!"Should not get here."); break; } @@ -2764,109 +2617,18 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, 4 * sizeof(float), format, ¶ms->ParameterValues[i]); - last_location = location; - } - } -} - -static void -set_uniform_initializer(struct gl_context *ctx, void *mem_ctx, - struct gl_shader_program *shader_program, - const char *name, const glsl_type *type, - ir_constant *val) -{ - if (type->is_record()) { - ir_constant *field_constant; - - field_constant = (ir_constant *)val->components.get_head(); - - for (unsigned int i = 0; i < type->length; i++) { - const glsl_type *field_type = type->fields.structure[i].type; - const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name, - type->fields.structure[i].name); - set_uniform_initializer(ctx, mem_ctx, shader_program, field_name, - field_type, field_constant); - field_constant = (ir_constant *)field_constant->next; - } - return; - } - - int loc = _mesa_get_uniform_location(ctx, shader_program, name); - - if (loc == -1) { - linker_error(shader_program, - "Couldn't find uniform for initializer %s\n", name); - return; - } - - for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) { - ir_constant *element; - const glsl_type *element_type; - if (type->is_array()) { - element = val->array_elements[i]; - element_type = type->fields.array; - } else { - element = val; - element_type = type; - } - void *values; - - if (element_type->base_type == GLSL_TYPE_BOOL) { - int *conv = ralloc_array(mem_ctx, int, element_type->components()); - for (unsigned int j = 0; j < element_type->components(); j++) { - conv[j] = element->value.b[j]; - } - values = (void *)conv; - element_type = glsl_type::get_instance(GLSL_TYPE_INT, - element_type->vector_elements, - 1); - } else { - values = &element->value; - } - - if (element_type->is_matrix()) { - _mesa_uniform_matrix(ctx, shader_program, - element_type->matrix_columns, - element_type->vector_elements, - loc, 1, GL_FALSE, (GLfloat *)values); - loc += element_type->matrix_columns; - } else { - _mesa_uniform(ctx, shader_program, loc, element_type->matrix_columns, - values, element_type->gl_type); - loc += type_size(element_type); - } - } -} - -static void -set_uniform_initializers(struct gl_context *ctx, - struct gl_shader_program *shader_program) -{ - void *mem_ctx = NULL; - - for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) { - struct gl_shader *shader = shader_program->_LinkedShaders[i]; - - if (shader == NULL) - continue; - - foreach_iter(exec_list_iterator, iter, *shader->ir) { - ir_instruction *ir = (ir_instruction *)iter.get(); - ir_variable *var = ir->as_variable(); - - if (!var || var->mode != ir_var_uniform || !var->constant_value) - continue; - - if (!mem_ctx) - mem_ctx = ralloc_context(NULL); + /* After attaching the driver's storage to the uniform, propagate any + * data from the linker's backing store. This will cause values from + * initializers in the source code to be copied over. + */ + _mesa_propagate_uniforms_to_driver_storage(storage, + 0, + MAX2(1, storage->array_elements)); - set_uniform_initializer(ctx, mem_ctx, shader_program, var->name, - var->type, var->constant_value); + last_location = location; } } - - ralloc_free(mem_ctx); } /* @@ -3044,6 +2806,8 @@ ir_to_mesa_visitor::copy_propagate(void) /* If this is a copy, add it to the ACP. */ if (inst->op == OPCODE_MOV && inst->dst.file == PROGRAM_TEMPORARY && + !(inst->dst.file == inst->src[0].file && + inst->dst.index == inst->src[0].index) && !inst->dst.reladdr && !inst->saturate && !inst->src[0].reladdr && @@ -3076,23 +2840,19 @@ get_mesa_program(struct gl_context *ctx, int i; struct gl_program *prog; GLenum target; - const char *target_string; - GLboolean progress; + const char *target_string = _mesa_glsl_shader_target_name(shader->Type); struct gl_shader_compiler_options *options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(shader->Type)]; switch (shader->Type) { case GL_VERTEX_SHADER: target = GL_VERTEX_PROGRAM_ARB; - target_string = "vertex"; break; case GL_FRAGMENT_SHADER: target = GL_FRAGMENT_PROGRAM_ARB; - target_string = "fragment"; break; case GL_GEOMETRY_SHADER: target = GL_GEOMETRY_PROGRAM_NV; - target_string = "geometry"; break; default: assert(!"should not be reached"); @@ -3117,35 +2877,6 @@ get_mesa_program(struct gl_context *ctx, visit_exec_list(shader->ir, &v); v.emit(NULL, OPCODE_END); - /* Now emit bodies for any functions that were used. */ - do { - progress = GL_FALSE; - - foreach_iter(exec_list_iterator, iter, v.function_signatures) { - function_entry *entry = (function_entry *)iter.get(); - - if (!entry->bgn_inst) { - v.current_function = entry; - - entry->bgn_inst = v.emit(NULL, OPCODE_BGNSUB); - entry->bgn_inst->function = entry; - - visit_exec_list(&entry->sig->body, &v); - - ir_to_mesa_instruction *last; - last = (ir_to_mesa_instruction *)v.instructions.get_tail(); - if (last->op != OPCODE_RET) - v.emit(NULL, OPCODE_RET); - - ir_to_mesa_instruction *end; - end = v.emit(NULL, OPCODE_ENDSUB); - end->function = entry; - - progress = GL_TRUE; - } - } - } while (progress); - prog->NumTemporaries = v.next_temp; int num_instructions = 0; @@ -3219,16 +2950,6 @@ get_mesa_program(struct gl_context *ctx, "rasterization.\n"); } break; - case OPCODE_BGNSUB: - inst->function->inst = i; - 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 */ - break; case OPCODE_ARL: prog->NumAddressRegs = 1; break; @@ -3270,11 +2991,17 @@ get_mesa_program(struct gl_context *ctx, */ mesa_instructions = NULL; - do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER); - count_resources(prog); + do_set_program_inouts(shader->ir, prog, shader->Type); - if (!check_resources(ctx, shader_program, prog)) - goto fail_exit; + prog->SamplersUsed = shader->active_samplers; + prog->ShadowSamplers = shader->shadow_samplers; + _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; + } _mesa_reference_program(ctx, &shader->Program, prog); @@ -3282,6 +3009,15 @@ get_mesa_program(struct gl_context *ctx, _mesa_optimize_program(ctx, prog); } + /* This has to be done last. Any operation that can cause + * prog->ParameterValues to get reallocated (e.g., anything that adds a + * program constant) has to happen before creating this linkage. + */ + _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters); + if (!shader_program->LinkStatus) { + goto fail_exit; + } + return prog; fail_exit: @@ -3324,7 +3060,8 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; progress = do_common_optimization(ir, true, true, - options->MaxUnrollIterations) + options->MaxUnrollIterations, + options) || progress; progress = lower_quadop_vector(ir, true) || progress; @@ -3351,6 +3088,7 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) || progress; progress = do_vec_index_to_cond_assign(ir) || progress; + progress = lower_vector_insert(ir, true) || progress; } while (progress); validate_ir_tree(ir); @@ -3365,20 +3103,13 @@ _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) { - static const GLenum targets[] = { - GL_VERTEX_PROGRAM_ARB, - GL_FRAGMENT_PROGRAM_ARB, - GL_GEOMETRY_PROGRAM_NV - }; - - if (i == MESA_SHADER_VERTEX) { - ((struct gl_vertex_program *)linked_prog)->UsesClipDistance - = prog->Vert.UsesClipDistance; - } + _mesa_copy_linked_program_data((gl_shader_type) i, prog, linked_prog); _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, linked_prog); - if (!ctx->Driver.ProgramStringNotify(ctx, targets[i], linked_prog)) { + if (!ctx->Driver.ProgramStringNotify(ctx, + _mesa_program_index_to_target(i), + linked_prog)) { return GL_FALSE; } } @@ -3389,91 +3120,6 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) return prog->LinkStatus; } - -/** - * Compile a GLSL shader. Called via glCompileShader(). - */ -void -_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) -{ - struct _mesa_glsl_parse_state *state = - new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader); - - const char *source = shader->Source; - /* Check if the user called glCompileShader without first calling - * glShaderSource. This should fail to compile, but not raise a GL_ERROR. - */ - if (source == NULL) { - shader->CompileStatus = GL_FALSE; - return; - } - - state->error = preprocess(state, &source, &state->info_log, - &ctx->Extensions, ctx->API); - - if (ctx->Shader.Flags & GLSL_DUMP) { - printf("GLSL source for %s shader %d:\n", - _mesa_glsl_shader_target_name(state->target), shader->Name); - printf("%s\n", shader->Source); - } - - if (!state->error) { - _mesa_glsl_lexer_ctor(state, source); - _mesa_glsl_parse(state); - _mesa_glsl_lexer_dtor(state); - } - - ralloc_free(shader->ir); - shader->ir = new(shader) exec_list; - if (!state->error && !state->translation_unit.is_empty()) - _mesa_ast_to_hir(shader->ir, state); - - if (!state->error && !shader->ir->is_empty()) { - validate_ir_tree(shader->ir); - - /* 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, false, 32)) - ; - - validate_ir_tree(shader->ir); - } - - shader->symbols = state->symbols; - - shader->CompileStatus = !state->error; - shader->InfoLog = state->info_log; - shader->Version = state->language_version; - memcpy(shader->builtins_to_link, state->builtins_to_link, - 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); - } - - if (ctx->Shader.Flags & GLSL_DUMP) { - if (shader->CompileStatus) { - printf("GLSL IR for shader %d:\n", shader->Name); - _mesa_print_ir(shader->ir, NULL); - printf("\n\n"); - } else { - printf("GLSL shader %d failed to compile.\n", shader->Name); - } - if (shader->InfoLog && shader->InfoLog[0] != 0) { - printf("GLSL shader %d info log:\n", shader->Name); - printf("%s\n", shader->InfoLog); - } - } - - /* Retain any live IR, but trash the rest. */ - reparent_ir(shader->ir, shader->ir); - - ralloc_free(state); -} - - /** * Link a GLSL shader program. Called via glLinkProgram(). */ @@ -3489,7 +3135,6 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) for (i = 0; i < prog->NumShaders; i++) { if (!prog->Shaders[i]->CompileStatus) { linker_error(prog, "linking with uncompiled shader"); - prog->LinkStatus = GL_FALSE; } } @@ -3503,8 +3148,6 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) } } - set_uniform_initializers(ctx, prog); - if (ctx->Shader.Flags & GLSL_DUMP) { if (!prog->LinkStatus) { printf("GLSL shader program %d failed to link\n", prog->Name);