diff options
author | marha <marha@users.sourceforge.net> | 2013-12-22 12:51:45 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2013-12-22 12:51:45 +0100 |
commit | c81020559f329a516191927222b3698ba7370aca (patch) | |
tree | 6f004f5723ca41881b2ba703ed619a92faebfe16 /mesalib/src/glsl | |
parent | c043f97a8572e1f509251288d8bcd70d0fb96770 (diff) | |
download | vcxsrv-c81020559f329a516191927222b3698ba7370aca.tar.gz vcxsrv-c81020559f329a516191927222b3698ba7370aca.tar.bz2 vcxsrv-c81020559f329a516191927222b3698ba7370aca.zip |
libxtrans fontconfig glproto libX11 libxcb xcbproto mesa xserver pixman xkeyboard-config git update 22 Dec 2013
xserver commit a68df147421da21528b5be2d34678383922fa352
libxcb commit f653464554469b5767f1c99abced25a76bace047
libxcb/xcb-proto commit 4087fc682c5ceb849b74442e17a6b73176e5eecb
xkeyboard-config commit a224a636139d22e1dc7ca7d23782cd656e87bcf5
libX11 commit 3d69b0a83e62f8f6fbdd952fc49cdbdf8825e1e6
libXdmcp commit 089081dca4ba3598c6f9bf401c029378943b5854
libXext commit bb24f2970f2e425f4df90c9b73d078ad15a73fbb
libfontenc commit 3acba630d8b57084f7e92c15732408711ed5137a
libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909
libXau commit 304a11be4727c5a7feeb2501e8e001466f8ce84e
xkbcomp commit e3e6e938535532bfad175c1635256ab7fb3ac943
pixman commit 945ab7a6f3eb6241f07e8f094dc0e647d1f10d9d
xextproto commit 3f355f138d6df57e067458a20f47307883048adb
randrproto commit e7526e6b5fe0966929cda10b2ded0258413744db
glproto commit f84853d97d5749308992412a215fa518b6536eb3
mkfontscale commit 880a0c4733e62e54e6a0f1238c7430727d23657b
xwininfo commit ba0d1b0da21d2dbdd81098ed5778f3792b472e13
libXft commit 4acfdaf95adb0a05c2a25550bdde036c865902f4
libXmu commit 22d9c590901e121936f50dee97dc60c4f7defb63
libxtrans commit 2c0a7840a28ae696e80e73157856d7a049fdf6c7
fontconfig commit 5c725f2f5829238d16116f782d00d8bb0defaf08
mesa commit 2efe7927d38983029784825fc4897e9b77aa237e
Diffstat (limited to 'mesalib/src/glsl')
56 files changed, 1279 insertions, 1155 deletions
diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 5c214b604..76911f056 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -357,6 +357,7 @@ struct ast_type_qualifier { unsigned in:1; unsigned out:1; unsigned centroid:1; + unsigned sample:1; unsigned uniform:1; unsigned smooth:1; unsigned flat:1; diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp index f7b5e8350..a5f23206a 100644 --- a/mesalib/src/glsl/ast_array_index.cpp +++ b/mesalib/src/glsl/ast_array_index.cpp @@ -41,8 +41,8 @@ update_max_array_access(ir_rvalue *ir, unsigned idx, YYLTYPE *loc, { if (ir_dereference_variable *deref_var = ir->as_dereference_variable()) { ir_variable *var = deref_var->var; - if (idx > var->max_array_access) { - var->max_array_access = idx; + if (idx > var->data.max_array_access) { + var->data.max_array_access = idx; /* Check whether this access will, as a side effect, implicitly cause * the size of a built-in array to be too large. @@ -168,7 +168,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, if (array->type->is_unsized_array()) { _mesa_glsl_error(&loc, state, "unsized array index must be constant"); } else if (array->type->fields.array->is_interface() - && array->variable_referenced()->mode == ir_var_uniform) { + && array->variable_referenced()->data.mode == ir_var_uniform) { /* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says: * * "All indexes used to index a uniform block array must be @@ -184,7 +184,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, */ ir_variable *v = array->whole_variable_referenced(); if (v != NULL) - v->max_array_access = array->type->array_size() - 1; + v->data.max_array_access = array->type->array_size() - 1; } /* From page 23 (29 of the PDF) of the GLSL 1.30 spec: diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 2707522ef..e4c0fd1c4 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -123,7 +123,7 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, YYLTYPE loc = actual_ast->get_location(); /* Verify that 'const_in' parameters are ir_constants. */ - if (formal->mode == ir_var_const_in && + if (formal->data.mode == ir_var_const_in && actual->ir_type != ir_type_constant) { _mesa_glsl_error(&loc, state, "parameter `in %s' must be a constant expression", @@ -132,10 +132,10 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, } /* Verify that 'out' and 'inout' actual parameters are lvalues. */ - if (formal->mode == ir_var_function_out - || formal->mode == ir_var_function_inout) { + if (formal->data.mode == ir_var_function_out + || formal->data.mode == ir_var_function_inout) { const char *mode = NULL; - switch (formal->mode) { + switch (formal->data.mode) { case ir_var_function_out: mode = "out"; break; case ir_var_function_inout: mode = "inout"; break; default: assert(false); break; @@ -155,9 +155,9 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, ir_variable *var = actual->variable_referenced(); if (var) - var->assigned = true; + var->data.assigned = true; - if (var && var->read_only) { + if (var && var->data.read_only) { _mesa_glsl_error(&loc, state, "function parameter '%s %s' references the " "read-only variable '%s'", @@ -274,20 +274,20 @@ fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type, } /** - * If a function call is generated, \c call_ir will point to it on exit. - * Otherwise \c call_ir will be set to \c NULL. + * Generate a function call. + * + * For non-void functions, this returns a dereference of the temporary variable + * which stores the return value for the call. For void functions, this returns + * NULL. */ static ir_rvalue * generate_call(exec_list *instructions, ir_function_signature *sig, exec_list *actual_parameters, - ir_call **call_ir, struct _mesa_glsl_parse_state *state) { void *ctx = state; exec_list post_call_conversions; - *call_ir = NULL; - /* Perform implicit conversion of arguments. For out parameters, we need * to place them in a temporary variable and do the conversion after the * call takes place. Since we haven't emitted the call yet, we'll place @@ -304,7 +304,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig, assert(formal != NULL); if (formal->type->is_numeric() || formal->type->is_boolean()) { - switch (formal->mode) { + switch (formal->data.mode) { case ir_var_const_in: case ir_var_function_in: { ir_rvalue *converted @@ -316,7 +316,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig, case ir_var_function_inout: fix_parameter(ctx, actual, formal->type, instructions, &post_call_conversions, - formal->mode == ir_var_function_inout); + formal->data.mode == ir_var_function_inout); break; default: assert (!"Illegal formal parameter mode"); @@ -421,6 +421,25 @@ done: return sig; } +static void +print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc, + ir_function *f) +{ + if (f == NULL) + return; + + foreach_list (node, &f->signatures) { + ir_function_signature *sig = (ir_function_signature *) node; + + if (sig->is_builtin() && !sig->is_builtin_available(state)) + continue; + + char *str = prototype_string(sig->return_type, f->name, &sig->parameters); + _mesa_glsl_error(loc, state, " %s", str); + ralloc_free(str); + } +} + /** * Raise a "no matching function" error, listing all possible overloads the * compiler considered so developers can figure out what went wrong. @@ -431,30 +450,23 @@ no_matching_function_error(const char *name, exec_list *actual_parameters, _mesa_glsl_parse_state *state) { - char *str = prototype_string(NULL, name, actual_parameters); - _mesa_glsl_error(loc, state, "no matching function for call to `%s'", str); - ralloc_free(str); - - const char *prefix = "candidates are: "; + gl_shader *sh = _mesa_glsl_get_builtin_function_shader(); - for (int i = -1; i < (int) state->num_builtins_to_link; i++) { - glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols - : state->symbols; - ir_function *f = syms->get_function(name); - if (f == NULL) - continue; - - foreach_list (node, &f->signatures) { - ir_function_signature *sig = (ir_function_signature *) node; - - if (sig->is_builtin() && !sig->is_builtin_available(state)) - continue; + if (state->symbols->get_function(name) == NULL + && (!state->uses_builtin_functions + || sh->symbols->get_function(name) == NULL)) { + _mesa_glsl_error(loc, state, "no function with name '%s'", name); + } else { + char *str = prototype_string(NULL, name, actual_parameters); + _mesa_glsl_error(loc, state, + "no matching function for call to `%s'; candidates are:", + str); + ralloc_free(str); - str = prototype_string(sig->return_type, f->name, &sig->parameters); - _mesa_glsl_error(loc, state, "%s%s", prefix, str); - ralloc_free(str); + print_function_prototypes(state, loc, state->symbols->get_function(name)); - prefix = " "; + if (state->uses_builtin_functions) { + print_function_prototypes(state, loc, sh->symbols->get_function(name)); } } } @@ -1651,7 +1663,7 @@ ast_function_expression::hir(exec_list *instructions, } else { const ast_expression *id = subexpressions[0]; const char *func_name = id->primary_expression.identifier; - YYLTYPE loc = id->get_location(); + YYLTYPE loc = get_location(); exec_list actual_parameters; process_parameters(instructions, &actual_parameters, &this->expressions, @@ -1660,7 +1672,6 @@ ast_function_expression::hir(exec_list *instructions, ir_function_signature *sig = match_function_by_name(func_name, &actual_parameters, state); - ir_call *call = NULL; ir_rvalue *value = NULL; if (sig == NULL) { no_matching_function_error(func_name, &loc, &actual_parameters, state); @@ -1669,8 +1680,7 @@ ast_function_expression::hir(exec_list *instructions, /* an error has already been emitted */ value = ir_rvalue::error_value(ctx); } else { - value = generate_call(instructions, sig, &actual_parameters, - &call, state); + value = generate_call(instructions, sig, &actual_parameters, state); } return value; diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 43cf49745..3bc181e87 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -728,7 +728,7 @@ mark_whole_array_access(ir_rvalue *access) ir_dereference_variable *deref = access->as_dereference_variable(); if (deref && deref->var) { - deref->var->max_array_access = deref->type->length - 1; + deref->var->data.max_array_access = deref->type->length - 1; } } @@ -767,7 +767,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, ir_variable *lhs_var = lhs->variable_referenced(); if (lhs_var) - lhs_var->assigned = true; + lhs_var->data.assigned = true; if (!error_emitted) { if (non_lvalue_description != NULL) { @@ -776,7 +776,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, non_lvalue_description); error_emitted = true; } else if (lhs->variable_referenced() != NULL - && lhs->variable_referenced()->read_only) { + && lhs->variable_referenced()->data.read_only) { _mesa_glsl_error(&lhs_loc, state, "assignment to read-only variable '%s'", lhs->variable_referenced()->name); @@ -819,11 +819,11 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, assert(var != NULL); - if (var->max_array_access >= unsigned(rhs->type->array_size())) { + if (var->data.max_array_access >= unsigned(rhs->type->array_size())) { /* FINISHME: This should actually log the location of the RHS. */ _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to " "previous access", - var->max_array_access); + var->data.max_array_access); } var->type = glsl_type::get_array_instance(lhs->type->element_type(), @@ -866,7 +866,7 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp", ir_var_temporary); instructions->push_tail(var); - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), lvalue)); @@ -1639,7 +1639,7 @@ ast_expression::hir(exec_list *instructions, state->symbols->get_variable(this->primary_expression.identifier); if (var != NULL) { - var->used = true; + var->data.used = true; result = new(ctx) ir_dereference_variable(var); } else { _mesa_glsl_error(& loc, state, "`%s' undeclared", @@ -1860,7 +1860,7 @@ ast_fully_specified_type::glsl_type(const char **name, if (type->base_type == GLSL_TYPE_FLOAT && state->es_shader - && state->target == fragment_shader + && state->target == MESA_SHADER_FRAGMENT && this->qualifier.precision == ast_precision_none && state->symbols->get_variable("#default precision") == NULL) { YYLTYPE loc = this->get_location(); @@ -1882,15 +1882,15 @@ ast_fully_specified_type::glsl_type(const char **name, * this function will produce undefined results. */ static bool -is_varying_var(ir_variable *var, _mesa_glsl_parser_targets target) +is_varying_var(ir_variable *var, gl_shader_type target) { switch (target) { - case vertex_shader: - return var->mode == ir_var_shader_out; - case fragment_shader: - return var->mode == ir_var_shader_in; + case MESA_SHADER_VERTEX: + return var->data.mode == ir_var_shader_out; + case MESA_SHADER_FRAGMENT: + return var->data.mode == ir_var_shader_in; default: - return var->mode == ir_var_shader_out || var->mode == ir_var_shader_in; + return var->data.mode == ir_var_shader_out || var->data.mode == ir_var_shader_in; } } @@ -1941,7 +1941,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, ir_variable *var, const ast_type_qualifier *qual) { - if (var->mode != ir_var_uniform) { + if (var->data.mode != ir_var_uniform) { _mesa_glsl_error(loc, state, "the \"binding\" qualifier only applies to uniforms"); return false; @@ -1985,13 +1985,13 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, */ unsigned limit = 0; switch (state->target) { - case vertex_shader: + case MESA_SHADER_VERTEX: limit = ctx->Const.VertexProgram.MaxTextureImageUnits; break; - case geometry_shader: + case MESA_SHADER_GEOMETRY: limit = ctx->Const.GeometryProgram.MaxTextureImageUnits; break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: limit = ctx->Const.FragmentProgram.MaxTextureImageUnits; break; } @@ -2049,8 +2049,8 @@ interpret_interpolation_qualifier(const struct ast_type_qualifier *qual, } - if ((state->target == vertex_shader && mode == ir_var_shader_in) || - (state->target == fragment_shader && mode == ir_var_shader_out)) { + if ((state->target == MESA_SHADER_VERTEX && mode == ir_var_shader_in) || + (state->target == MESA_SHADER_FRAGMENT && mode == ir_var_shader_out)) { _mesa_glsl_error(loc, state, "interpolation qualifier `%s' cannot be applied to " "vertex shader inputs or fragment shader outputs", @@ -2077,8 +2077,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual, * locations. */ switch (state->target) { - case vertex_shader: - if (var->mode == ir_var_shader_in) { + case MESA_SHADER_VERTEX: + if (var->data.mode == ir_var_shader_in) { if (!state->check_explicit_attrib_location_allowed(loc, var)) return; @@ -2088,14 +2088,14 @@ validate_explicit_location(const struct ast_type_qualifier *qual, fail = true; break; - case geometry_shader: + case MESA_SHADER_GEOMETRY: _mesa_glsl_error(loc, state, "geometry shader variables cannot be given " "explicit locations"); return; - case fragment_shader: - if (var->mode == ir_var_shader_out) { + case MESA_SHADER_FRAGMENT: + if (var->data.mode == ir_var_shader_out) { if (!state->check_explicit_attrib_location_allowed(loc, var)) return; @@ -2112,7 +2112,7 @@ validate_explicit_location(const struct ast_type_qualifier *qual, mode_string(var), _mesa_glsl_shader_target_name(state->target)); } else { - var->explicit_location = true; + var->data.explicit_location = true; /* This bit of silliness is needed because invalid explicit locations * are supposed to be flagged during linking. Small negative values @@ -2122,11 +2122,11 @@ validate_explicit_location(const struct ast_type_qualifier *qual, * ensures that negative values stay negative. */ if (qual->location >= 0) { - var->location = (state->target == vertex_shader) + var->data.location = (state->target == MESA_SHADER_VERTEX) ? (qual->location + VERT_ATTRIB_GENERIC0) : (qual->location + FRAG_RESULT_DATA0); } else { - var->location = qual->location; + var->data.location = qual->location; } if (qual->flags.q.explicit_index) { @@ -2143,8 +2143,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual, _mesa_glsl_error(loc, state, "explicit index may only be 0 or 1"); } else { - var->explicit_index = true; - var->index = qual->index; + var->data.explicit_index = true; + var->data.index = qual->index; } } } @@ -2162,25 +2162,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i)); if (qual->flags.q.invariant) { - if (var->used) { + if (var->data.used) { _mesa_glsl_error(loc, state, "variable `%s' may not be redeclared " "`invariant' after being used", var->name); } else { - var->invariant = 1; + var->data.invariant = 1; } } if (qual->flags.q.constant || qual->flags.q.attribute || qual->flags.q.uniform - || (qual->flags.q.varying && (state->target == fragment_shader))) - var->read_only = 1; + || (qual->flags.q.varying && (state->target == MESA_SHADER_FRAGMENT))) + var->data.read_only = 1; if (qual->flags.q.centroid) - var->centroid = 1; + var->data.centroid = 1; - if (qual->flags.q.attribute && state->target != vertex_shader) { + if (qual->flags.q.sample) + var->data.sample = 1; + + if (qual->flags.q.attribute && state->target != MESA_SHADER_VERTEX) { var->type = glsl_type::error_type; _mesa_glsl_error(loc, state, "`attribute' variables may not be declared in the " @@ -2207,18 +2210,18 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, * the setting alone. */ if (qual->flags.q.in && qual->flags.q.out) - var->mode = ir_var_function_inout; + var->data.mode = ir_var_function_inout; else if (qual->flags.q.in) - var->mode = is_parameter ? ir_var_function_in : ir_var_shader_in; + var->data.mode = is_parameter ? ir_var_function_in : ir_var_shader_in; else if (qual->flags.q.attribute - || (qual->flags.q.varying && (state->target == fragment_shader))) - var->mode = ir_var_shader_in; + || (qual->flags.q.varying && (state->target == MESA_SHADER_FRAGMENT))) + var->data.mode = ir_var_shader_in; else if (qual->flags.q.out) - var->mode = is_parameter ? ir_var_function_out : ir_var_shader_out; - else if (qual->flags.q.varying && (state->target == vertex_shader)) - var->mode = ir_var_shader_out; + var->data.mode = is_parameter ? ir_var_function_out : ir_var_shader_out; + else if (qual->flags.q.varying && (state->target == MESA_SHADER_VERTEX)) + var->data.mode = ir_var_shader_out; else if (qual->flags.q.uniform) - var->mode = ir_var_uniform; + var->data.mode = ir_var_uniform; if (!is_parameter && is_varying_var(var, state->target)) { /* This variable is being used to link data between shader stages (in @@ -2270,28 +2273,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (state->all_invariant && (state->current_function == NULL)) { switch (state->target) { - case vertex_shader: - if (var->mode == ir_var_shader_out) - var->invariant = true; + case MESA_SHADER_VERTEX: + if (var->data.mode == ir_var_shader_out) + var->data.invariant = true; break; - case geometry_shader: - if ((var->mode == ir_var_shader_in) - || (var->mode == ir_var_shader_out)) - var->invariant = true; + case MESA_SHADER_GEOMETRY: + if ((var->data.mode == ir_var_shader_in) + || (var->data.mode == ir_var_shader_out)) + var->data.invariant = true; break; - case fragment_shader: - if (var->mode == ir_var_shader_in) - var->invariant = true; + case MESA_SHADER_FRAGMENT: + if (var->data.mode == ir_var_shader_in) + var->data.invariant = true; break; } } - var->interpolation = - interpret_interpolation_qualifier(qual, (ir_variable_mode) var->mode, + var->data.interpolation = + interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode, state, loc); - var->pixel_center_integer = qual->flags.q.pixel_center_integer; - var->origin_upper_left = qual->flags.q.origin_upper_left; + var->data.pixel_center_integer = qual->flags.q.pixel_center_integer; + var->data.origin_upper_left = qual->flags.q.origin_upper_left; if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer) && (strcmp(var->name, "gl_FragCoord") != 0)) { const char *const qual_string = (qual->flags.q.origin_upper_left) @@ -2312,27 +2315,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (qual->flags.q.explicit_binding && validate_binding_qualifier(state, loc, var, qual)) { - var->explicit_binding = true; - var->binding = qual->binding; + var->data.explicit_binding = true; + var->data.binding = qual->binding; } if (var->type->contains_atomic()) { - if (var->mode == ir_var_uniform) { - if (var->explicit_binding) { - unsigned *offset = &state->atomic_counter_offsets[var->binding]; + if (var->data.mode == ir_var_uniform) { + if (var->data.explicit_binding) { + unsigned *offset = + &state->atomic_counter_offsets[var->data.binding]; if (*offset % ATOMIC_COUNTER_SIZE) _mesa_glsl_error(loc, state, "misaligned atomic counter offset"); - var->atomic.offset = *offset; + var->data.atomic.offset = *offset; *offset += var->type->atomic_size(); } else { _mesa_glsl_error(loc, state, "atomic counters require explicit binding point"); } - } else if (var->mode != ir_var_function_in) { + } else if (var->data.mode != ir_var_function_in) { _mesa_glsl_error(loc, state, "atomic counters may only be declared as " "function parameters or uniform-qualified " "global variables"); @@ -2406,15 +2410,15 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, "gl_FragDepth"); } if (qual->flags.q.depth_any) - var->depth_layout = ir_depth_layout_any; + var->data.depth_layout = ir_depth_layout_any; else if (qual->flags.q.depth_greater) - var->depth_layout = ir_depth_layout_greater; + var->data.depth_layout = ir_depth_layout_greater; else if (qual->flags.q.depth_less) - var->depth_layout = ir_depth_layout_less; + var->data.depth_layout = ir_depth_layout_less; else if (qual->flags.q.depth_unchanged) - var->depth_layout = ir_depth_layout_unchanged; + var->data.depth_layout = ir_depth_layout_unchanged; else - var->depth_layout = ir_depth_layout_none; + var->data.depth_layout = ir_depth_layout_none; if (qual->flags.q.std140 || qual->flags.q.packed || @@ -2475,10 +2479,10 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, const unsigned size = unsigned(var->type->array_size()); check_builtin_array_max_size(var->name, size, loc, state); - if ((size > 0) && (size <= earlier->max_array_access)) { + if ((size > 0) && (size <= earlier->data.max_array_access)) { _mesa_glsl_error(& loc, state, "array size must be > %u due to " "previous access", - earlier->max_array_access); + earlier->data.max_array_access); } earlier->type = var->type; @@ -2488,12 +2492,12 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, state->is_version(150, 0)) && strcmp(var->name, "gl_FragCoord") == 0 && earlier->type == var->type - && earlier->mode == var->mode) { + && earlier->data.mode == var->data.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; + earlier->data.origin_upper_left = var->data.origin_upper_left; + earlier->data.pixel_center_integer = var->data.pixel_center_integer; /* According to section 4.3.7 of the GLSL 1.30 spec, * the following built-in varaibles can be redeclared with an @@ -2513,41 +2517,41 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, || strcmp(var->name, "gl_Color") == 0 || strcmp(var->name, "gl_SecondaryColor") == 0) && earlier->type == var->type - && earlier->mode == var->mode) { - earlier->interpolation = var->interpolation; + && earlier->data.mode == var->data.mode) { + earlier->data.interpolation = var->data.interpolation; /* Layout qualifiers for gl_FragDepth. */ } else if ((state->AMD_conservative_depth_enable || state->ARB_conservative_depth_enable) && strcmp(var->name, "gl_FragDepth") == 0 && earlier->type == var->type - && earlier->mode == var->mode) { + && earlier->data.mode == var->data.mode) { /** From the AMD_conservative_depth spec: * Within any shader, the first redeclarations of gl_FragDepth * must appear before any use of gl_FragDepth. */ - if (earlier->used) { + if (earlier->data.used) { _mesa_glsl_error(&loc, state, "the first redeclaration of gl_FragDepth " "must appear before any use of gl_FragDepth"); } /* Prevent inconsistent redeclaration of depth layout qualifier. */ - if (earlier->depth_layout != ir_depth_layout_none - && earlier->depth_layout != var->depth_layout) { + if (earlier->data.depth_layout != ir_depth_layout_none + && earlier->data.depth_layout != var->data.depth_layout) { _mesa_glsl_error(&loc, state, "gl_FragDepth: depth layout is declared here " "as '%s, but it was previously declared as " "'%s'", - depth_layout_string(var->depth_layout), - depth_layout_string(earlier->depth_layout)); + depth_layout_string(var->data.depth_layout), + depth_layout_string(earlier->data.depth_layout)); } - earlier->depth_layout = var->depth_layout; + earlier->data.depth_layout = var->data.depth_layout; } else if (allow_all_redeclarations) { - if (earlier->mode != var->mode) { + if (earlier->data.mode != var->data.mode) { _mesa_glsl_error(&loc, state, "redeclaration of `%s' with incorrect qualifiers", var->name); @@ -2582,7 +2586,7 @@ process_initializer(ir_variable *var, ast_declaration *decl, * directly by an application via API commands, or indirectly by * OpenGL." */ - if (var->mode == ir_var_uniform) { + if (var->data.mode == ir_var_uniform) { state->check_version(120, 0, &initializer_loc, "cannot initialize uniforms"); } @@ -2592,11 +2596,11 @@ process_initializer(ir_variable *var, ast_declaration *decl, "cannot initialize samplers"); } - if ((var->mode == ir_var_shader_in) && (state->current_function == NULL)) { + if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) { _mesa_glsl_error(& initializer_loc, state, "cannot initialize %s shader input / %s", _mesa_glsl_shader_target_name(state->target), - (state->target == vertex_shader) + (state->target == MESA_SHADER_VERTEX) ? "attribute" : "varying"); } @@ -2647,9 +2651,9 @@ process_initializer(ir_variable *var, ast_declaration *decl, } if (rhs && !rhs->type->is_error()) { - bool temp = var->read_only; + bool temp = var->data.read_only; if (type->qualifier.flags.q.constant) - var->read_only = false; + var->data.read_only = false; /* Never emit code to initialize a uniform. */ @@ -2664,7 +2668,7 @@ process_initializer(ir_variable *var, ast_declaration *decl, initializer_type = rhs->type; var->constant_initializer = rhs->constant_expression_value(); - var->has_initializer = true; + var->data.has_initializer = true; /* If the declared variable is an unsized array, it must inherrit * its full type from the initializer. A declaration such as @@ -2688,7 +2692,7 @@ process_initializer(ir_variable *var, ast_declaration *decl, */ var->type = initializer_type; - var->read_only = temp; + var->data.read_only = temp; } return result; @@ -2840,23 +2844,23 @@ ast_declarator_list::hir(exec_list *instructions, _mesa_glsl_error(& loc, state, "undeclared variable `%s' cannot be marked " "invariant", decl->identifier); - } else if ((state->target == vertex_shader) - && (earlier->mode != ir_var_shader_out)) { + } else if ((state->target == MESA_SHADER_VERTEX) + && (earlier->data.mode != ir_var_shader_out)) { _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, vertex shader " "outputs only", decl->identifier); - } else if ((state->target == fragment_shader) - && (earlier->mode != ir_var_shader_in)) { + } else if ((state->target == MESA_SHADER_FRAGMENT) + && (earlier->data.mode != ir_var_shader_in)) { _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, fragment shader " "inputs only", decl->identifier); - } else if (earlier->used) { + } else if (earlier->data.used) { _mesa_glsl_error(& loc, state, "variable `%s' may not be redeclared " "`invariant' after being used", earlier->name); } else { - earlier->invariant = true; + earlier->data.invariant = true; } } @@ -2940,7 +2944,7 @@ ast_declarator_list::hir(exec_list *instructions, precision_names[this->type->qualifier.precision], type_name); } - } else { + } else if (this->type->specifier->structure == NULL) { _mesa_glsl_warning(&loc, state, "empty declaration"); } } @@ -3030,13 +3034,13 @@ ast_declarator_list::hir(exec_list *instructions, & loc, false); if (this->type->qualifier.flags.q.invariant) { - if ((state->target == vertex_shader) && - var->mode != ir_var_shader_out) { + if ((state->target == MESA_SHADER_VERTEX) && + var->data.mode != ir_var_shader_out) { _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, vertex shader " "outputs only", var->name); - } else if ((state->target == fragment_shader) && - var->mode != ir_var_shader_in) { + } else if ((state->target == MESA_SHADER_FRAGMENT) && + var->data.mode != ir_var_shader_in) { /* FINISHME: Note that this doesn't work for invariant on * a function signature inval */ @@ -3073,10 +3077,10 @@ ast_declarator_list::hir(exec_list *instructions, "global scope%s", mode, var->name, extra); } - } else if (var->mode == ir_var_shader_in) { - var->read_only = true; + } else if (var->data.mode == ir_var_shader_in) { + var->data.read_only = true; - if (state->target == vertex_shader) { + if (state->target == MESA_SHADER_VERTEX) { bool error_emitted = false; /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: @@ -3131,7 +3135,7 @@ ast_declarator_list::hir(exec_list *instructions, "cannot have array type")) { error_emitted = true; } - } else if (state->target == geometry_shader) { + } else if (state->target == MESA_SHADER_GEOMETRY) { /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: * * Geometry shader input variables get the per-vertex values @@ -3180,11 +3184,11 @@ ast_declarator_list::hir(exec_list *instructions, */ if (state->is_version(130, 300) && var->type->contains_integer() && - var->interpolation != INTERP_QUALIFIER_FLAT && - ((state->target == fragment_shader && var->mode == ir_var_shader_in) - || (state->target == vertex_shader && var->mode == ir_var_shader_out + var->data.interpolation != INTERP_QUALIFIER_FLAT && + ((state->target == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_in) + || (state->target == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_out && state->es_shader))) { - const char *var_type = (state->target == vertex_shader) ? + const char *var_type = (state->target == MESA_SHADER_VERTEX) ? "vertex output" : "fragment input"; _mesa_glsl_error(&loc, state, "if a %s is (or contains) " "an integer, then it must be qualified with 'flat'", @@ -3241,14 +3245,14 @@ ast_declarator_list::hir(exec_list *instructions, assert(i != NULL); switch (state->target) { - case vertex_shader: + case MESA_SHADER_VERTEX: if (this->type->qualifier.flags.q.in) { _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to vertex " "shader inputs", i); } break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: if (this->type->qualifier.flags.q.out) { _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to fragment " @@ -3271,12 +3275,20 @@ ast_declarator_list::hir(exec_list *instructions, if (state->is_version(130, 300) && this->type->qualifier.flags.q.centroid && this->type->qualifier.flags.q.in - && state->target == vertex_shader) { + && state->target == MESA_SHADER_VERTEX) { _mesa_glsl_error(&loc, state, "'centroid in' cannot be used in a vertex shader"); } + if (state->target == MESA_SHADER_VERTEX + && this->type->qualifier.flags.q.sample + && this->type->qualifier.flags.q.in) { + + _mesa_glsl_error(&loc, state, + "'sample in' cannot be used in a vertex shader"); + } + /* Section 4.3.6 of the GLSL 1.30 specification states: * "It is an error to use centroid out in a fragment shader." * @@ -3284,7 +3296,7 @@ ast_declarator_list::hir(exec_list *instructions, * "It is an error to use auxiliary storage qualifiers or interpolation * qualifiers on an output in a fragment shader." */ - if (state->target == fragment_shader && + if (state->target == MESA_SHADER_FRAGMENT && this->type->qualifier.flags.q.out && this->type->qualifier.has_auxiliary_storage()) { _mesa_glsl_error(&loc, state, @@ -3363,12 +3375,12 @@ ast_declarator_list::hir(exec_list *instructions, false /* allow_all_redeclarations */); if (earlier != NULL) { if (strncmp(var->name, "gl_", 3) == 0 && - earlier->how_declared == ir_var_declared_in_block) { + earlier->data.how_declared == ir_var_declared_in_block) { _mesa_glsl_error(&loc, state, "`%s' has already been redeclared using " "gl_PerVertex", var->name); } - earlier->how_declared = ir_var_declared_normally; + earlier->data.how_declared = ir_var_declared_normally; } if (decl->initializer != NULL) { @@ -3548,7 +3560,7 @@ ast_parameter_declarator::hir(exec_list *instructions, * as out or inout function parameters, nor can they be assigned * into." */ - if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out) + if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) && type->contains_sampler()) { _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers"); type = glsl_type::error_type; @@ -3568,7 +3580,7 @@ ast_parameter_declarator::hir(exec_list *instructions, * So for GLSL 1.10, passing an array as an out or inout parameter is not * allowed. This restriction is removed in GLSL 1.20, and in GLSL ES. */ - if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out) + if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) && type->is_array() && !state->check_version(120, 100, &loc, "arrays cannot be out or inout parameters")) { @@ -3942,7 +3954,7 @@ ast_jump_statement::hir(exec_list *instructions, } case ast_discard: - if (state->target != fragment_shader) { + if (state->target != MESA_SHADER_FRAGMENT) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, @@ -4480,7 +4492,7 @@ ast_type_specifier::hir(exec_list *instructions, if (type->base_type == GLSL_TYPE_FLOAT && state->es_shader - && state->target == fragment_shader) { + && state->target == MESA_SHADER_FRAGMENT) { /* Section 4.5.3 (Default Precision Qualifiers) of the GLSL ES 1.00 * spec says: * @@ -4662,6 +4674,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, fields[i].interpolation = interpret_interpolation_qualifier(qual, var_mode, state, &loc); fields[i].centroid = qual->flags.q.centroid ? 1 : 0; + fields[i].sample = qual->flags.q.sample ? 1 : 0; if (qual->flags.q.row_major || qual->flags.q.column_major) { if (!qual->flags.q.uniform) { @@ -4782,7 +4795,7 @@ public: virtual ir_visitor_status visit(ir_dereference_variable *ir) { - if (ir->var->mode == mode && ir->var->get_interface_type() == block) { + if (ir->var->data.mode == mode && ir->var->get_interface_type() == block) { found = true; return visit_stop; } @@ -4930,6 +4943,8 @@ ast_interface_block::hir(exec_list *instructions, earlier_per_vertex->fields.structure[j].interpolation; fields[i].centroid = earlier_per_vertex->fields.structure[j].centroid; + fields[i].sample = + earlier_per_vertex->fields.structure[j].sample; } } @@ -4980,7 +4995,7 @@ ast_interface_block::hir(exec_list *instructions, * variable (or input block, see interface blocks below) needs to be * declared as an array. */ - if (state->target == geometry_shader && !this->is_array && + if (state->target == MESA_SHADER_GEOMETRY && !this->is_array && var_mode == ir_var_shader_in) { _mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays"); } @@ -5035,7 +5050,7 @@ ast_interface_block::hir(exec_list *instructions, * geometry shader input. */ if (this->array_size == NULL && - (state->target != geometry_shader || !this->layout.flags.q.in)) { + (state->target != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) { _mesa_glsl_error(&loc, state, "only geometry shader inputs may be unsized " "instance block arrays"); @@ -5054,7 +5069,7 @@ ast_interface_block::hir(exec_list *instructions, var_mode); } - if (state->target == geometry_shader && var_mode == ir_var_shader_in) + if (state->target == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in) handle_geometry_shader_input_decl(state, loc, var); if (ir_variable *earlier = @@ -5063,7 +5078,7 @@ ast_interface_block::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "`%s' redeclared", this->instance_name); } - earlier->how_declared = ir_var_declared_normally; + earlier->data.how_declared = ir_var_declared_normally; earlier->type = var->type; earlier->reinit_interface_type(block_type); delete var; @@ -5082,8 +5097,9 @@ ast_interface_block::hir(exec_list *instructions, new(state) ir_variable(fields[i].type, ralloc_strdup(state, fields[i].name), var_mode); - var->interpolation = fields[i].interpolation; - var->centroid = fields[i].centroid; + var->data.interpolation = fields[i].interpolation; + var->data.centroid = fields[i].centroid; + var->data.sample = fields[i].sample; var->init_interface_type(block_type); if (redeclaring_per_vertex) { @@ -5094,11 +5110,11 @@ ast_interface_block::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "redeclaration of gl_PerVertex can only " "include built-in variables"); - } else if (earlier->how_declared == ir_var_declared_normally) { + } else if (earlier->data.how_declared == ir_var_declared_normally) { _mesa_glsl_error(&loc, state, "`%s' has already been redeclared", var->name); } else { - earlier->how_declared = ir_var_declared_in_block; + earlier->data.how_declared = ir_var_declared_in_block; earlier->reinit_interface_type(block_type); } continue; @@ -5111,8 +5127,8 @@ ast_interface_block::hir(exec_list *instructions, * the UBO declaration itself doesn't get an ir_variable unless it * has an instance name. This is ugly. */ - var->explicit_binding = this->layout.flags.q.explicit_binding; - var->binding = this->layout.binding; + var->data.explicit_binding = this->layout.flags.q.explicit_binding; + var->data.binding = this->layout.binding; state->symbols->add_variable(var); instructions->push_tail(var); @@ -5144,8 +5160,8 @@ ast_interface_block::hir(exec_list *instructions, ir_variable *const var = ((ir_instruction *) node)->as_variable(); if (var != NULL && var->get_interface_type() == earlier_per_vertex && - var->mode == var_mode) { - if (var->how_declared == ir_var_declared_normally) { + var->data.mode == var_mode) { + if (var->data.how_declared == ir_var_declared_normally) { _mesa_glsl_error(&loc, state, "redeclaration of gl_PerVertex cannot " "follow a redeclaration of `%s'", @@ -5200,7 +5216,7 @@ ast_gs_input_layout::hir(exec_list *instructions, */ foreach_list (node, instructions) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (var == NULL || var->mode != ir_var_shader_in) + if (var == NULL || var->data.mode != ir_var_shader_in) continue; /* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an @@ -5208,12 +5224,12 @@ ast_gs_input_layout::hir(exec_list *instructions, */ if (var->type->is_unsized_array()) { - if (var->max_array_access >= num_vertices) { + if (var->data.max_array_access >= num_vertices) { _mesa_glsl_error(&loc, state, "this geometry shader input layout implies %u" " vertices, but an access to element %u of input" " `%s' already exists", num_vertices, - var->max_array_access, var->name); + var->data.max_array_access, var->name); } else { var->type = glsl_type::get_array_instance(var->type->fields.array, num_vertices); @@ -5241,7 +5257,7 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, foreach_list(node, instructions) { ir_variable *var = ((ir_instruction *)node)->as_variable(); - if (!var || !var->assigned) + if (!var || !var->data.assigned) continue; if (strcmp(var->name, "gl_FragColor") == 0) @@ -5249,8 +5265,8 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, else if (strcmp(var->name, "gl_FragData") == 0) gl_FragData_assigned = true; else if (strncmp(var->name, "gl_", 3) != 0) { - if (state->target == fragment_shader && - var->mode == ir_var_shader_out) { + if (state->target == MESA_SHADER_FRAGMENT && + var->data.mode == ir_var_shader_out) { user_defined_fs_output_assigned = true; user_defined_fs_output = var; } @@ -5331,7 +5347,7 @@ remove_per_vertex_blocks(exec_list *instructions, foreach_list_safe(node, instructions) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); if (var != NULL && var->get_interface_type() == per_vertex && - var->mode == mode) { + var->data.mode == mode) { state->symbols->disable_variable(var->name); var->remove(); } diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index 2b088bf8b..d758bfa1f 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -90,7 +90,8 @@ ast_type_qualifier::has_storage() const bool ast_type_qualifier::has_auxiliary_storage() const { - return this->flags.q.centroid; + return this->flags.q.centroid + || this->flags.q.sample; } const char* diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index 8cb75e5ad..840a6c9a2 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -77,7 +77,7 @@ always_available(const _mesa_glsl_parse_state *state) static bool compatibility_vs_only(const _mesa_glsl_parse_state *state) { - return state->target == vertex_shader && + return state->target == MESA_SHADER_VERTEX && state->language_version <= 130 && !state->es_shader; } @@ -85,13 +85,13 @@ compatibility_vs_only(const _mesa_glsl_parse_state *state) static bool fs_only(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader; + return state->target == MESA_SHADER_FRAGMENT; } static bool gs_only(const _mesa_glsl_parse_state *state) { - return state->target == geometry_shader; + return state->target == MESA_SHADER_GEOMETRY; } static bool @@ -103,7 +103,7 @@ v110(const _mesa_glsl_parse_state *state) static bool v110_fs_only(const _mesa_glsl_parse_state *state) { - return !state->es_shader && state->target == fragment_shader; + return !state->es_shader && state->target == MESA_SHADER_FRAGMENT; } static bool @@ -122,7 +122,7 @@ static bool v130_fs_only(const _mesa_glsl_parse_state *state) { return state->is_version(130, 300) && - state->target == fragment_shader; + state->target == MESA_SHADER_FRAGMENT; } static bool @@ -155,7 +155,7 @@ lod_exists_in_stage(const _mesa_glsl_parse_state *state) * Since ARB_shader_texture_lod can only be enabled on desktop GLSL, we * don't need to explicitly check state->es_shader. */ - return state->target == vertex_shader || + return state->target == MESA_SHADER_VERTEX || state->is_version(130, 300) || state->ARB_shader_texture_lod_enable; } @@ -223,7 +223,7 @@ texture_array_lod(const _mesa_glsl_parse_state *state) static bool fs_texture_array(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && state->EXT_texture_array_enable; } @@ -243,7 +243,7 @@ texture_multisample(const _mesa_glsl_parse_state *state) static bool fs_texture_cube_map_array(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && (state->is_version(400, 0) || state->ARB_texture_cube_map_array_enable); } @@ -265,7 +265,7 @@ texture_query_levels(const _mesa_glsl_parse_state *state) static bool texture_query_lod(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && state->ARB_texture_query_lod_enable; } @@ -292,7 +292,7 @@ texture_gather_only(const _mesa_glsl_parse_state *state) static bool fs_oes_derivatives(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && (state->is_version(110, 300) || state->OES_standard_derivatives_enable); } @@ -318,7 +318,7 @@ tex3d(const _mesa_glsl_parse_state *state) static bool fs_tex3d(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && (!state->es_shader || state->OES_texture_3D_enable); } @@ -357,8 +357,6 @@ public: ir_function_signature *find(_mesa_glsl_parse_state *state, const char *name, exec_list *actual_parameters); -private: - void *mem_ctx; /** * A shader to hold all the built-in signatures; created by this module. * @@ -368,6 +366,9 @@ private: */ gl_shader *shader; +private: + void *mem_ctx; + /** Global variables used by built-in functions. */ ir_variable *gl_ModelViewProjectionMatrix; ir_variable *gl_Vertex; @@ -608,8 +609,7 @@ builtin_builder::find(_mesa_glsl_parse_state *state, * that the "no matching signature" error will list potential candidates * from the available built-ins. */ - state->builtins_to_link[0] = shader; - state->num_builtins_to_link = 1; + state->uses_builtin_functions = true; ir_function *f = shader->symbols->get_function(name); if (f == NULL) @@ -4020,4 +4020,11 @@ _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, { return builtins.find(state, name, actual_parameters); } + +gl_shader * +_mesa_glsl_get_builtin_function_shader() +{ + return builtins.shader; +} + /** @} */ diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index d57324c2f..ff9acb8d0 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -332,6 +332,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type, this->fields[this->num_fields].location = slot; this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE; this->fields[this->num_fields].centroid = 0; + this->fields[this->num_fields].sample = 0; this->num_fields++; } @@ -434,14 +435,14 @@ builtin_variable_generator::add_variable(const char *name, enum ir_variable_mode mode, int slot) { ir_variable *var = new(symtab) ir_variable(type, name, mode); - var->how_declared = ir_var_declared_implicitly; + var->data.how_declared = ir_var_declared_implicitly; - switch (var->mode) { + switch (var->data.mode) { case ir_var_auto: case ir_var_shader_in: case ir_var_uniform: case ir_var_system_value: - var->read_only = true; + var->data.read_only = true; break; case ir_var_shader_out: break; @@ -454,9 +455,9 @@ builtin_variable_generator::add_variable(const char *name, break; } - var->location = slot; - var->explicit_location = (slot >= 0); - var->explicit_index = 0; + var->data.location = slot; + var->data.explicit_location = (slot >= 0); + var->data.explicit_index = 0; /* Once the variable is created an initialized, add it to the symbol table * and add the declaration to the IR stream. @@ -523,7 +524,7 @@ builtin_variable_generator::add_const(const char *name, int value) ir_var_auto, -1); var->constant_value = new(var) ir_constant(value); var->constant_initializer = new(var) ir_constant(value); - var->has_initializer = true; + var->data.has_initializer = true; return var; } @@ -792,9 +793,9 @@ builtin_variable_generator::generate_gs_special_vars() */ ir_variable *var; var = add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveIDIn"); - var->interpolation = INTERP_QUALIFIER_FLAT; + var->data.interpolation = INTERP_QUALIFIER_FLAT; var = add_output(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); - var->interpolation = INTERP_QUALIFIER_FLAT; + var->data.interpolation = INTERP_QUALIFIER_FLAT; } @@ -812,7 +813,7 @@ builtin_variable_generator::generate_fs_special_vars() if (state->is_version(150, 0)) { ir_variable *var = add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); - var->interpolation = INTERP_QUALIFIER_FLAT; + var->data.interpolation = INTERP_QUALIFIER_FLAT; } /* gl_FragColor and gl_FragData were deprecated starting in desktop GLSL @@ -857,6 +858,10 @@ builtin_variable_generator::generate_fs_special_vars() */ add_output(FRAG_RESULT_SAMPLE_MASK, array(int_t, 1), "gl_SampleMask"); } + + if (state->ARB_gpu_shader5_enable) { + add_system_value(SYSTEM_VALUE_SAMPLE_MASK_IN, array(int_t, 1), "gl_SampleMaskIn"); + } } @@ -872,13 +877,13 @@ builtin_variable_generator::add_varying(int slot, const glsl_type *type, const char *name_as_gs_input) { switch (state->target) { - case geometry_shader: + case MESA_SHADER_GEOMETRY: this->per_vertex_in.add_field(slot, type, name); /* FALLTHROUGH */ - case vertex_shader: + case MESA_SHADER_VERTEX: this->per_vertex_out.add_field(slot, type, name); break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: add_input(slot, type, name); break; } @@ -896,7 +901,7 @@ builtin_variable_generator::generate_varyings() add_varying(loc, type, name, name "In") /* gl_Position and gl_PointSize are not visible from fragment shaders. */ - if (state->target != fragment_shader) { + if (state->target != MESA_SHADER_FRAGMENT) { ADD_VARYING(VARYING_SLOT_POS, vec4_t, "gl_Position"); ADD_VARYING(VARYING_SLOT_PSIZ, float_t, "gl_PointSize"); } @@ -909,7 +914,7 @@ builtin_variable_generator::generate_varyings() if (compatibility) { ADD_VARYING(VARYING_SLOT_TEX0, array(vec4_t, 0), "gl_TexCoord"); ADD_VARYING(VARYING_SLOT_FOGC, float_t, "gl_FogFragCoord"); - if (state->target == fragment_shader) { + if (state->target == MESA_SHADER_FRAGMENT) { ADD_VARYING(VARYING_SLOT_COL0, vec4_t, "gl_Color"); ADD_VARYING(VARYING_SLOT_COL1, vec4_t, "gl_SecondaryColor"); } else { @@ -921,13 +926,13 @@ builtin_variable_generator::generate_varyings() } } - if (state->target == geometry_shader) { + if (state->target == MESA_SHADER_GEOMETRY) { const glsl_type *per_vertex_in_type = this->per_vertex_in.construct_interface_instance(); add_variable("gl_in", array(per_vertex_in_type, 0), ir_var_shader_in, -1); } - if (state->target == vertex_shader || state->target == geometry_shader) { + if (state->target == MESA_SHADER_VERTEX || state->target == MESA_SHADER_GEOMETRY) { const glsl_type *per_vertex_out_type = this->per_vertex_out.construct_interface_instance(); const glsl_struct_field *fields = per_vertex_out_type->fields.structure; @@ -935,8 +940,9 @@ builtin_variable_generator::generate_varyings() ir_variable *var = add_variable(fields[i].name, fields[i].type, ir_var_shader_out, fields[i].location); - var->interpolation = fields[i].interpolation; - var->centroid = fields[i].centroid; + var->data.interpolation = fields[i].interpolation; + var->data.centroid = fields[i].centroid; + var->data.sample = fields[i].sample; var->init_interface_type(per_vertex_out_type); } } @@ -958,13 +964,13 @@ _mesa_glsl_initialize_variables(exec_list *instructions, gen.generate_varyings(); switch (state->target) { - case vertex_shader: + case MESA_SHADER_VERTEX: gen.generate_vs_special_vars(); break; - case geometry_shader: + case MESA_SHADER_GEOMETRY: gen.generate_gs_special_vars(); break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: gen.generate_fs_special_vars(); break; } diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index 822d70d6b..50875bf3b 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -520,7 +520,7 @@ readonly KEYWORD(0, 300, 0, 0, READONLY); writeonly KEYWORD(0, 300, 0, 0, WRITEONLY); resource KEYWORD(0, 300, 0, 0, RESOURCE); patch KEYWORD(0, 300, 0, 0, PATCH); -sample KEYWORD(0, 300, 0, 0, SAMPLE); +sample KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_gpu_shader5_enable, SAMPLE); subroutine KEYWORD(0, 300, 0, 0, SUBROUTINE); diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index ada3690f6..39767609d 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -1521,7 +1521,7 @@ type_qualifier: { if ($2.has_auxiliary_storage()) { _mesa_glsl_error(&@1, state, - "duplicate auxiliary storage qualifier (centroid)"); + "duplicate auxiliary storage qualifier (centroid or sample)"); } if (!state->ARB_shading_language_420pack_enable && @@ -1571,7 +1571,12 @@ auxiliary_storage_qualifier: memset(& $$, 0, sizeof($$)); $$.flags.q.centroid = 1; } - /* TODO: "sample" and "patch" also go here someday. */ + | SAMPLE + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.sample = 1; + } + /* TODO: "patch" also goes here someday. */ storage_qualifier: CONST_TOK @@ -2214,11 +2219,11 @@ basic_interface_block: * "It is illegal to have an input block in a vertex shader * or an output block in a fragment shader" */ - if ((state->target == vertex_shader) && $1.flags.q.in) { + if ((state->target == MESA_SHADER_VERTEX) && $1.flags.q.in) { _mesa_glsl_error(& @1, state, "`in' interface block is not allowed for " "a vertex shader"); - } else if ((state->target == fragment_shader) && $1.flags.q.out) { + } else if ((state->target == MESA_SHADER_FRAGMENT) && $1.flags.q.out) { _mesa_glsl_error(& @1, state, "`out' interface block is not allowed for " "a fragment shader"); @@ -2372,7 +2377,7 @@ layout_defaults: { void *ctx = state; $$ = NULL; - if (state->target != geometry_shader) { + if (state->target != MESA_SHADER_GEOMETRY) { _mesa_glsl_error(& @1, state, "input layout qualifiers only valid in " "geometry shaders"); @@ -2400,7 +2405,7 @@ layout_defaults: | layout_qualifier OUT_TOK ';' { - if (state->target != geometry_shader) { + if (state->target != MESA_SHADER_GEOMETRY) { _mesa_glsl_error(& @1, state, "out layout qualifiers only valid in " "geometry shaders"); diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index d76d94b7a..5f19368d8 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -58,9 +58,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, : ctx(_ctx), switch_state() { switch (target) { - case GL_VERTEX_SHADER: this->target = vertex_shader; break; - case GL_FRAGMENT_SHADER: this->target = fragment_shader; break; - case GL_GEOMETRY_SHADER: this->target = geometry_shader; break; + case GL_VERTEX_SHADER: this->target = MESA_SHADER_VERTEX; break; + case GL_FRAGMENT_SHADER: this->target = MESA_SHADER_FRAGMENT; break; + case GL_GEOMETRY_SHADER: this->target = MESA_SHADER_GEOMETRY; break; } this->scanner = NULL; @@ -76,7 +76,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->loop_nesting_ast = NULL; this->struct_specifier_depth = 0; - this->num_builtins_to_link = 0; + + this->uses_builtin_functions = false; /* Set default language version and extensions */ this->language_version = ctx->Const.ForceGLSLVersion ? @@ -366,12 +367,12 @@ _mesa_glsl_shader_target_name(GLenum type) * our internal enum into short stage names. */ const char * -_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target) +_mesa_glsl_shader_target_name(gl_shader_type target) { switch (target) { - case vertex_shader: return "vertex"; - case fragment_shader: return "fragment"; - case geometry_shader: return "geometry"; + case MESA_SHADER_VERTEX: return "vertex"; + case MESA_SHADER_FRAGMENT: return "fragment"; + case MESA_SHADER_GEOMETRY: return "geometry"; } assert(!"Should not get here."); @@ -877,6 +878,8 @@ _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q) if (q->flags.q.centroid) printf("centroid "); + if (q->flags.q.sample) + printf("sample "); if (q->flags.q.uniform) printf("uniform "); if (q->flags.q.smooth) @@ -1532,10 +1535,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, shader->InfoLog = state->info_log; shader->Version = state->language_version; shader->IsES = state->es_shader; - - 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; + shader->uses_builtin_functions = state->uses_builtin_functions; if (shader->UniformBlocks) ralloc_free(shader->UniformBlocks); diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index d232bb3f6..622ddbac7 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -34,12 +34,6 @@ #include <stdlib.h> #include "glsl_symbol_table.h" -enum _mesa_glsl_parser_targets { - vertex_shader, - geometry_shader, - fragment_shader -}; - struct gl_context; struct glsl_switch_state { @@ -171,7 +165,7 @@ struct _mesa_glsl_parse_state { bool es_shader; unsigned language_version; - enum _mesa_glsl_parser_targets target; + gl_shader_type target; /** * Number of nested struct_specifier levels @@ -361,9 +355,7 @@ struct _mesa_glsl_parse_state { /** Extensions supported by the OpenGL implementation. */ const struct gl_extensions *extensions; - /** Shaders containing built-in functions that are used for linking. */ - struct gl_shader *builtins_to_link[16]; - unsigned num_builtins_to_link; + bool uses_builtin_functions; /** * For geometry shaders, size of the most recently seen input declaration @@ -433,7 +425,7 @@ extern bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, * Get the textual name of the specified shader target */ extern const char * -_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target); +_mesa_glsl_shader_target_name(gl_shader_type target); #endif /* __cplusplus */ diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index f74013096..12d4ac0ee 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -103,6 +103,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].location = fields[i].location; this->fields.structure[i].interpolation = fields[i].interpolation; this->fields.structure[i].centroid = fields[i].centroid; + this->fields.structure[i].sample = fields[i].sample; this->fields.structure[i].row_major = fields[i].row_major; } } @@ -130,6 +131,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].location = fields[i].location; this->fields.structure[i].interpolation = fields[i].interpolation; this->fields.structure[i].centroid = fields[i].centroid; + this->fields.structure[i].sample = fields[i].sample; this->fields.structure[i].row_major = fields[i].row_major; } } @@ -483,6 +485,9 @@ glsl_type::record_key_compare(const void *a, const void *b) if (key1->fields.structure[i].centroid != key2->fields.structure[i].centroid) return 1; + if (key1->fields.structure[i].sample + != key2->fields.structure[i].sample) + return 1; } return 0; diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 96eee5e64..fb7c9288d 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -634,6 +634,12 @@ struct glsl_struct_field { * in ir_variable::centroid). 0 otherwise. */ unsigned centroid:1; + + /** + * For interface blocks, 1 if this variable uses sample interpolation (as + * in ir_variable::sample). 0 otherwise. + */ + unsigned sample:1; }; static inline unsigned int diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index ffff2976a..04a7b874a 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1277,11 +1277,6 @@ ir_constant::is_basis() const ir_loop::ir_loop() { this->ir_type = ir_type_loop; - this->cmp = ir_unop_neg; - this->from = NULL; - this->to = NULL; - this->increment = NULL; - this->counter = NULL; } @@ -1364,7 +1359,7 @@ ir_dereference::is_lvalue() const /* Every l-value derference chain eventually ends in a variable. */ - if ((var == NULL) || var->read_only) + if ((var == NULL) || var->data.read_only) return false; /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: @@ -1584,29 +1579,36 @@ ir_swizzle::variable_referenced() const ir_variable::ir_variable(const struct glsl_type *type, const char *name, ir_variable_mode mode) - : max_array_access(0), max_ifc_array_access(NULL), - read_only(false), centroid(false), invariant(false), - how_declared(ir_var_declared_normally), mode(mode), - interpolation(INTERP_QUALIFIER_NONE), atomic() + : max_ifc_array_access(NULL) { this->ir_type = ir_type_variable; this->type = type; this->name = ralloc_strdup(this, name); - this->explicit_location = false; - this->has_initializer = false; - this->location = -1; - this->location_frac = 0; + this->data.explicit_location = false; + this->data.has_initializer = false; + this->data.location = -1; + this->data.location_frac = 0; this->warn_extension = NULL; this->constant_value = NULL; this->constant_initializer = NULL; - this->origin_upper_left = false; - this->pixel_center_integer = false; - this->depth_layout = ir_depth_layout_none; - this->used = false; + this->data.origin_upper_left = false; + this->data.pixel_center_integer = false; + this->data.depth_layout = ir_depth_layout_none; + this->data.used = false; + this->data.read_only = false; + this->data.centroid = false; + this->data.sample = false; + this->data.invariant = false; + this->data.how_declared = ir_var_declared_normally; + this->data.mode = mode; + this->data.interpolation = INTERP_QUALIFIER_NONE; + this->data.max_array_access = 0; + this->data.atomic.buffer_index = 0; + this->data.atomic.offset = 0; if (type != NULL) { if (type->base_type == GLSL_TYPE_SAMPLER) - this->read_only = true; + this->data.read_only = true; if (type->is_interface()) this->init_interface_type(type); @@ -1634,9 +1636,9 @@ interpolation_string(unsigned interpolation) glsl_interp_qualifier ir_variable::determine_interpolation_mode(bool flat_shade) { - if (this->interpolation != INTERP_QUALIFIER_NONE) - return (glsl_interp_qualifier) this->interpolation; - int location = this->location; + if (this->data.interpolation != INTERP_QUALIFIER_NONE) + return (glsl_interp_qualifier) this->data.interpolation; + int location = this->data.location; bool is_gl_Color = location == VARYING_SLOT_COL0 || location == VARYING_SLOT_COL1; if (flat_shade && is_gl_Color) @@ -1706,10 +1708,11 @@ ir_function_signature::qualifiers_match(exec_list *params) ir_variable *a = (ir_variable *)iter_a.get(); ir_variable *b = (ir_variable *)iter_b.get(); - if (a->read_only != b->read_only || - !modes_match(a->mode, b->mode) || - a->interpolation != b->interpolation || - a->centroid != b->centroid) { + if (a->data.read_only != b->data.read_only || + !modes_match(a->data.mode, b->data.mode) || + a->data.interpolation != b->data.interpolation || + a->data.centroid != b->data.centroid || + a->data.sample != b->data.sample) { /* parameter a's qualifiers don't match */ return a->name; @@ -1729,12 +1732,6 @@ ir_function_signature::replace_parameters(exec_list *new_params) * parameter information comes from the function prototype, it may either * specify incorrect parameter names or not have names at all. */ - foreach_iter(exec_list_iterator, iter, parameters) { - assert(((ir_instruction *) iter.get())->as_variable() != NULL); - - iter.remove(); - } - new_params->move_nodes_to(¶meters); } @@ -1899,9 +1896,9 @@ vertices_per_prim(GLenum prim) const char * mode_string(const ir_variable *var) { - switch (var->mode) { + switch (var->data.mode) { case ir_var_auto: - return (var->read_only) ? "global constant" : "global variable"; + return (var->data.read_only) ? "global constant" : "global variable"; case ir_var_uniform: return "uniform"; diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 4f775da4b..780959b73 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -86,6 +86,7 @@ enum ir_node_type { ir_type_max /**< maximum ir_type enum number, for validation */ }; + /** * Base class of all IR instructions */ @@ -402,7 +403,7 @@ public: */ inline bool is_in_uniform_block() const { - return this->mode == ir_var_uniform && this->interface_type != NULL; + return this->data.mode == ir_var_uniform && this->interface_type != NULL; } /** @@ -502,13 +503,6 @@ public: const char *name; /** - * Highest element accessed with a constant expression array index - * - * Not used for non-array variables. - */ - unsigned max_array_access; - - /** * For variables which satisfy the is_interface_instance() predicate, this * points to an array of integers such that if the ith member of the * interface block is an array, max_ifc_array_access[i] is the maximum @@ -521,177 +515,189 @@ public: */ unsigned *max_ifc_array_access; - /** - * Is the variable read-only? - * - * This is set for variables declared as \c const, shader inputs, - * and uniforms. - */ - unsigned read_only:1; - unsigned centroid:1; - unsigned invariant:1; - - /** - * Has this variable been used for reading or writing? - * - * Several GLSL semantic checks require knowledge of whether or not a - * variable has been used. For example, it is an error to redeclare a - * variable as invariant after it has been used. - * - * This is only maintained in the ast_to_hir.cpp path, not in - * Mesa's fixed function or ARB program paths. - */ - unsigned used:1; - - /** - * Has this variable been statically assigned? - * - * This answers whether the variable was assigned in any path of - * the shader during ast_to_hir. This doesn't answer whether it is - * still written after dead code removal, nor is it maintained in - * non-ast_to_hir.cpp (GLSL parsing) paths. - */ - unsigned assigned:1; - - /** - * Enum indicating how the variable was declared. See - * ir_var_declaration_type. - * - * This is used to detect certain kinds of illegal variable redeclarations. - */ - unsigned how_declared:2; - - /** - * Storage class of the variable. - * - * \sa ir_variable_mode - */ - unsigned mode:4; - - /** - * Interpolation mode for shader inputs / outputs - * - * \sa ir_variable_interpolation - */ - unsigned interpolation:2; - - /** - * \name ARB_fragment_coord_conventions - * @{ - */ - unsigned origin_upper_left:1; - unsigned pixel_center_integer:1; - /*@}*/ + struct ir_variable_data { - /** - * Was the location explicitly set in the shader? - * - * If the location is explicitly set in the shader, it \b cannot be changed - * by the linker or by the API (e.g., calls to \c glBindAttribLocation have - * no effect). - */ - unsigned explicit_location:1; - unsigned explicit_index:1; - - /** - * Was an initial binding explicitly set in the shader? - * - * If so, constant_value contains an integer ir_constant representing the - * initial binding point. - */ - unsigned explicit_binding:1; + /** + * Is the variable read-only? + * + * This is set for variables declared as \c const, shader inputs, + * and uniforms. + */ + unsigned read_only:1; + unsigned centroid:1; + unsigned sample:1; + unsigned invariant:1; + + /** + * Has this variable been used for reading or writing? + * + * Several GLSL semantic checks require knowledge of whether or not a + * variable has been used. For example, it is an error to redeclare a + * variable as invariant after it has been used. + * + * This is only maintained in the ast_to_hir.cpp path, not in + * Mesa's fixed function or ARB program paths. + */ + unsigned used:1; + + /** + * Has this variable been statically assigned? + * + * This answers whether the variable was assigned in any path of + * the shader during ast_to_hir. This doesn't answer whether it is + * still written after dead code removal, nor is it maintained in + * non-ast_to_hir.cpp (GLSL parsing) paths. + */ + unsigned assigned:1; - /** - * Does this variable have an initializer? - * - * This is used by the linker to cross-validiate initializers of global - * variables. - */ - unsigned has_initializer:1; + /** + * Enum indicating how the variable was declared. See + * ir_var_declaration_type. + * + * This is used to detect certain kinds of illegal variable redeclarations. + */ + unsigned how_declared:2; - /** - * Is this variable a generic output or input that has not yet been matched - * up to a variable in another stage of the pipeline? - * - * This is used by the linker as scratch storage while assigning locations - * to generic inputs and outputs. - */ - unsigned is_unmatched_generic_inout:1; + /** + * Storage class of the variable. + * + * \sa ir_variable_mode + */ + unsigned mode:4; - /** - * If non-zero, then this variable may be packed along with other variables - * into a single varying slot, so this offset should be applied when - * accessing components. For example, an offset of 1 means that the x - * component of this variable is actually stored in component y of the - * location specified by \c location. - */ - unsigned location_frac:2; + /** + * Interpolation mode for shader inputs / outputs + * + * \sa ir_variable_interpolation + */ + unsigned interpolation:2; - /** - * Non-zero if this variable was created by lowering a named interface - * block which was not an array. - * - * Note that this variable and \c from_named_ifc_block_array will never - * both be non-zero. - */ - unsigned from_named_ifc_block_nonarray:1; + /** + * \name ARB_fragment_coord_conventions + * @{ + */ + unsigned origin_upper_left:1; + unsigned pixel_center_integer:1; + /*@}*/ + + /** + * Was the location explicitly set in the shader? + * + * If the location is explicitly set in the shader, it \b cannot be changed + * by the linker or by the API (e.g., calls to \c glBindAttribLocation have + * no effect). + */ + unsigned explicit_location:1; + unsigned explicit_index:1; + + /** + * Was an initial binding explicitly set in the shader? + * + * If so, constant_value contains an integer ir_constant representing the + * initial binding point. + */ + unsigned explicit_binding:1; - /** - * Non-zero if this variable was created by lowering a named interface - * block which was an array. - * - * Note that this variable and \c from_named_ifc_block_nonarray will never - * both be non-zero. - */ - unsigned from_named_ifc_block_array:1; + /** + * Does this variable have an initializer? + * + * This is used by the linker to cross-validiate initializers of global + * variables. + */ + unsigned has_initializer:1; + + /** + * Is this variable a generic output or input that has not yet been matched + * up to a variable in another stage of the pipeline? + * + * This is used by the linker as scratch storage while assigning locations + * to generic inputs and outputs. + */ + unsigned is_unmatched_generic_inout:1; + + /** + * If non-zero, then this variable may be packed along with other variables + * into a single varying slot, so this offset should be applied when + * accessing components. For example, an offset of 1 means that the x + * component of this variable is actually stored in component y of the + * location specified by \c location. + */ + unsigned location_frac:2; + + /** + * Non-zero if this variable was created by lowering a named interface + * block which was not an array. + * + * Note that this variable and \c from_named_ifc_block_array will never + * both be non-zero. + */ + unsigned from_named_ifc_block_nonarray:1; + + /** + * Non-zero if this variable was created by lowering a named interface + * block which was an array. + * + * Note that this variable and \c from_named_ifc_block_nonarray will never + * both be non-zero. + */ + unsigned from_named_ifc_block_array:1; - /** - * \brief Layout qualifier for gl_FragDepth. - * - * This is not equal to \c ir_depth_layout_none if and only if this - * variable is \c gl_FragDepth and a layout qualifier is specified. - */ - ir_depth_layout depth_layout; + /** + * \brief Layout qualifier for gl_FragDepth. + * + * This is not equal to \c ir_depth_layout_none if and only if this + * variable is \c gl_FragDepth and a layout qualifier is specified. + */ + ir_depth_layout depth_layout; + + /** + * Storage location of the base of this variable + * + * The precise meaning of this field depends on the nature of the variable. + * + * - Vertex shader input: one of the values from \c gl_vert_attrib. + * - Vertex shader output: one of the values from \c gl_varying_slot. + * - Geometry shader input: one of the values from \c gl_varying_slot. + * - Geometry shader output: one of the values from \c gl_varying_slot. + * - Fragment shader input: one of the values from \c gl_varying_slot. + * - Fragment shader output: one of the values from \c gl_frag_result. + * - Uniforms: Per-stage uniform slot number for default uniform block. + * - Uniforms: Index within the uniform block definition for UBO members. + * - Other: This field is not currently used. + * + * If the variable is a uniform, shader input, or shader output, and the + * slot has not been assigned, the value will be -1. + */ + int location; - /** - * Storage location of the base of this variable - * - * The precise meaning of this field depends on the nature of the variable. - * - * - Vertex shader input: one of the values from \c gl_vert_attrib. - * - Vertex shader output: one of the values from \c gl_varying_slot. - * - Geometry shader input: one of the values from \c gl_varying_slot. - * - Geometry shader output: one of the values from \c gl_varying_slot. - * - Fragment shader input: one of the values from \c gl_varying_slot. - * - Fragment shader output: one of the values from \c gl_frag_result. - * - Uniforms: Per-stage uniform slot number for default uniform block. - * - Uniforms: Index within the uniform block definition for UBO members. - * - Other: This field is not currently used. - * - * If the variable is a uniform, shader input, or shader output, and the - * slot has not been assigned, the value will be -1. - */ - int location; + /** + * output index for dual source blending. + */ + int index; - /** - * output index for dual source blending. - */ - int index; + /** + * Initial binding point for a sampler or UBO. + * + * For array types, this represents the binding point for the first element. + */ + int binding; - /** - * Initial binding point for a sampler or UBO. - * - * For array types, this represents the binding point for the first element. - */ - int binding; + /** + * Location an atomic counter is stored at. + */ + struct { + unsigned buffer_index; + unsigned offset; + } atomic; + + /** + * Highest element accessed with a constant expression array index + * + * Not used for non-array variables. + */ + unsigned max_array_access; - /** - * Location an atomic counter is stored at. - */ - struct { - unsigned buffer_index; - unsigned offset; - } atomic; + } data; /** * Built-in state that backs this uniform @@ -1022,34 +1028,6 @@ public: /** List of ir_instruction that make up the body of the loop. */ exec_list body_instructions; - - /** - * \name Loop counter and controls - * - * Represents a loop like a FORTRAN \c do-loop. - * - * \note - * If \c from and \c to are the same value, the loop will execute once. - */ - /*@{*/ - ir_rvalue *from; /** Value of the loop counter on the first - * iteration of the loop. - */ - ir_rvalue *to; /** Value of the loop counter on the last - * iteration of the loop. - */ - ir_rvalue *increment; - ir_variable *counter; - - /** - * Comparison operation in the loop terminator. - * - * If any of the loop control fields are non-\c NULL, this field must be - * one of \c ir_binop_less, \c ir_binop_greater, \c ir_binop_lequal, - * \c ir_binop_gequal, \c ir_binop_equal, or \c ir_binop_nequal. - */ - int cmp; - /*@}*/ }; @@ -2344,6 +2322,9 @@ extern ir_function_signature * _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, const char *name, exec_list *actual_parameters); +extern gl_shader * +_mesa_glsl_get_builtin_function_shader(void); + extern void _mesa_glsl_release_functions(void); diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index 40ed33afc..4e5cf68ca 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -41,35 +41,19 @@ ir_variable * ir_variable::clone(void *mem_ctx, struct hash_table *ht) const { ir_variable *var = new(mem_ctx) ir_variable(this->type, this->name, - (ir_variable_mode) this->mode); + (ir_variable_mode) this->data.mode); - var->max_array_access = this->max_array_access; + var->data.max_array_access = this->data.max_array_access; if (this->is_interface_instance()) { var->max_ifc_array_access = rzalloc_array(var, unsigned, this->interface_type->length); memcpy(var->max_ifc_array_access, this->max_ifc_array_access, this->interface_type->length * sizeof(unsigned)); } - var->read_only = this->read_only; - var->centroid = this->centroid; - var->invariant = this->invariant; - var->interpolation = this->interpolation; - var->location = this->location; - var->index = this->index; - var->binding = this->binding; - var->atomic.buffer_index = this->atomic.buffer_index; - var->atomic.offset = this->atomic.offset; + + memcpy(&var->data, &this->data, sizeof(var->data)); + var->warn_extension = this->warn_extension; - var->origin_upper_left = this->origin_upper_left; - var->pixel_center_integer = this->pixel_center_integer; - var->explicit_location = this->explicit_location; - var->explicit_index = this->explicit_index; - var->explicit_binding = this->explicit_binding; - var->has_initializer = this->has_initializer; - var->depth_layout = this->depth_layout; - var->assigned = this->assigned; - var->how_declared = this->how_declared; - var->used = this->used; var->num_state_slots = this->num_state_slots; if (this->state_slots) { @@ -157,20 +141,11 @@ ir_loop::clone(void *mem_ctx, struct hash_table *ht) const { ir_loop *new_loop = new(mem_ctx) ir_loop(); - if (this->from) - new_loop->from = this->from->clone(mem_ctx, ht); - if (this->to) - new_loop->to = this->to->clone(mem_ctx, ht); - if (this->increment) - new_loop->increment = this->increment->clone(mem_ctx, ht); - new_loop->counter = counter; - foreach_iter(exec_list_iterator, iter, this->body_instructions) { ir_instruction *ir = (ir_instruction *)iter.get(); new_loop->body_instructions.push_tail(ir->clone(mem_ctx, ht)); } - new_loop->cmp = this->cmp; return new_loop; } diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index 0efd1d5b3..7ca865e22 100644 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -1583,7 +1583,7 @@ ir_dereference_variable::constant_expression_value(struct hash_table *variable_c /* The constant_value of a uniform variable is its initializer, * not the lifetime constant value of the uniform. */ - if (var->mode == ir_var_uniform) + if (var->data.mode == ir_var_uniform) return NULL; if (!var->constant_value) diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp index 53cf469d9..bd5318d23 100644 --- a/mesalib/src/glsl/ir_function.cpp +++ b/mesalib/src/glsl/ir_function.cpp @@ -66,7 +66,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) /* Try to find an implicit conversion from actual to param. */ inexact_match = true; - switch ((enum ir_variable_mode)(param->mode)) { + switch ((enum ir_variable_mode)(param->data.mode)) { case ir_var_auto: case ir_var_uniform: case ir_var_temporary: diff --git a/mesalib/src/glsl/ir_hv_accept.cpp b/mesalib/src/glsl/ir_hv_accept.cpp index 941b25e97..2a1f70e5b 100644 --- a/mesalib/src/glsl/ir_hv_accept.cpp +++ b/mesalib/src/glsl/ir_hv_accept.cpp @@ -91,26 +91,6 @@ ir_loop::accept(ir_hierarchical_visitor *v) if (s == visit_stop) return s; - if (s != visit_continue_with_parent) { - if (this->from) { - s = this->from->accept(v); - if (s != visit_continue) - return (s == visit_continue_with_parent) ? visit_continue : s; - } - - if (this->to) { - s = this->to->accept(v); - if (s != visit_continue) - return (s == visit_continue_with_parent) ? visit_continue : s; - } - - if (this->increment) { - s = this->increment->accept(v); - if (s != visit_continue) - return (s == visit_continue_with_parent) ? visit_continue : s; - } - } - return v->visit_leave(this); } diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp index f85e573c4..01c5f7f1c 100644 --- a/mesalib/src/glsl/ir_print_visitor.cpp +++ b/mesalib/src/glsl/ir_print_visitor.cpp @@ -148,8 +148,9 @@ void ir_print_visitor::visit(ir_variable *ir) { printf("(declare "); - const char *const cent = (ir->centroid) ? "centroid " : ""; - const char *const inv = (ir->invariant) ? "invariant " : ""; + const char *const cent = (ir->data.centroid) ? "centroid " : ""; + const char *const samp = (ir->data.sample) ? "sample " : ""; + const char *const inv = (ir->data.invariant) ? "invariant " : ""; const char *const mode[] = { "", "uniform ", "shader_in ", "shader_out ", "in ", "out ", "inout ", "const_in ", "sys ", "temporary " }; @@ -157,8 +158,8 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const interp[] = { "", "smooth", "flat", "noperspective" }; STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT); - printf("(%s%s%s%s) ", - cent, inv, mode[ir->mode], interp[ir->interpolation]); + printf("(%s%s%s%s%s) ", + cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]); print_type(ir->type); printf(" %s)", unique_name(ir)); @@ -416,9 +417,9 @@ void ir_print_visitor::visit(ir_constant *ir) if (ir->value.f[i] == 0.0f) /* 0.0 == -0.0, so print with %f to get the proper sign. */ printf("%.1f", ir->value.f[i]); - else if (abs(ir->value.f[i]) < 0.000001f) + else if (fabs(ir->value.f[i]) < 0.000001f) printf("%a", ir->value.f[i]); - else if (abs(ir->value.f[i]) > 1000000.0f) + else if (fabs(ir->value.f[i]) > 1000000.0f) printf("%e", ir->value.f[i]); else printf("%f", ir->value.f[i]); @@ -522,19 +523,7 @@ ir_print_visitor::visit(ir_if *ir) void ir_print_visitor::visit(ir_loop *ir) { - printf("(loop ("); - if (ir->counter != NULL) - ir->counter->accept(this); - printf(") ("); - if (ir->from != NULL) - ir->from->accept(this); - printf(") ("); - if (ir->to != NULL) - ir->to->accept(this); - printf(") ("); - if (ir->increment != NULL) - ir->increment->accept(this); - printf(") (\n"); + printf("(loop (\n"); indentation++; foreach_iter(exec_list_iterator, iter, ir->body_instructions) { diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 00e2db9a3..7970112ec 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -412,33 +412,35 @@ ir_reader::read_declaration(s_expression *expr) // FINISHME: Check for duplicate/conflicting qualifiers. if (strcmp(qualifier->value(), "centroid") == 0) { - var->centroid = 1; + var->data.centroid = 1; + } else if (strcmp(qualifier->value(), "sample") == 0) { + var->data.sample = 1; } else if (strcmp(qualifier->value(), "invariant") == 0) { - var->invariant = 1; + var->data.invariant = 1; } else if (strcmp(qualifier->value(), "uniform") == 0) { - var->mode = ir_var_uniform; + var->data.mode = ir_var_uniform; } else if (strcmp(qualifier->value(), "auto") == 0) { - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; } else if (strcmp(qualifier->value(), "in") == 0) { - var->mode = ir_var_function_in; + var->data.mode = ir_var_function_in; } else if (strcmp(qualifier->value(), "shader_in") == 0) { - var->mode = ir_var_shader_in; + var->data.mode = ir_var_shader_in; } else if (strcmp(qualifier->value(), "const_in") == 0) { - var->mode = ir_var_const_in; + var->data.mode = ir_var_const_in; } else if (strcmp(qualifier->value(), "out") == 0) { - var->mode = ir_var_function_out; + var->data.mode = ir_var_function_out; } else if (strcmp(qualifier->value(), "shader_out") == 0) { - var->mode = ir_var_shader_out; + var->data.mode = ir_var_shader_out; } else if (strcmp(qualifier->value(), "inout") == 0) { - var->mode = ir_var_function_inout; + var->data.mode = ir_var_function_inout; } else if (strcmp(qualifier->value(), "temporary") == 0) { - var->mode = ir_var_temporary; + var->data.mode = ir_var_temporary; } else if (strcmp(qualifier->value(), "smooth") == 0) { - var->interpolation = INTERP_QUALIFIER_SMOOTH; + var->data.interpolation = INTERP_QUALIFIER_SMOOTH; } else if (strcmp(qualifier->value(), "flat") == 0) { - var->interpolation = INTERP_QUALIFIER_FLAT; + var->data.interpolation = INTERP_QUALIFIER_FLAT; } else if (strcmp(qualifier->value(), "noperspective") == 0) { - var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; + var->data.interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; } else { ir_read_error(expr, "unknown qualifier: %s", qualifier->value()); return NULL; @@ -486,18 +488,16 @@ ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx) ir_loop * ir_reader::read_loop(s_expression *expr) { - s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body; + s_expression *s_body; - s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (loop <counter> <from> <to> " - "<increment> <body>)"); + s_pattern loop_pat[] = { "loop", s_body }; + if (!MATCH(expr, loop_pat)) { + ir_read_error(expr, "expected (loop <body>)"); return NULL; } - // FINISHME: actually read the count/from/to fields. - ir_loop *loop = new(mem_ctx) ir_loop; + read_instructions(&loop->body_instructions, s_body, loop); if (state->error) { delete loop; diff --git a/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp index ab23538c3..0b49eb2b6 100644 --- a/mesalib/src/glsl/ir_set_program_inouts.cpp +++ b/mesalib/src/glsl/ir_set_program_inouts.cpp @@ -27,7 +27,7 @@ * Sets the InputsRead and OutputsWritten of Mesa programs. * * Additionally, for fragment shaders, sets the InterpQualifier array, the - * IsCentroid bitfield, and the UsesDFdy flag. + * IsCentroid and IsSample bitfields, and the UsesDFdy flag. * * Mesa programs (gl_program, not gl_shader_program) have a set of * flags indicating which varyings are read and written. Computing @@ -75,9 +75,9 @@ private: static inline bool is_shader_inout(ir_variable *var) { - return var->mode == ir_var_shader_in || - var->mode == ir_var_shader_out || - var->mode == ir_var_system_value; + return var->data.mode == ir_var_shader_in || + var->data.mode == ir_var_shader_out || + var->data.mode == ir_var_system_value; } static void @@ -93,20 +93,24 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len, */ for (int i = 0; i < len; i++) { - GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i); - if (var->mode == ir_var_shader_in) { + GLbitfield64 bitfield = + BITFIELD64_BIT(var->data.location + var->data.index + offset + i); + if (var->data.mode == ir_var_shader_in) { prog->InputsRead |= bitfield; if (is_fragment_shader) { gl_fragment_program *fprog = (gl_fragment_program *) prog; - fprog->InterpQualifier[var->location + var->index + offset + i] = - (glsl_interp_qualifier) var->interpolation; - if (var->centroid) + fprog->InterpQualifier[var->data.location + + var->data.index + offset + i] = + (glsl_interp_qualifier) var->data.interpolation; + if (var->data.centroid) fprog->IsCentroid |= bitfield; + if (var->data.sample) + fprog->IsSample |= bitfield; } - } else if (var->mode == ir_var_system_value) { + } else if (var->data.mode == ir_var_system_value) { prog->SystemValuesRead |= bitfield; } else { - assert(var->mode == ir_var_shader_out); + assert(var->data.mode == ir_var_shader_out); prog->OutputsWritten |= bitfield; } } @@ -121,7 +125,7 @@ ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var) { const glsl_type *type = var->type; if (this->shader_type == GL_GEOMETRY_SHADER && - var->mode == ir_var_shader_in && type->is_array()) { + var->data.mode == ir_var_shader_in && type->is_array()) { type = type->fields.array; } @@ -160,7 +164,7 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var, const glsl_type *type = var->type; if (this->shader_type == GL_GEOMETRY_SHADER && - var->mode == ir_var_shader_in) { + var->data.mode == ir_var_shader_in) { /* The only geometry shader input that is not an array is * gl_PrimitiveIDIn, and in that case, this code will never be reached, * because gl_PrimitiveIDIn can't be indexed into in array fashion. @@ -242,7 +246,7 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) if (ir_dereference_variable * const deref_var = inner_array->array->as_dereference_variable()) { if (this->shader_type == GL_GEOMETRY_SHADER && - deref_var->var->mode == ir_var_shader_in) { + deref_var->var->data.mode == ir_var_shader_in) { /* foo is a geometry shader input, so i is the vertex, and j the * part of the input we're accessing. */ @@ -261,7 +265,7 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) ir->array->as_dereference_variable()) { /* ir => foo[i], where foo is a variable. */ if (this->shader_type == GL_GEOMETRY_SHADER && - deref_var->var->mode == ir_var_shader_in) { + deref_var->var->data.mode == ir_var_shader_in) { /* foo is a geometry shader input, so i is the vertex, and we're * accessing the entire input. */ @@ -341,6 +345,7 @@ do_set_program_inouts(exec_list *instructions, struct gl_program *prog, gl_fragment_program *fprog = (gl_fragment_program *) prog; memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier)); fprog->IsCentroid = 0; + fprog->IsSample = 0; fprog->UsesDFdy = false; fprog->UsesKill = false; } diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp index 13e41a089..4bbb3ce65 100644 --- a/mesalib/src/glsl/ir_validate.cpp +++ b/mesalib/src/glsl/ir_validate.cpp @@ -63,7 +63,6 @@ public: virtual ir_visitor_status visit_enter(ir_if *ir); - virtual ir_visitor_status visit_leave(ir_loop *ir); virtual ir_visitor_status visit_enter(ir_function *ir); virtual ir_visitor_status visit_leave(ir_function *ir); virtual ir_visitor_status visit_enter(ir_function_signature *ir); @@ -149,42 +148,6 @@ ir_validate::visit_enter(ir_if *ir) ir_visitor_status -ir_validate::visit_leave(ir_loop *ir) -{ - if (ir->counter != NULL) { - if ((ir->from == NULL) || (ir->to == NULL) || (ir->increment == NULL)) { - printf("ir_loop has invalid loop controls:\n" - " counter: %p\n" - " from: %p\n" - " to: %p\n" - " increment: %p\n", - (void *) ir->counter, (void *) ir->from, (void *) ir->to, - (void *) ir->increment); - abort(); - } - - if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) { - printf("ir_loop has invalid comparitor %d\n", ir->cmp); - abort(); - } - } else { - if ((ir->from != NULL) || (ir->to != NULL) || (ir->increment != NULL)) { - printf("ir_loop has invalid loop controls:\n" - " counter: %p\n" - " from: %p\n" - " to: %p\n" - " increment: %p\n", - (void *) ir->counter, (void *) ir->from, (void *) ir->to, - (void *) ir->increment); - abort(); - } - } - - return visit_continue; -} - - -ir_visitor_status ir_validate::visit_enter(ir_function *ir) { /* Function definitions cannot be nested. @@ -679,9 +642,9 @@ ir_validate::visit(ir_variable *ir) * to be out of bounds. */ if (ir->type->array_size() > 0) { - if (ir->max_array_access >= ir->type->length) { + if (ir->data.max_array_access >= ir->type->length) { printf("ir_variable has maximum access out of bounds (%d vs %d)\n", - ir->max_array_access, ir->type->length - 1); + ir->data.max_array_access, ir->type->length - 1); ir->print(); abort(); } @@ -707,7 +670,7 @@ ir_validate::visit(ir_variable *ir) } } - if (ir->constant_initializer != NULL && !ir->has_initializer) { + if (ir->constant_initializer != NULL && !ir->data.has_initializer) { printf("ir_variable didn't have an initializer, but has a constant " "initializer value.\n"); ir->print(); @@ -789,8 +752,8 @@ ir_validate::visit_enter(ir_call *ir) printf("ir_call parameter type mismatch:\n"); goto dump_ir; } - if (formal_param->mode == ir_var_function_out - || formal_param->mode == ir_var_function_inout) { + if (formal_param->data.mode == ir_var_function_out + || formal_param->data.mode == ir_var_function_inout) { if (!actual_param->is_lvalue()) { printf("ir_call out/inout parameters must be lvalues:\n"); goto dump_ir; diff --git a/mesalib/src/glsl/link_atomics.cpp b/mesalib/src/glsl/link_atomics.cpp index 2466bbd79..33903ad54 100644 --- a/mesalib/src/glsl/link_atomics.cpp +++ b/mesalib/src/glsl/link_atomics.cpp @@ -73,16 +73,16 @@ namespace { const active_atomic_counter *const first = (active_atomic_counter *) a; const active_atomic_counter *const second = (active_atomic_counter *) b; - return int(first->var->atomic.offset) - int(second->var->atomic.offset); + return int(first->var->data.atomic.offset) - int(second->var->data.atomic.offset); } bool check_atomic_counters_overlap(const ir_variable *x, const ir_variable *y) { - return ((x->atomic.offset >= y->atomic.offset && - x->atomic.offset < y->atomic.offset + y->type->atomic_size()) || - (y->atomic.offset >= x->atomic.offset && - y->atomic.offset < x->atomic.offset + x->type->atomic_size())); + return ((x->data.atomic.offset >= y->data.atomic.offset && + x->data.atomic.offset < y->data.atomic.offset + y->type->atomic_size()) || + (y->data.atomic.offset >= x->data.atomic.offset && + y->data.atomic.offset < x->data.atomic.offset + x->type->atomic_size())); } active_atomic_buffer * @@ -107,7 +107,7 @@ namespace { unsigned id; bool found = prog->UniformHash->get(id, var->name); assert(found); - active_atomic_buffer *buf = &buffers[var->binding]; + active_atomic_buffer *buf = &buffers[var->data.binding]; /* If this is the first time the buffer is used, increment * the counter of buffers used. @@ -118,7 +118,7 @@ namespace { buf->push_back(id, var); buf->stage_references[i]++; - buf->size = MAX2(buf->size, var->atomic.offset + + buf->size = MAX2(buf->size, var->data.atomic.offset + var->type->atomic_size()); } } @@ -143,7 +143,7 @@ namespace { linker_error(prog, "Atomic counter %s declared at offset %d " "which is already in use.", buffers[i].counters[j].var->name, - buffers[i].counters[j].var->atomic.offset); + buffers[i].counters[j].var->data.atomic.offset); } } } @@ -190,9 +190,9 @@ link_assign_atomic_counter_resources(struct gl_context *ctx, gl_uniform_storage *const storage = &prog->UniformStorage[id]; mab.Uniforms[j] = id; - var->atomic.buffer_index = i; + var->data.atomic.buffer_index = i; storage->atomic_buffer_index = i; - storage->offset = var->atomic.offset; + storage->offset = var->data.atomic.offset; storage->array_stride = (var->type->is_array() ? var->type->element_type()->atomic_size() : 0); } diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp index 68aa62032..56f3f207e 100644 --- a/mesalib/src/glsl/link_functions.cpp +++ b/mesalib/src/glsl/link_functions.cpp @@ -201,8 +201,9 @@ public: if (formal_param->type->is_array()) { ir_dereference_variable *deref = actual_param->as_dereference_variable(); if (deref && deref->var && deref->var->type->is_array()) { - deref->var->max_array_access = - MAX2(formal_param->max_array_access, deref->var->max_array_access); + deref->var->data.max_array_access = + MAX2(formal_param->data.max_array_access, + deref->var->data.max_array_access); } } } @@ -234,8 +235,9 @@ public: * we need to track the maximal access to the array as linking * pulls more functions in that access the array. */ - var->max_array_access = - MAX2(var->max_array_access, ir->var->max_array_access); + var->data.max_array_access = + MAX2(var->data.max_array_access, + ir->var->data.max_array_access); if (var->type->length == 0 && ir->var->type->length != 0) var->type = ir->var->type; diff --git a/mesalib/src/glsl/link_interface_blocks.cpp b/mesalib/src/glsl/link_interface_blocks.cpp index 6900fa94e..476963642 100644 --- a/mesalib/src/glsl/link_interface_blocks.cpp +++ b/mesalib/src/glsl/link_interface_blocks.cpp @@ -60,7 +60,7 @@ struct interface_block_definition if (var->type->is_array()) array_size = var->type->length; } - explicitly_declared = (var->how_declared != ir_var_declared_implicitly); + explicitly_declared = (var->data.how_declared != ir_var_declared_implicitly); } /** @@ -270,7 +270,7 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog, continue; interface_block_definitions *definitions; - switch (var->mode) { + switch (var->data.mode) { case ir_var_shader_in: definitions = &in_interfaces; break; @@ -298,7 +298,7 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog, */ definitions->store(def); } else if (!intrastage_match(prev_def, &def, - (ir_variable_mode) var->mode)) { + (ir_variable_mode) var->data.mode)) { linker_error(prog, "definitions of interface block `%s' do not" " match\n", iface_type->name); return; @@ -318,7 +318,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog, /* Add input interfaces from the consumer to the symbol table. */ foreach_list(node, consumer->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (!var || !var->get_interface_type() || var->mode != ir_var_shader_in) + if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_in) continue; definitions.store(interface_block_definition(var)); @@ -327,7 +327,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog, /* Verify that the producer's output interfaces match. */ foreach_list(node, producer->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (!var || !var->get_interface_type() || var->mode != ir_var_shader_out) + if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_out) continue; interface_block_definition *consumer_def = @@ -361,7 +361,7 @@ validate_interstage_uniform_blocks(struct gl_shader_program *prog, const gl_shader *stage = stages[i]; foreach_list(node, stage->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (!var || !var->get_interface_type() || var->mode != ir_var_uniform) + if (!var || !var->get_interface_type() || var->data.mode != ir_var_uniform) continue; interface_block_definition *old_def = diff --git a/mesalib/src/glsl/link_uniform_initializers.cpp b/mesalib/src/glsl/link_uniform_initializers.cpp index 786aaf0b4..04daa1760 100644 --- a/mesalib/src/glsl/link_uniform_initializers.cpp +++ b/mesalib/src/glsl/link_uniform_initializers.cpp @@ -224,15 +224,15 @@ link_set_uniform_initializers(struct gl_shader_program *prog) foreach_list(node, shader->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (!var || var->mode != ir_var_uniform) + if (!var || var->data.mode != ir_var_uniform) continue; if (!mem_ctx) mem_ctx = ralloc_context(NULL); - if (var->explicit_binding) { + if (var->data.explicit_binding) { linker::set_uniform_binding(mem_ctx, prog, var->name, - var->type, var->binding); + var->type, var->data.binding); } else if (var->constant_value) { linker::set_uniform_initializer(mem_ctx, prog, var->name, var->type, var->constant_value); diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index 0a15739c2..bda6e4ffb 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -75,7 +75,7 @@ program_resource_visitor::process(ir_variable *var) */ /* Only strdup the name if we actually will need to modify it. */ - if (var->from_named_ifc_block_array) { + if (var->data.from_named_ifc_block_array) { /* lower_named_interface_blocks created this variable by lowering an * interface block array to an array variable. For example if the * original source code was: @@ -108,7 +108,7 @@ program_resource_visitor::process(ir_variable *var) recursion(var->type, &name, new_length, false, NULL); } ralloc_free(name); - } else if (var->from_named_ifc_block_nonarray) { + } else if (var->data.from_named_ifc_block_nonarray) { /* lower_named_interface_blocks created this variable by lowering a * named interface block (non-array) to an ordinary variable. For * example if the original source code was: @@ -408,10 +408,10 @@ public: const struct gl_uniform_block *const block = &prog->UniformBlocks[ubo_block_index]; - assert(var->location != -1); + assert(var->data.location != -1); const struct gl_uniform_buffer_variable *const ubo_var = - &block->Uniforms[var->location]; + &block->Uniforms[var->data.location]; ubo_row_major = ubo_var->RowMajor; ubo_byte_offset = ubo_var->Offset; @@ -637,10 +637,10 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) if ((var == NULL) || !var->is_in_uniform_block()) continue; - assert(var->mode == ir_var_uniform); + assert(var->data.mode == ir_var_uniform); if (var->is_interface_instance()) { - var->location = 0; + var->data.location = 0; continue; } @@ -669,13 +669,13 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) if (strncmp(var->name, begin, l) == 0) { found = true; - var->location = j; + var->data.location = j; break; } } else if (!strcmp(var->name, shader->UniformBlocks[i].Uniforms[j].Name)) { found = true; - var->location = j; + var->data.location = j; break; } } @@ -767,7 +767,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform)) + if ((var == NULL) || (var->data.mode != ir_var_uniform)) continue; /* FINISHME: Update code to process built-in uniforms! @@ -818,7 +818,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) foreach_list(node, prog->_LinkedShaders[i]->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform)) + if ((var == NULL) || (var->data.mode != ir_var_uniform)) continue; /* FINISHME: Update code to process built-in uniforms! diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index be36b5f8f..229a4cb85 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -93,31 +93,43 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog, /* Check that all of the qualifiers match between stages. */ - if (input->centroid != output->centroid) { + if (input->data.centroid != output->data.centroid) { linker_error(prog, "%s shader output `%s' %s centroid qualifier, " "but %s shader input %s centroid qualifier\n", _mesa_glsl_shader_target_name(producer_type), output->name, - (output->centroid) ? "has" : "lacks", + (output->data.centroid) ? "has" : "lacks", _mesa_glsl_shader_target_name(consumer_type), - (input->centroid) ? "has" : "lacks"); + (input->data.centroid) ? "has" : "lacks"); return; } - if (input->invariant != output->invariant) { + if (input->data.sample != output->data.sample) { + linker_error(prog, + "%s shader output `%s' %s sample qualifier, " + "but %s shader input %s sample qualifier\n", + _mesa_glsl_shader_target_name(producer_type), + output->name, + (output->data.sample) ? "has" : "lacks", + _mesa_glsl_shader_target_name(consumer_type), + (input->data.sample) ? "has" : "lacks"); + return; + } + + if (input->data.invariant != output->data.invariant) { linker_error(prog, "%s shader output `%s' %s invariant qualifier, " "but %s shader input %s invariant qualifier\n", _mesa_glsl_shader_target_name(producer_type), output->name, - (output->invariant) ? "has" : "lacks", + (output->data.invariant) ? "has" : "lacks", _mesa_glsl_shader_target_name(consumer_type), - (input->invariant) ? "has" : "lacks"); + (input->data.invariant) ? "has" : "lacks"); return; } - if (input->interpolation != output->interpolation) { + if (input->data.interpolation != output->data.interpolation) { linker_error(prog, "%s shader output `%s' specifies %s " "interpolation qualifier, " @@ -125,9 +137,9 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog, "interpolation qualifier\n", _mesa_glsl_shader_target_name(producer_type), output->name, - interpolation_string(output->interpolation), + interpolation_string(output->data.interpolation), _mesa_glsl_shader_target_name(consumer_type), - interpolation_string(input->interpolation)); + interpolation_string(input->data.interpolation)); return; } } @@ -143,11 +155,11 @@ cross_validate_front_and_back_color(struct gl_shader_program *prog, GLenum consumer_type, GLenum producer_type) { - if (front_color != NULL && front_color->assigned) + if (front_color != NULL && front_color->data.assigned) cross_validate_types_and_qualifiers(prog, input, front_color, consumer_type, producer_type); - if (back_color != NULL && back_color->assigned) + if (back_color != NULL && back_color->data.assigned) cross_validate_types_and_qualifiers(prog, input, back_color, consumer_type, producer_type); } @@ -166,7 +178,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, foreach_list(node, producer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_shader_out)) + if ((var == NULL) || (var->data.mode != ir_var_shader_out)) continue; parameters.add_variable(var); @@ -184,10 +196,10 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, foreach_list(node, consumer->ir) { ir_variable *const input = ((ir_instruction *) node)->as_variable(); - if ((input == NULL) || (input->mode != ir_var_shader_in)) + if ((input == NULL) || (input->data.mode != ir_var_shader_in)) continue; - if (strcmp(input->name, "gl_Color") == 0 && input->used) { + if (strcmp(input->name, "gl_Color") == 0 && input->data.used) { const ir_variable *const front_color = parameters.get_variable("gl_FrontColor"); @@ -197,7 +209,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, cross_validate_front_and_back_color(prog, input, front_color, back_color, consumer->Type, producer->Type); - } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->used) { + } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->data.used) { const ir_variable *const front_color = parameters.get_variable("gl_FrontSecondaryColor"); @@ -317,8 +329,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, assert(this->is_varying()); unsigned fine_location - = this->matched_candidate->toplevel_var->location * 4 - + this->matched_candidate->toplevel_var->location_frac + = this->matched_candidate->toplevel_var->data.location * 4 + + this->matched_candidate->toplevel_var->data.location_frac + this->matched_candidate->offset; if (this->matched_candidate->type->is_array()) { @@ -734,7 +746,7 @@ varying_matches::~varying_matches() void varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) { - if (!producer_var->is_unmatched_generic_inout) { + if (!producer_var->data.is_unmatched_generic_inout) { /* Either a location already exists for this variable (since it is part * of fixed functionality), or it has already been recorded as part of a * previous match. @@ -752,12 +764,14 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) * regardless of where they appear. We can trivially satisfy that * requirement by changing the interpolation type to flat here. */ - producer_var->centroid = false; - producer_var->interpolation = INTERP_QUALIFIER_FLAT; + producer_var->data.centroid = false; + producer_var->data.sample = false; + producer_var->data.interpolation = INTERP_QUALIFIER_FLAT; if (consumer_var) { - consumer_var->centroid = false; - consumer_var->interpolation = INTERP_QUALIFIER_FLAT; + consumer_var->data.centroid = false; + consumer_var->data.sample = false; + consumer_var->data.interpolation = INTERP_QUALIFIER_FLAT; } } @@ -784,9 +798,9 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) this->matches[this->num_matches].producer_var = producer_var; this->matches[this->num_matches].consumer_var = consumer_var; this->num_matches++; - producer_var->is_unmatched_generic_inout = 0; + producer_var->data.is_unmatched_generic_inout = 0; if (consumer_var) - consumer_var->is_unmatched_generic_inout = 0; + consumer_var->data.is_unmatched_generic_inout = 0; } @@ -838,12 +852,12 @@ varying_matches::store_locations(unsigned producer_base, unsigned slot = generic_location / 4; unsigned offset = generic_location % 4; - producer_var->location = producer_base + slot; - producer_var->location_frac = offset; + producer_var->data.location = producer_base + slot; + producer_var->data.location_frac = offset; if (consumer_var) { - assert(consumer_var->location == -1); - consumer_var->location = consumer_base + slot; - consumer_var->location_frac = offset; + assert(consumer_var->data.location == -1); + consumer_var->data.location = consumer_base + slot; + consumer_var->data.location_frac = offset; } } } @@ -873,9 +887,9 @@ varying_matches::compute_packing_class(ir_variable *var) * * Therefore, the packing class depends only on the interpolation type. */ - unsigned packing_class = var->centroid ? 1 : 0; + unsigned packing_class = var->data.centroid | (var->data.sample << 1); packing_class *= 4; - packing_class += var->interpolation; + packing_class += var->data.interpolation; return packing_class; } @@ -933,8 +947,8 @@ is_varying_var(GLenum shaderType, const ir_variable *var) { /* Only fragment shaders will take a varying variable as an input */ if (shaderType == GL_FRAGMENT_SHADER && - var->mode == ir_var_shader_in) { - switch (var->location) { + var->data.mode == ir_var_shader_in) { + switch (var->data.location) { case VARYING_SLOT_POS: case VARYING_SLOT_FACE: case VARYING_SLOT_PNTC: @@ -1082,7 +1096,7 @@ assign_varying_locations(struct gl_context *ctx, ir_variable *const input_var = ((ir_instruction *) node)->as_variable(); - if ((input_var != NULL) && (input_var->mode == ir_var_shader_in)) { + if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) { if (input_var->get_interface_type() != NULL) { char *const iface_field_name = ralloc_asprintf(mem_ctx, "%s.%s", @@ -1101,7 +1115,7 @@ assign_varying_locations(struct gl_context *ctx, foreach_list(node, producer->ir) { ir_variable *const output_var = ((ir_instruction *) node)->as_variable(); - if ((output_var == NULL) || (output_var->mode != ir_var_shader_out)) + if ((output_var == NULL) || (output_var->data.mode != ir_var_shader_out)) continue; tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates); @@ -1121,7 +1135,7 @@ assign_varying_locations(struct gl_context *ctx, (ir_variable *) hash_table_find(consumer_inputs, output_var->name); } - if (input_var && input_var->mode != ir_var_shader_in) + if (input_var && input_var->data.mode != ir_var_shader_in) input_var = NULL; if (input_var) { @@ -1143,7 +1157,7 @@ assign_varying_locations(struct gl_context *ctx, return false; } - if (matched_candidate->toplevel_var->is_unmatched_generic_inout) + if (matched_candidate->toplevel_var->data.is_unmatched_generic_inout) matches.record(matched_candidate->toplevel_var, NULL); } @@ -1185,8 +1199,8 @@ assign_varying_locations(struct gl_context *ctx, foreach_list(node, consumer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var && var->mode == ir_var_shader_in && - var->is_unmatched_generic_inout) { + if (var && var->data.mode == ir_var_shader_in && + var->data.is_unmatched_generic_inout) { if (prog->Version <= 120) { /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec: * @@ -1211,7 +1225,7 @@ assign_varying_locations(struct gl_context *ctx, /* An 'in' variable is only really a shader input if its * value is written by the previous stage. */ - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; } } } @@ -1229,7 +1243,7 @@ check_against_output_limit(struct gl_context *ctx, foreach_list(node, producer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var && var->mode == ir_var_shader_out && + if (var && var->data.mode == ir_var_shader_out && is_varying_var(producer->Type, var)) { output_vectors += var->type->count_attribute_slots(); } @@ -1278,7 +1292,7 @@ check_against_input_limit(struct gl_context *ctx, foreach_list(node, consumer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var && var->mode == ir_var_shader_in && + if (var && var->data.mode == ir_var_shader_in && is_varying_var(consumer->Type, var)) { input_vectors += var->type->count_attribute_slots(); } diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 1366077f7..a6133ea9c 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -114,8 +114,8 @@ public: ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *sig_param = (ir_variable *)sig_iter.get(); - if (sig_param->mode == ir_var_function_out || - sig_param->mode == ir_var_function_inout) { + if (sig_param->data.mode == ir_var_function_out || + sig_param->data.mode == ir_var_function_inout) { ir_variable *var = param_rval->variable_referenced(); if (var && strcmp(name, var->name) == 0) { found = true; @@ -198,7 +198,7 @@ public: virtual ir_visitor_status visit(ir_variable *var) { - if (!var->type->is_array() || var->mode != ir_var_shader_in) + if (!var->type->is_array() || var->data.mode != ir_var_shader_in) return visit_continue; unsigned size = var->type->length; @@ -217,16 +217,16 @@ public: * array using an index too large for its actual size assigned at link * time. */ - if (var->max_array_access >= this->num_vertices) { + if (var->data.max_array_access >= this->num_vertices) { linker_error(this->prog, "geometry shader accesses element %i of " "%s, but only %i input vertices\n", - var->max_array_access, var->name, this->num_vertices); + var->data.max_array_access, var->name, this->num_vertices); return visit_continue; } var->type = glsl_type::get_array_instance(var->type->element_type(), this->num_vertices); - var->max_array_access = this->num_vertices - 1; + var->data.max_array_access = this->num_vertices - 1; return visit_continue; } @@ -379,9 +379,9 @@ link_invalidate_variable_locations(exec_list *ir) * shader inputs (via layout(location=...)), and generic fragment shader * outputs (also via layout(location=...)). */ - if (!var->explicit_location) { - var->location = -1; - var->location_frac = 0; + if (!var->data.explicit_location) { + var->data.location = -1; + var->data.location_frac = 0; } /* ir_variable::is_unmatched_generic_inout is used by the linker while @@ -396,10 +396,10 @@ link_invalidate_variable_locations(exec_list *ir) * GL_ARB_separate_shader_objects is supported. When that extension is * implemented, this function will need some modifications. */ - if (!var->explicit_location) { - var->is_unmatched_generic_inout = 1; + if (!var->data.explicit_location) { + var->data.is_unmatched_generic_inout = 1; } else { - var->is_unmatched_generic_inout = 0; + var->data.is_unmatched_generic_inout = 0; } } } @@ -580,13 +580,13 @@ cross_validate_globals(struct gl_shader_program *prog, if (var == NULL) continue; - if (uniforms_only && (var->mode != ir_var_uniform)) + if (uniforms_only && (var->data.mode != ir_var_uniform)) continue; /* Don't cross validate temporaries that are at global scope. These * will eventually get pulled into the shaders 'main'. */ - if (var->mode == ir_var_temporary) + if (var->data.mode == ir_var_temporary) continue; /* If a global with this name has already been seen, verify that the @@ -619,17 +619,17 @@ cross_validate_globals(struct gl_shader_program *prog, } } - if (var->explicit_location) { - if (existing->explicit_location - && (var->location != existing->location)) { + if (var->data.explicit_location) { + if (existing->data.explicit_location + && (var->data.location != existing->data.location)) { linker_error(prog, "explicit locations for %s " "`%s' have differing values\n", mode_string(var), var->name); return; } - existing->location = var->location; - existing->explicit_location = true; + existing->data.location = var->data.location; + existing->data.explicit_location = true; } /* From the GLSL 4.20 specification: @@ -638,21 +638,21 @@ cross_validate_globals(struct gl_shader_program *prog, * opaque-uniform name. However, it is not an error to specify a * binding on some but not all declarations for the same name" */ - if (var->explicit_binding) { - if (existing->explicit_binding && - var->binding != existing->binding) { + if (var->data.explicit_binding) { + if (existing->data.explicit_binding && + var->data.binding != existing->data.binding) { linker_error(prog, "explicit bindings for %s " "`%s' have differing values\n", mode_string(var), var->name); return; } - existing->binding = var->binding; - existing->explicit_binding = true; + existing->data.binding = var->data.binding; + existing->data.explicit_binding = true; } if (var->type->contains_atomic() && - var->atomic.offset != existing->atomic.offset) { + var->data.atomic.offset != existing->data.atomic.offset) { linker_error(prog, "offset specifications for %s " "`%s' have differing values\n", mode_string(var), var->name); @@ -671,9 +671,9 @@ cross_validate_globals(struct gl_shader_program *prog, * of qualifiers." */ if (strcmp(var->name, "gl_FragDepth") == 0) { - bool layout_declared = var->depth_layout != ir_depth_layout_none; + bool layout_declared = var->data.depth_layout != ir_depth_layout_none; bool layout_differs = - var->depth_layout != existing->depth_layout; + var->data.depth_layout != existing->data.depth_layout; if (layout_declared && layout_differs) { linker_error(prog, @@ -682,7 +682,7 @@ cross_validate_globals(struct gl_shader_program *prog, "the same set of qualifiers."); } - if (var->used && layout_differs) { + if (var->data.used && layout_differs) { linker_error(prog, "If gl_FragDepth is redeclared with a layout " "qualifier in any fragment shader, it must be " @@ -734,8 +734,8 @@ cross_validate_globals(struct gl_shader_program *prog, } } - if (var->has_initializer) { - if (existing->has_initializer + if (var->data.has_initializer) { + if (existing->data.has_initializer && (var->constant_initializer == NULL || existing->constant_initializer == NULL)) { linker_error(prog, @@ -750,21 +750,27 @@ cross_validate_globals(struct gl_shader_program *prog, * otherwise) will propagate the existence to the variable * stored in the symbol table. */ - existing->has_initializer = true; + existing->data.has_initializer = true; } - if (existing->invariant != var->invariant) { + if (existing->data.invariant != var->data.invariant) { linker_error(prog, "declarations for %s `%s' have " "mismatching invariant qualifiers\n", mode_string(var), var->name); return; } - if (existing->centroid != var->centroid) { + if (existing->data.centroid != var->data.centroid) { linker_error(prog, "declarations for %s `%s' have " "mismatching centroid qualifiers\n", mode_string(var), var->name); return; } + if (existing->data.sample != var->data.sample) { + linker_error(prog, "declarations for %s `%s` have " + "mismatching sample qualifiers\n", + mode_string(var), var->name); + return; + } } else variables.add_variable(var); } @@ -884,7 +890,7 @@ remap_variables(ir_instruction *inst, struct gl_shader *target, virtual ir_visitor_status visit(ir_dereference_variable *ir) { - if (ir->var->mode == ir_var_temporary) { + if (ir->var->data.mode == ir_var_temporary) { ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var); assert(var != NULL); @@ -958,13 +964,13 @@ move_non_declarations(exec_list *instructions, exec_node *last, continue; ir_variable *var = inst->as_variable(); - if ((var != NULL) && (var->mode != ir_var_temporary)) + if ((var != NULL) && (var->data.mode != ir_var_temporary)) continue; assert(inst->as_assignment() || inst->as_call() || inst->as_if() /* for initializers with the ?: operator */ - || ((var != NULL) && (var->mode == ir_var_temporary))); + || ((var != NULL) && (var->data.mode == ir_var_temporary))); if (make_copies) { inst = inst->clone(target, NULL); @@ -1036,7 +1042,7 @@ public: virtual ir_visitor_status visit(ir_variable *var) { - fixup_type(&var->type, var->max_array_access); + fixup_type(&var->type, var->data.max_array_access); if (var->type->is_interface()) { if (interface_contains_unsized_arrays(var->type)) { const glsl_type *new_type = @@ -1405,36 +1411,38 @@ link_intrastage_shaders(void *mem_ctx, insertion_point, true, linked); } - /* Resolve initializers for global variables in the linked shader. - */ - unsigned num_linking_shaders = num_shaders; - for (unsigned i = 0; i < num_shaders; i++) - num_linking_shaders += shader_list[i]->num_builtins_to_link; + /* Check if any shader needs built-in functions. */ + bool need_builtins = false; + for (unsigned i = 0; i < num_shaders; i++) { + if (shader_list[i]->uses_builtin_functions) { + need_builtins = true; + break; + } + } - gl_shader **linking_shaders = - (gl_shader **) calloc(num_linking_shaders, sizeof(gl_shader *)); + bool ok; + if (need_builtins) { + /* Make a temporary array one larger than shader_list, which will hold + * the built-in function shader as well. + */ + gl_shader **linking_shaders = (gl_shader **) + calloc(num_shaders + 1, sizeof(gl_shader *)); + memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *)); + linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader(); - memcpy(linking_shaders, shader_list, - sizeof(linking_shaders[0]) * num_shaders); + ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1); - unsigned idx = num_shaders; - for (unsigned i = 0; i < num_shaders; i++) { - memcpy(&linking_shaders[idx], shader_list[i]->builtins_to_link, - sizeof(linking_shaders[0]) * shader_list[i]->num_builtins_to_link); - idx += shader_list[i]->num_builtins_to_link; + free(linking_shaders); + } else { + ok = link_function_calls(prog, linked, shader_list, num_shaders); } - assert(idx == num_linking_shaders); - if (!link_function_calls(prog, linked, linking_shaders, - num_linking_shaders)) { + if (!ok) { ctx->Driver.DeleteShader(ctx, linked); - free(linking_shaders); return NULL; } - free(linking_shaders); - /* At this point linked should contain all of the linked IR, so * validate it to make sure nothing went wrong. */ @@ -1486,7 +1494,7 @@ update_array_sizes(struct gl_shader_program *prog) foreach_list(node, prog->_LinkedShaders[i]->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform) || + if ((var == NULL) || (var->data.mode != ir_var_uniform) || !var->type->is_array()) continue; @@ -1501,7 +1509,7 @@ update_array_sizes(struct gl_shader_program *prog) if (var->is_in_uniform_block() || var->type->contains_atomic()) continue; - unsigned int size = var->max_array_access; + unsigned int size = var->data.max_array_access; for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) { if (prog->_LinkedShaders[j] == NULL) continue; @@ -1512,8 +1520,8 @@ update_array_sizes(struct gl_shader_program *prog) continue; if (strcmp(var->name, other_var->name) == 0 && - other_var->max_array_access > size) { - size = other_var->max_array_access; + other_var->data.max_array_access > size) { + size = other_var->data.max_array_access; } } } @@ -1652,16 +1660,17 @@ assign_attribute_or_color_locations(gl_shader_program *prog, foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != (unsigned) direction)) + if ((var == NULL) || (var->data.mode != (unsigned) direction)) continue; - if (var->explicit_location) { - if ((var->location >= (int)(max_index + generic_base)) - || (var->location < 0)) { + if (var->data.explicit_location) { + if ((var->data.location >= (int)(max_index + generic_base)) + || (var->data.location < 0)) { linker_error(prog, "invalid explicit location %d specified for `%s'\n", - (var->location < 0) - ? var->location : var->location - generic_base, + (var->data.location < 0) + ? var->data.location + : var->data.location - generic_base, var->name); return false; } @@ -1670,8 +1679,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog, if (prog->AttributeBindings->get(binding, var->name)) { assert(binding >= VERT_ATTRIB_GENERIC0); - var->location = binding; - var->is_unmatched_generic_inout = 0; + var->data.location = binding; + var->data.is_unmatched_generic_inout = 0; } } else if (target_index == MESA_SHADER_FRAGMENT) { unsigned binding; @@ -1679,11 +1688,11 @@ assign_attribute_or_color_locations(gl_shader_program *prog, if (prog->FragDataBindings->get(binding, var->name)) { assert(binding >= FRAG_RESULT_DATA0); - var->location = binding; - var->is_unmatched_generic_inout = 0; + var->data.location = binding; + var->data.is_unmatched_generic_inout = 0; if (prog->FragDataIndexBindings->get(index, var->name)) { - var->index = index; + var->data.index = index; } } } @@ -1694,8 +1703,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog, * add it to the list of variables that need linker-assigned locations. */ const unsigned slots = var->type->count_attribute_slots(); - if (var->location != -1) { - if (var->location >= generic_base && var->index < 1) { + if (var->data.location != -1) { + if (var->data.location >= generic_base && var->data.index < 1) { /* From page 61 of the OpenGL 4.0 spec: * * "LinkProgram will fail if the attribute bindings assigned @@ -1729,7 +1738,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, /* Mask representing the contiguous slots that will be used by * this attribute. */ - const unsigned attr = var->location - generic_base; + const unsigned attr = var->data.location - generic_base; const unsigned use_mask = (1 << slots) - 1; /* Generate a link error if the set of bits requested for this @@ -1795,8 +1804,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog, return false; } - to_assign[i].var->location = generic_base + location; - to_assign[i].var->is_unmatched_generic_inout = 0; + to_assign[i].var->data.location = generic_base + location; + to_assign[i].var->data.is_unmatched_generic_inout = 0; used_locations |= (use_mask << location); } @@ -1813,15 +1822,15 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode) foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != int(mode))) + if ((var == NULL) || (var->data.mode != int(mode))) continue; /* A shader 'in' or 'out' variable is only really an input or output if * its value is used by other shader stages. This will cause the variable * to have a location assigned. */ - if (var->is_unmatched_generic_inout) { - var->mode = ir_var_auto; + if (var->data.is_unmatched_generic_inout) { + var->data.mode = ir_var_auto; } } } @@ -1849,12 +1858,12 @@ store_fragdepth_layout(struct gl_shader_program *prog) foreach_list(node, ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var == NULL || var->mode != ir_var_shader_out) { + if (var == NULL || var->data.mode != ir_var_shader_out) { continue; } if (strcmp(var->name, "gl_FragDepth") == 0) { - switch (var->depth_layout) { + switch (var->data.depth_layout) { case ir_depth_layout_none: prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE; return; diff --git a/mesalib/src/glsl/loop_analysis.cpp b/mesalib/src/glsl/loop_analysis.cpp index b08241af5..fd2b6c923 100644 --- a/mesalib/src/glsl/loop_analysis.cpp +++ b/mesalib/src/glsl/loop_analysis.cpp @@ -33,6 +33,46 @@ static bool all_expression_operands_are_loop_constant(ir_rvalue *, static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *); +/** + * Record the fact that the given loop variable was referenced inside the loop. + * + * \arg in_assignee is true if the reference was on the LHS of an assignment. + * + * \arg in_conditional_code_or_nested_loop is true if the reference occurred + * inside an if statement or a nested loop. + * + * \arg current_assignment is the ir_assignment node that the loop variable is + * on the LHS of, if any (ignored if \c in_assignee is false). + */ +void +loop_variable::record_reference(bool in_assignee, + bool in_conditional_code_or_nested_loop, + ir_assignment *current_assignment) +{ + if (in_assignee) { + assert(current_assignment != NULL); + + if (in_conditional_code_or_nested_loop || + current_assignment->condition != NULL) { + this->conditional_or_nested_assignment = true; + } + + if (this->first_assignment == NULL) { + assert(this->num_assignments == 0); + + this->first_assignment = current_assignment; + } + + this->num_assignments++; + } else if (this->first_assignment == current_assignment) { + /* This catches the case where the variable is used in the RHS of an + * assignment where it is also in the LHS. + */ + this->read_before_write = true; + } +} + + loop_state::loop_state() { this->ht = hash_table_ctor(0, hash_table_pointer_hash, @@ -94,7 +134,7 @@ loop_terminator * loop_variable_state::insert(ir_if *if_stmt) { void *mem_ctx = ralloc_parent(this); - loop_terminator *t = rzalloc(mem_ctx, loop_terminator); + loop_terminator *t = new(mem_ctx) loop_terminator(); t->ir = if_stmt; this->terminators.push_tail(t); @@ -102,6 +142,33 @@ loop_variable_state::insert(ir_if *if_stmt) return t; } + +/** + * If the given variable already is recorded in the state for this loop, + * return the corresponding loop_variable object that records information + * about it. + * + * Otherwise, create a new loop_variable object to record information about + * the variable, and set its \c read_before_write field appropriately based on + * \c in_assignee. + * + * \arg in_assignee is true if this variable was encountered on the LHS of an + * assignment. + */ +loop_variable * +loop_variable_state::get_or_insert(ir_variable *var, bool in_assignee) +{ + loop_variable *lv = this->get(var); + + if (lv == NULL) { + lv = this->insert(var); + lv->read_before_write = !in_assignee; + } + + return lv; +} + + namespace { class loop_analysis : public ir_hierarchical_visitor { @@ -157,14 +224,14 @@ loop_analysis::visit(ir_loop_jump *ir) ir_visitor_status loop_analysis::visit_enter(ir_call *ir) { - /* If we're not somewhere inside a loop, there's nothing to do. */ - if (this->state.is_empty()) - return visit_continue; - - loop_variable_state *const ls = - (loop_variable_state *) this->state.get_head(); + /* Mark every loop that we're currently analyzing as containing an ir_call + * (even those at outer nesting levels). + */ + foreach_list(node, &this->state) { + loop_variable_state *const ls = (loop_variable_state *) node; + ls->contains_calls = true; + } - ls->contains_calls = true; return visit_continue_with_parent; } @@ -177,35 +244,18 @@ loop_analysis::visit(ir_dereference_variable *ir) if (this->state.is_empty()) return visit_continue; - loop_variable_state *const ls = - (loop_variable_state *) this->state.get_head(); - - ir_variable *var = ir->variable_referenced(); - loop_variable *lv = ls->get(var); - - if (lv == NULL) { - lv = ls->insert(var); - lv->read_before_write = !this->in_assignee; - } - - if (this->in_assignee) { - assert(this->current_assignment != NULL); + bool nested = false; - lv->conditional_assignment = (this->if_statement_depth > 0) - || (this->current_assignment->condition != NULL); + foreach_list(node, &this->state) { + loop_variable_state *const ls = (loop_variable_state *) node; - if (lv->first_assignment == NULL) { - assert(lv->num_assignments == 0); - - lv->first_assignment = this->current_assignment; - } + ir_variable *var = ir->variable_referenced(); + loop_variable *lv = ls->get_or_insert(var, this->in_assignee); - lv->num_assignments++; - } else if (lv->first_assignment == this->current_assignment) { - /* This catches the case where the variable is used in the RHS of an - * assignment where it is also in the LHS. - */ - lv->read_before_write = true; + lv->record_reference(this->in_assignee, + nested || this->if_statement_depth > 0, + this->current_assignment); + nested = true; } return visit_continue; @@ -286,7 +336,7 @@ loop_analysis::visit_leave(ir_loop *ir) foreach_list_safe(node, &ls->variables) { loop_variable *lv = (loop_variable *) node; - if (lv->conditional_assignment || (lv->num_assignments > 1)) + if (lv->conditional_or_nested_assignment || (lv->num_assignments > 1)) continue; /* Process the RHS of the assignment. If all of the variables @@ -326,9 +376,10 @@ loop_analysis::visit_leave(ir_loop *ir) assert(lv->num_assignments == 1); assert(lv->first_assignment != NULL); - /* The assignmnet to the variable in the loop must be unconditional. + /* The assignment to the variable in the loop must be unconditional and + * not inside a nested loop. */ - if (lv->conditional_assignment) + if (lv->conditional_or_nested_assignment) continue; /* Basic loop induction variables have a single assignment in the loop @@ -338,8 +389,6 @@ loop_analysis::visit_leave(ir_loop *ir) ir_rvalue *const inc = get_basic_induction_increment(lv->first_assignment, ls->var_hash); if (inc != NULL) { - lv->iv_scale = NULL; - lv->biv = lv->var; lv->increment = inc; lv->remove(); @@ -347,6 +396,75 @@ loop_analysis::visit_leave(ir_loop *ir) } } + /* Search the loop terminating conditions for those of the form 'i < c' + * where i is a loop induction variable, c is a constant, and < is any + * relative operator. From each of these we can infer an iteration count. + * Also figure out which terminator (if any) produces the smallest + * iteration count--this is the limiting terminator. + */ + foreach_list(node, &ls->terminators) { + loop_terminator *t = (loop_terminator *) node; + ir_if *if_stmt = t->ir; + + /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care + * about the former here. + */ + ir_expression *cond = if_stmt->condition->as_expression(); + if (cond == NULL) + continue; + + switch (cond->operation) { + case ir_binop_less: + case ir_binop_greater: + case ir_binop_lequal: + case ir_binop_gequal: { + /* The expressions that we care about will either be of the form + * 'counter < limit' or 'limit < counter'. Figure out which is + * which. + */ + ir_rvalue *counter = cond->operands[0]->as_dereference_variable(); + ir_constant *limit = cond->operands[1]->as_constant(); + enum ir_expression_operation cmp = cond->operation; + + if (limit == NULL) { + counter = cond->operands[1]->as_dereference_variable(); + limit = cond->operands[0]->as_constant(); + + switch (cmp) { + case ir_binop_less: cmp = ir_binop_greater; break; + case ir_binop_greater: cmp = ir_binop_less; break; + case ir_binop_lequal: cmp = ir_binop_gequal; break; + case ir_binop_gequal: cmp = ir_binop_lequal; break; + default: assert(!"Should not get here."); + } + } + + if ((counter == NULL) || (limit == NULL)) + break; + + ir_variable *var = counter->variable_referenced(); + + ir_rvalue *init = find_initial_value(ir, var); + + loop_variable *lv = ls->get(var); + if (lv != NULL && lv->is_induction_var()) { + t->iterations = calculate_iterations(init, limit, lv->increment, + cmp); + + if (t->iterations >= 0 && + (ls->limiting_terminator == NULL || + t->iterations < ls->limiting_terminator->iterations)) { + ls->limiting_terminator = t; + } + } + break; + } + + default: + break; + } + } + return visit_continue; } diff --git a/mesalib/src/glsl/loop_analysis.h b/mesalib/src/glsl/loop_analysis.h index 769d62661..f841042f0 100644 --- a/mesalib/src/glsl/loop_analysis.h +++ b/mesalib/src/glsl/loop_analysis.h @@ -39,16 +39,12 @@ analyze_loop_variables(exec_list *instructions); /** * Fill in loop control fields * - * Based on analysis of loop variables, this function tries to remove sequences - * in the loop of the form + * Based on analysis of loop variables, this function tries to remove + * redundant sequences in the loop of the form * * (if (expression bool ...) (break)) * - * and fill in the \c ir_loop::from, \c ir_loop::to, and \c ir_loop::counter - * fields of the \c ir_loop. - * - * In this process, some conditional break-statements may be eliminated - * altogether. For example, if it is provable that one loop exit condition will + * For example, if it is provable that one loop exit condition will * always be satisfied before another, the unnecessary exit condition will be * removed. */ @@ -59,6 +55,13 @@ set_loop_controls(exec_list *instructions, loop_state *ls); extern bool unroll_loops(exec_list *instructions, loop_state *ls, unsigned max_iterations); +ir_rvalue * +find_initial_value(ir_loop *loop, ir_variable *var); + +int +calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, + enum ir_expression_operation op); + /** * Tracking for all variables used in a loop @@ -67,15 +70,11 @@ class loop_variable_state : public exec_node { public: class loop_variable *get(const ir_variable *); class loop_variable *insert(ir_variable *); + class loop_variable *get_or_insert(ir_variable *, bool in_assignee); class loop_terminator *insert(ir_if *); /** - * Loop whose variable state is being tracked by this structure - */ - ir_loop *loop; - - /** * Variables that have not yet been classified */ exec_list variables; @@ -104,18 +103,17 @@ public: exec_list terminators; /** - * Hash table containing all variables accessed in this loop + * If any of the terminators in \c terminators leads to termination of the + * loop after a constant number of iterations, this is the terminator that + * leads to termination after the smallest number of iterations. Otherwise + * NULL. */ - hash_table *var_hash; + loop_terminator *limiting_terminator; /** - * Maximum number of loop iterations. - * - * If this value is negative, then the loop may be infinite. This actually - * means that analysis was unable to determine an upper bound on the number - * of loop iterations. + * Hash table containing all variables accessed in this loop */ - int max_iterations; + hash_table *var_hash; /** * Number of ir_loop_jump instructions that operate on this loop @@ -129,11 +127,11 @@ public: loop_variable_state() { - this->max_iterations = -1; this->num_loop_jumps = 0; this->contains_calls = false; this->var_hash = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); + this->limiting_terminator = NULL; } ~loop_variable_state() @@ -171,8 +169,11 @@ public: /** Are all variables in the RHS of the assignment loop constants? */ bool rhs_clean; - /** Is there an assignment to the variable that is conditional? */ - bool conditional_assignment; + /** + * Is there an assignment to the variable that is conditional, or inside a + * nested loop? + */ + bool conditional_or_nested_assignment; /** Reference to the first assignment to the variable in the loop body. */ ir_assignment *first_assignment; @@ -181,27 +182,30 @@ public: unsigned num_assignments; /** - * Increment values for loop induction variables + * Increment value for a loop induction variable * - * Loop induction variables have a single increment of the form - * \c b * \c biv + \c c, where \c b and \c c are loop constants and \c i - * is a basic loop induction variable. + * If this is a loop induction variable, the amount by which the variable + * is incremented on each iteration through the loop. * - * If \c iv_scale is \c NULL, 1 is used. If \c biv is the same as \c var, - * then \c var is a basic loop induction variable. + * If this is not a loop induction variable, NULL. */ - /*@{*/ - ir_rvalue *iv_scale; - ir_variable *biv; ir_rvalue *increment; - /*@}*/ + + + inline bool is_induction_var() const + { + /* Induction variables always have a non-null increment, and vice + * versa. + */ + return this->increment != NULL; + } inline bool is_loop_constant() const { const bool is_const = (this->num_assignments == 0) || ((this->num_assignments == 1) - && !this->conditional_assignment + && !this->conditional_or_nested_assignment && !this->read_before_write && this->rhs_clean); @@ -213,16 +217,35 @@ public: /* Variables that are marked read-only *MUST* be loop constant. */ - assert(!this->var->read_only || (this->var->read_only && is_const)); + assert(!this->var->data.read_only + || (this->var->data.read_only && is_const)); return is_const; } + + void record_reference(bool in_assignee, + bool in_conditional_code_or_nested_loop, + ir_assignment *current_assignment); }; class loop_terminator : public exec_node { public: + loop_terminator() + : ir(NULL), iterations(-1) + { + } + + /** + * Statement which terminates the loop. + */ ir_if *ir; + + /** + * The number of iterations after which the terminator is known to + * terminate the loop (if that is a fixed value). Otherwise -1. + */ + int iterations; }; diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp index 26481930d..3db06ad18 100644 --- a/mesalib/src/glsl/loop_controls.cpp +++ b/mesalib/src/glsl/loop_controls.cpp @@ -183,114 +183,41 @@ loop_control_visitor::visit_leave(ir_loop *ir) return visit_continue; } - /* Search the loop terminating conditions for one of the form 'i < c' where - * i is a loop induction variable, c is a constant, and < is any relative - * operator. - */ - int max_iterations = ls->max_iterations; - - if(ir->from && ir->to && ir->increment) - max_iterations = calculate_iterations(ir->from, ir->to, ir->increment, (ir_expression_operation)ir->cmp); - - if(max_iterations < 0) - max_iterations = INT_MAX; + if (ls->limiting_terminator != NULL) { + /* If the limiting terminator has an iteration count of zero, then we've + * proven that the loop cannot run, so delete it. + */ + int iterations = ls->limiting_terminator->iterations; + if (iterations == 0) { + ir->remove(); + this->progress = true; + return visit_continue; + } + } + /* Remove the conditional break statements associated with all terminators + * that are associated with a fixed iteration count, except for the one + * associated with the limiting terminator--that one needs to stay, since + * it terminates the loop. Exception: if the loop still has a normative + * bound, then that terminates the loop, so we don't even need the limiting + * terminator. + */ foreach_list(node, &ls->terminators) { loop_terminator *t = (loop_terminator *) node; - ir_if *if_stmt = t->ir; - /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care - * about the former here. - */ - ir_expression *cond = if_stmt->condition->as_expression(); - if (cond == NULL) - continue; - - switch (cond->operation) { - case ir_binop_less: - case ir_binop_greater: - case ir_binop_lequal: - case ir_binop_gequal: { - /* The expressions that we care about will either be of the form - * 'counter < limit' or 'limit < counter'. Figure out which is - * which. - */ - ir_rvalue *counter = cond->operands[0]->as_dereference_variable(); - ir_constant *limit = cond->operands[1]->as_constant(); - enum ir_expression_operation cmp = cond->operation; - - if (limit == NULL) { - counter = cond->operands[1]->as_dereference_variable(); - limit = cond->operands[0]->as_constant(); - - switch (cmp) { - case ir_binop_less: cmp = ir_binop_greater; break; - case ir_binop_greater: cmp = ir_binop_less; break; - case ir_binop_lequal: cmp = ir_binop_gequal; break; - case ir_binop_gequal: cmp = ir_binop_lequal; break; - default: assert(!"Should not get here."); - } - } - - if ((counter == NULL) || (limit == NULL)) - break; - - ir_variable *var = counter->variable_referenced(); - - ir_rvalue *init = find_initial_value(ir, var); - - foreach_list(iv_node, &ls->induction_variables) { - loop_variable *lv = (loop_variable *) iv_node; - - if (lv->var == var) { - const int iterations = calculate_iterations(init, limit, - lv->increment, - cmp); - if (iterations >= 0) { - /* If the new iteration count is lower than the previously - * believed iteration count, update the loop control values. - */ - if (iterations < max_iterations) { - ir->from = init->clone(ir, NULL); - ir->to = limit->clone(ir, NULL); - ir->increment = lv->increment->clone(ir, NULL); - ir->counter = lv->var; - ir->cmp = cmp; - - max_iterations = iterations; - } - - /* Remove the conditional break statement. The loop - * controls are now set such that the exit condition will be - * satisfied. - */ - if_stmt->remove(); - - assert(ls->num_loop_jumps > 0); - ls->num_loop_jumps--; - - this->progress = true; - } - - break; - } - } - break; - } + if (t->iterations < 0) + continue; - default: - break; + if (t != ls->limiting_terminator) { + t->ir->remove(); + + assert(ls->num_loop_jumps > 0); + ls->num_loop_jumps--; + + this->progress = true; } } - /* If we have proven the one of the loop exit conditions is satisifed before - * running the loop once, remove the loop. - */ - if (max_iterations == 0) - ir->remove(); - else - ls->max_iterations = max_iterations; - return visit_continue; } diff --git a/mesalib/src/glsl/loop_unroll.cpp b/mesalib/src/glsl/loop_unroll.cpp index ff97766f1..6eced1736 100644 --- a/mesalib/src/glsl/loop_unroll.cpp +++ b/mesalib/src/glsl/loop_unroll.cpp @@ -37,6 +37,10 @@ public: } virtual ir_visitor_status visit_leave(ir_loop *ir); + void simple_unroll(ir_loop *ir, int iterations); + void complex_unroll(ir_loop *ir, int iterations, + bool continue_from_then_branch); + void splice_post_if_instructions(ir_if *ir_if, exec_list *splice_dest); loop_state *state; @@ -86,6 +90,138 @@ public: }; +/** + * Unroll a loop which does not contain any jumps. For example, if the input + * is: + * + * (loop (...) ...instrs...) + * + * And the iteration count is 3, the output will be: + * + * ...instrs... ...instrs... ...instrs... + */ +void +loop_unroll_visitor::simple_unroll(ir_loop *ir, int iterations) +{ + void *const mem_ctx = ralloc_parent(ir); + + for (int i = 0; i < iterations; i++) { + exec_list copy_list; + + copy_list.make_empty(); + clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + + ir->insert_before(©_list); + } + + /* The loop has been replaced by the unrolled copies. Remove the original + * loop from the IR sequence. + */ + ir->remove(); + + this->progress = true; +} + + +/** + * Unroll a loop whose last statement is an ir_if. If \c + * continue_from_then_branch is true, the loop is repeated only when the + * "then" branch of the if is taken; otherwise it is repeated only when the + * "else" branch of the if is taken. + * + * For example, if the input is: + * + * (loop (...) + * ...body... + * (if (cond) + * (...then_instrs...) + * (...else_instrs...))) + * + * And the iteration count is 3, and \c continue_from_then_branch is true, + * then the output will be: + * + * ...body... + * (if (cond) + * (...then_instrs... + * ...body... + * (if (cond) + * (...then_instrs... + * ...body... + * (if (cond) + * (...then_instrs...) + * (...else_instrs...))) + * (...else_instrs...))) + * (...else_instrs)) + */ +void +loop_unroll_visitor::complex_unroll(ir_loop *ir, int iterations, + bool continue_from_then_branch) +{ + void *const mem_ctx = ralloc_parent(ir); + ir_instruction *ir_to_replace = ir; + + for (int i = 0; i < iterations; i++) { + exec_list copy_list; + + copy_list.make_empty(); + clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + + ir_if *ir_if = ((ir_instruction *) copy_list.get_tail())->as_if(); + assert(ir_if != NULL); + + ir_to_replace->insert_before(©_list); + ir_to_replace->remove(); + + /* placeholder that will be removed in the next iteration */ + ir_to_replace = + new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); + + exec_list *const list = (continue_from_then_branch) + ? &ir_if->then_instructions : &ir_if->else_instructions; + + list->push_tail(ir_to_replace); + } + + ir_to_replace->remove(); + + this->progress = true; +} + + +/** + * Move all of the instructions which follow \c ir_if to the end of + * \c splice_dest. + * + * For example, in the code snippet: + * + * (if (cond) + * (...then_instructions... + * break) + * (...else_instructions...)) + * ...post_if_instructions... + * + * If \c ir_if points to the "if" instruction, and \c splice_dest points to + * (...else_instructions...), the code snippet is transformed into: + * + * (if (cond) + * (...then_instructions... + * break) + * (...else_instructions... + * ...post_if_instructions...)) + */ +void +loop_unroll_visitor::splice_post_if_instructions(ir_if *ir_if, + exec_list *splice_dest) +{ + while (!ir_if->get_next()->is_tail_sentinel()) { + ir_instruction *move_ir = (ir_instruction *) ir_if->get_next(); + + move_ir->remove(); + splice_dest->push_tail(move_ir); + } +} + + ir_visitor_status loop_unroll_visitor::visit_leave(ir_loop *ir) { @@ -100,14 +236,14 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) return visit_continue; } - iterations = ls->max_iterations; - /* Don't try to unroll loops where the number of iterations is not known * at compile-time. */ - if (iterations < 0) + if (ls->limiting_terminator == NULL) return visit_continue; + iterations = ls->limiting_terminator->iterations; + /* Don't try to unroll loops that have zillions of iterations either. */ if (iterations > (int) max_iterations) @@ -120,127 +256,83 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) if (count.fail || count.nodes * iterations > (int)max_iterations * 5) return visit_continue; - if (ls->num_loop_jumps > 1) - return visit_continue; - else if (ls->num_loop_jumps) { - ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail(); - assert(last_ir != NULL); - - if (is_break(last_ir)) { - /* If the only loop-jump is a break at the end of the loop, the loop - * will execute exactly once. Remove the break, set the iteration - * count, and fall through to the normal unroller. - */ - last_ir->remove(); - iterations = 1; - - this->progress = true; - } else { - ir_if *ir_if = NULL; - ir_instruction *break_ir = NULL; - bool continue_from_then_branch = false; - - foreach_list(node, &ir->body_instructions) { - /* recognize loops in the form produced by ir_lower_jumps */ - ir_instruction *cur_ir = (ir_instruction *) node; - - ir_if = cur_ir->as_if(); - if (ir_if != NULL) { - /* Determine which if-statement branch, if any, ends with a - * break. The branch that did *not* have the break will get a - * temporary continue inserted in each iteration of the loop - * unroll. - * - * Note that since ls->num_loop_jumps is <= 1, it is impossible - * for both branches to end with a break. - */ - ir_instruction *ir_if_last = - (ir_instruction *) ir_if->then_instructions.get_tail(); - - if (is_break(ir_if_last)) { - continue_from_then_branch = false; - break_ir = ir_if_last; - break; - } else { - ir_if_last = - (ir_instruction *) ir_if->else_instructions.get_tail(); - - if (is_break(ir_if_last)) { - break_ir = ir_if_last; - continue_from_then_branch = true; - break; - } - } - } - } - - if (break_ir == NULL) - return visit_continue; - - /* move instructions after then if in the continue branch */ - while (!ir_if->get_next()->is_tail_sentinel()) { - ir_instruction *move_ir = (ir_instruction *) ir_if->get_next(); - - move_ir->remove(); - if (continue_from_then_branch) - ir_if->then_instructions.push_tail(move_ir); - else - ir_if->else_instructions.push_tail(move_ir); - } - - /* Remove the break from the if-statement. - */ - break_ir->remove(); - - void *const mem_ctx = ralloc_parent(ir); - ir_instruction *ir_to_replace = ir; - - for (int i = 0; i < iterations; i++) { - exec_list copy_list; + /* Note: the limiting terminator contributes 1 to ls->num_loop_jumps. + * We'll be removing the limiting terminator before we unroll. + */ + assert(ls->num_loop_jumps > 0); + unsigned predicted_num_loop_jumps = ls->num_loop_jumps - 1; - copy_list.make_empty(); - clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + if (predicted_num_loop_jumps > 1) + return visit_continue; - ir_if = ((ir_instruction *) copy_list.get_tail())->as_if(); - assert(ir_if != NULL); + if (predicted_num_loop_jumps == 0) { + ls->limiting_terminator->ir->remove(); + simple_unroll(ir, iterations); + return visit_continue; + } - ir_to_replace->insert_before(©_list); - ir_to_replace->remove(); + ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail(); + assert(last_ir != NULL); - /* placeholder that will be removed in the next iteration */ - ir_to_replace = - new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); + if (is_break(last_ir)) { + /* If the only loop-jump is a break at the end of the loop, the loop + * will execute exactly once. Remove the break and use the simple + * unroller with an iteration count of 1. + */ + last_ir->remove(); - exec_list *const list = (continue_from_then_branch) - ? &ir_if->then_instructions : &ir_if->else_instructions; + ls->limiting_terminator->ir->remove(); + simple_unroll(ir, 1); + return visit_continue; + } - list->push_tail(ir_to_replace); + foreach_list(node, &ir->body_instructions) { + /* recognize loops in the form produced by ir_lower_jumps */ + ir_instruction *cur_ir = (ir_instruction *) node; + + /* Skip the limiting terminator, since it will go away when we + * unroll. + */ + if (cur_ir == ls->limiting_terminator->ir) + continue; + + ir_if *ir_if = cur_ir->as_if(); + if (ir_if != NULL) { + /* Determine which if-statement branch, if any, ends with a + * break. The branch that did *not* have the break will get a + * temporary continue inserted in each iteration of the loop + * unroll. + * + * Note that since ls->num_loop_jumps is <= 1, it is impossible + * for both branches to end with a break. + */ + ir_instruction *ir_if_last = + (ir_instruction *) ir_if->then_instructions.get_tail(); + + if (is_break(ir_if_last)) { + ls->limiting_terminator->ir->remove(); + splice_post_if_instructions(ir_if, &ir_if->else_instructions); + ir_if_last->remove(); + complex_unroll(ir, iterations, false); + return visit_continue; + } else { + ir_if_last = + (ir_instruction *) ir_if->else_instructions.get_tail(); + + if (is_break(ir_if_last)) { + ls->limiting_terminator->ir->remove(); + splice_post_if_instructions(ir_if, &ir_if->then_instructions); + ir_if_last->remove(); + complex_unroll(ir, iterations, true); + return visit_continue; + } } - - ir_to_replace->remove(); - - this->progress = true; - return visit_continue; } } - void *const mem_ctx = ralloc_parent(ir); - - for (int i = 0; i < iterations; i++) { - exec_list copy_list; - - copy_list.make_empty(); - clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); - - ir->insert_before(©_list); - } - - /* The loop has been replaced by the unrolled copies. Remove the original - * loop from the IR sequence. + /* Did not find the break statement. It must be in a complex if-nesting, + * so don't try to unroll. */ - ir->remove(); - - this->progress = true; return visit_continue; } diff --git a/mesalib/src/glsl/lower_clip_distance.cpp b/mesalib/src/glsl/lower_clip_distance.cpp index 04fa6d410..bb4f6ab11 100644 --- a/mesalib/src/glsl/lower_clip_distance.cpp +++ b/mesalib/src/glsl/lower_clip_distance.cpp @@ -135,13 +135,13 @@ lower_clip_distance_visitor::visit(ir_variable *ir) "gl_ClipDistanceMESA"); this->new_clip_distance_1d_var->type = glsl_type::get_array_instance(glsl_type::vec4_type, new_size); - this->new_clip_distance_1d_var->max_array_access - = ir->max_array_access / 4; + this->new_clip_distance_1d_var->data.max_array_access + = ir->data.max_array_access / 4; ir->replace_with(this->new_clip_distance_1d_var); } else { /* 2D gl_ClipDistance (used for geometry input). */ - assert(ir->mode == ir_var_shader_in && + assert(ir->data.mode == ir_var_shader_in && this->shader_type == GL_GEOMETRY_SHADER_ARB); if (this->old_clip_distance_2d_var) return visit_continue; @@ -161,8 +161,8 @@ lower_clip_distance_visitor::visit(ir_variable *ir) glsl_type::get_array_instance(glsl_type::vec4_type, new_size), ir->type->array_size()); - this->new_clip_distance_2d_var->max_array_access - = ir->max_array_access / 4; + this->new_clip_distance_2d_var->data.max_array_access + = ir->data.max_array_access / 4; ir->replace_with(this->new_clip_distance_2d_var); } @@ -500,8 +500,8 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) this->base_ir->insert_before(temp_clip_distance); actual_param->replace_with( new(ctx) ir_dereference_variable(temp_clip_distance)); - if (formal_param->mode == ir_var_function_in - || formal_param->mode == ir_var_function_inout) { + if (formal_param->data.mode == ir_var_function_in + || formal_param->data.mode == ir_var_function_inout) { /* Copy from gl_ClipDistance to the temporary before the call. * Since we are going to insert this copy before the current * instruction, we need to visit it afterwards to make sure it @@ -513,8 +513,8 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) this->base_ir->insert_before(new_assignment); this->visit_new_assignment(new_assignment); } - if (formal_param->mode == ir_var_function_out - || formal_param->mode == ir_var_function_inout) { + if (formal_param->data.mode == ir_var_function_out + || formal_param->data.mode == ir_var_function_inout) { /* Copy from the temporary to gl_ClipDistance after the call. * Since visit_list_elements() has already decided which * instruction it's going to visit next, we need to visit diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp index d01879cbd..8f8d448ea 100644 --- a/mesalib/src/glsl/lower_instructions.cpp +++ b/mesalib/src/glsl/lower_instructions.cpp @@ -383,7 +383,6 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir) /* Constants */ ir_constant *zeroi = ir_constant::zero(ir, ivec); - ir_constant *zerof = ir_constant::zero(ir, ir->type); ir_constant *sign_mantissa_mask = new(ir) ir_constant(0x807fffffu, vec_elem); ir_constant *sign_mask = new(ir) ir_constant(0x80000000u, vec_elem); @@ -429,8 +428,7 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir) */ i.insert_before(zero_sign_x); i.insert_before(assign(zero_sign_x, - bitcast_u2f(bit_or(bit_and(bitcast_f2u(x), sign_mask), - bitcast_f2u(zerof))))); + bitcast_u2f(bit_and(bitcast_f2u(x), sign_mask)))); i.insert_before(is_not_zero_or_underflow); i.insert_before(assign(is_not_zero_or_underflow, diff --git a/mesalib/src/glsl/lower_named_interface_blocks.cpp b/mesalib/src/glsl/lower_named_interface_blocks.cpp index d59d11150..09d867ea3 100644 --- a/mesalib/src/glsl/lower_named_interface_blocks.cpp +++ b/mesalib/src/glsl/lower_named_interface_blocks.cpp @@ -108,7 +108,7 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions) * but, this will require changes to the other uniform block * support code. */ - if (var->mode == ir_var_uniform) + if (var->data.mode == ir_var_uniform) continue; const glsl_type * iface_t = var->type; @@ -139,8 +139,8 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions) new_var = new(mem_ctx) ir_variable(iface_t->fields.structure[i].type, var_name, - (ir_variable_mode) var->mode); - new_var->from_named_ifc_block_nonarray = 1; + (ir_variable_mode) var->data.mode); + new_var->data.from_named_ifc_block_nonarray = 1; } else { const glsl_type *new_array_type = glsl_type::get_array_instance( @@ -149,14 +149,15 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions) new_var = new(mem_ctx) ir_variable(new_array_type, var_name, - (ir_variable_mode) var->mode); - new_var->from_named_ifc_block_array = 1; + (ir_variable_mode) var->data.mode); + new_var->data.from_named_ifc_block_array = 1; } - new_var->location = iface_t->fields.structure[i].location; - new_var->explicit_location = (new_var->location >= 0); - new_var->interpolation = + new_var->data.location = iface_t->fields.structure[i].location; + new_var->data.explicit_location = (new_var->data.location >= 0); + new_var->data.interpolation = iface_t->fields.structure[i].interpolation; - new_var->centroid = iface_t->fields.structure[i].centroid; + new_var->data.centroid = iface_t->fields.structure[i].centroid; + new_var->data.sample = iface_t->fields.structure[i].sample; new_var->init_interface_type(iface_t); hash_table_insert(interface_namespace, new_var, @@ -211,7 +212,7 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue) * but, this will require changes to the other uniform block * support code. */ - if (var->mode == ir_var_uniform) + if (var->data.mode == ir_var_uniform) return; if (var->get_interface_type() != NULL) { diff --git a/mesalib/src/glsl/lower_output_reads.cpp b/mesalib/src/glsl/lower_output_reads.cpp index 128b0b8cd..afe17766b 100644 --- a/mesalib/src/glsl/lower_output_reads.cpp +++ b/mesalib/src/glsl/lower_output_reads.cpp @@ -91,7 +91,7 @@ output_read_remover::~output_read_remover() ir_visitor_status output_read_remover::visit(ir_dereference_variable *ir) { - if (ir->var->mode != ir_var_shader_out) + if (ir->var->data.mode != ir_var_shader_out) return visit_continue; ir_variable *temp = (ir_variable *) hash_table_find(replacements, ir->var); diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp index 61ee692f6..9edef5d04 100644 --- a/mesalib/src/glsl/lower_packed_varyings.cpp +++ b/mesalib/src/glsl/lower_packed_varyings.cpp @@ -258,8 +258,8 @@ lower_packed_varyings_visitor::run(exec_list *instructions) if (var == NULL) continue; - if (var->mode != this->mode || - var->location < (int) this->location_base || + if (var->data.mode != this->mode || + var->data.location < (int) this->location_base || !this->needs_lowering(var)) continue; @@ -268,18 +268,18 @@ lower_packed_varyings_visitor::run(exec_list *instructions) * safe, caller should ensure that integral varyings always use flat * interpolation, even when this is not required by GLSL. */ - assert(var->interpolation == INTERP_QUALIFIER_FLAT || + assert(var->data.interpolation == INTERP_QUALIFIER_FLAT || !var->type->contains_integer()); /* Change the old varying into an ordinary global. */ - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; /* Create a reference to the old varying. */ ir_dereference_variable *deref = new(this->mem_ctx) ir_dereference_variable(var); /* Recursively pack or unpack it. */ - this->lower_rvalue(deref, var->location * 4 + var->location_frac, var, + this->lower_rvalue(deref, var->data.location * 4 + var->data.location_frac, var, var->name, this->gs_input_vertices != 0, 0); } } @@ -547,7 +547,7 @@ lower_packed_varyings_visitor::get_packed_varying_deref( if (this->packed_varyings[slot] == NULL) { char *packed_name = ralloc_asprintf(this->mem_ctx, "packed:%s", name); const glsl_type *packed_type; - if (unpacked_var->interpolation == INTERP_QUALIFIER_FLAT) + if (unpacked_var->data.interpolation == INTERP_QUALIFIER_FLAT) packed_type = glsl_type::ivec4_type; else packed_type = glsl_type::vec4_type; @@ -562,11 +562,12 @@ lower_packed_varyings_visitor::get_packed_varying_deref( /* Prevent update_array_sizes() from messing with the size of the * array. */ - packed_var->max_array_access = this->gs_input_vertices - 1; + packed_var->data.max_array_access = this->gs_input_vertices - 1; } - packed_var->centroid = unpacked_var->centroid; - packed_var->interpolation = unpacked_var->interpolation; - packed_var->location = location; + packed_var->data.centroid = unpacked_var->data.centroid; + packed_var->data.sample = unpacked_var->data.sample; + packed_var->data.interpolation = unpacked_var->data.interpolation; + packed_var->data.location = location; unpacked_var->insert_before(packed_var); this->packed_varyings[slot] = packed_var; } else { diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp index 16b6801b8..c73b148b0 100644 --- a/mesalib/src/glsl/lower_ubo_reference.cpp +++ b/mesalib/src/glsl/lower_ubo_reference.cpp @@ -143,7 +143,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) struct gl_uniform_block *block = &shader->UniformBlocks[i]; this->ubo_var = var->is_interface_instance() - ? &block->Uniforms[0] : &block->Uniforms[var->location]; + ? &block->Uniforms[0] : &block->Uniforms[var->data.location]; break; } diff --git a/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp b/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp index 699fb3903..7c5d80f43 100644 --- a/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp +++ b/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp @@ -365,7 +365,7 @@ public: if (var == NULL) return this->lower_temps; - switch (var->mode) { + switch (var->data.mode) { case ir_var_auto: case ir_var_temporary: return this->lower_temps; diff --git a/mesalib/src/glsl/opt_array_splitting.cpp b/mesalib/src/glsl/opt_array_splitting.cpp index c7c5f6712..e946e0ae5 100644 --- a/mesalib/src/glsl/opt_array_splitting.cpp +++ b/mesalib/src/glsl/opt_array_splitting.cpp @@ -122,8 +122,8 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var) { assert(var); - if (var->mode != ir_var_auto && - var->mode != ir_var_temporary) + if (var->data.mode != ir_var_auto && + var->data.mode != ir_var_temporary) return NULL; if (!(var->type->is_array() || var->type->is_matrix())) diff --git a/mesalib/src/glsl/opt_constant_folding.cpp b/mesalib/src/glsl/opt_constant_folding.cpp index 072fefe9a..08a47b96b 100644 --- a/mesalib/src/glsl/opt_constant_folding.cpp +++ b/mesalib/src/glsl/opt_constant_folding.cpp @@ -127,8 +127,8 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir) ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *sig_param = (ir_variable *)sig_iter.get(); - if (sig_param->mode == ir_var_function_in - || sig_param->mode == ir_var_const_in) { + if (sig_param->data.mode == ir_var_function_in + || sig_param->data.mode == ir_var_const_in) { ir_rvalue *new_param = param_rval; handle_rvalue(&new_param); diff --git a/mesalib/src/glsl/opt_constant_propagation.cpp b/mesalib/src/glsl/opt_constant_propagation.cpp index 2f65937fe..f1a6fbdaa 100644 --- a/mesalib/src/glsl/opt_constant_propagation.cpp +++ b/mesalib/src/glsl/opt_constant_propagation.cpp @@ -285,8 +285,8 @@ ir_constant_propagation_visitor::visit_enter(ir_call *ir) 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_function_out - && sig_param->mode != ir_var_function_inout) { + if (sig_param->data.mode != ir_var_function_out + && sig_param->data.mode != ir_var_function_inout) { ir_rvalue *new_param = param; handle_rvalue(&new_param); if (new_param != param) diff --git a/mesalib/src/glsl/opt_constant_variable.cpp b/mesalib/src/glsl/opt_constant_variable.cpp index cbe6450c6..a026c51c3 100644 --- a/mesalib/src/glsl/opt_constant_variable.cpp +++ b/mesalib/src/glsl/opt_constant_variable.cpp @@ -137,8 +137,8 @@ ir_constant_variable_visitor::visit_enter(ir_call *ir) ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *param = (ir_variable *)sig_iter.get(); - if (param->mode == ir_var_function_out || - param->mode == ir_var_function_inout) { + if (param->data.mode == ir_var_function_out || + param->data.mode == ir_var_function_inout) { ir_variable *var = param_rval->variable_referenced(); struct assignment_entry *entry; diff --git a/mesalib/src/glsl/opt_copy_propagation.cpp b/mesalib/src/glsl/opt_copy_propagation.cpp index 7282b611e..db5dfc153 100644 --- a/mesalib/src/glsl/opt_copy_propagation.cpp +++ b/mesalib/src/glsl/opt_copy_propagation.cpp @@ -189,8 +189,8 @@ ir_copy_propagation_visitor::visit_enter(ir_call *ir) foreach_iter(exec_list_iterator, iter, ir->actual_parameters) { ir_variable *sig_param = (ir_variable *)sig_param_iter.get(); ir_instruction *ir = (ir_instruction *)iter.get(); - if (sig_param->mode != ir_var_function_out - && sig_param->mode != ir_var_function_inout) { + if (sig_param->data.mode != ir_var_function_out + && sig_param->data.mode != ir_var_function_inout) { ir->accept(this); } sig_param_iter.next(); diff --git a/mesalib/src/glsl/opt_copy_propagation_elements.cpp b/mesalib/src/glsl/opt_copy_propagation_elements.cpp index 6a19da40d..ba8a0f532 100644 --- a/mesalib/src/glsl/opt_copy_propagation_elements.cpp +++ b/mesalib/src/glsl/opt_copy_propagation_elements.cpp @@ -297,8 +297,8 @@ ir_copy_propagation_elements_visitor::visit_enter(ir_call *ir) foreach_iter(exec_list_iterator, iter, ir->actual_parameters) { ir_variable *sig_param = (ir_variable *)sig_param_iter.get(); ir_instruction *ir = (ir_instruction *)iter.get(); - if (sig_param->mode != ir_var_function_out - && sig_param->mode != ir_var_function_inout) { + if (sig_param->data.mode != ir_var_function_out + && sig_param->data.mode != ir_var_function_inout) { ir->accept(this); } sig_param_iter.next(); diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp index 8f73940d8..a2b63ee99 100644 --- a/mesalib/src/glsl/opt_cse.cpp +++ b/mesalib/src/glsl/opt_cse.cpp @@ -193,7 +193,7 @@ is_cse_candidate_visitor::visit(ir_dereference_variable *ir) /* Currently, since we don't handle kills of the ae based on variables * getting assigned, we can only handle constant variables. */ - if (ir->var->read_only) { + if (ir->var->data.read_only) { return visit_continue; } else { ok = false; diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp index b336bc0a8..a939a2b64 100644 --- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp +++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp @@ -85,10 +85,10 @@ public: { ir_variable *var = ir->variable_referenced(); - if (!var || var->mode != this->mode) + if (!var || var->data.mode != this->mode) return visit_continue; - if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) { + if (this->find_frag_outputs && var->data.location == FRAG_RESULT_DATA0) { this->fragdata_array = var; ir_constant *index = ir->array_index->as_constant(); @@ -105,7 +105,7 @@ public: return visit_continue_with_parent; } - if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) { + if (!this->find_frag_outputs && var->data.location == VARYING_SLOT_TEX0) { this->texcoord_array = var; ir_constant *index = ir->array_index->as_constant(); @@ -130,17 +130,17 @@ public: { ir_variable *var = ir->variable_referenced(); - if (var->mode != this->mode || !var->type->is_array()) + if (var->data.mode != this->mode || !var->type->is_array()) return visit_continue; - if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) { + if (this->find_frag_outputs && var->data.location == FRAG_RESULT_DATA0) { /* This is a whole array dereference. */ this->fragdata_usage |= (1 << var->type->array_size()) - 1; this->lower_fragdata_array = false; return visit_continue; } - if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) { + if (!this->find_frag_outputs && var->data.location == VARYING_SLOT_TEX0) { /* This is a whole array dereference like "gl_TexCoord = x;", * there's probably no point in lowering that. */ @@ -152,7 +152,7 @@ public: virtual ir_visitor_status visit(ir_variable *var) { - if (var->mode != this->mode) + if (var->data.mode != this->mode) return visit_continue; /* Nothing to do here for fragment outputs. */ @@ -160,7 +160,7 @@ public: return visit_continue; /* Handle colors and fog. */ - switch (var->location) { + switch (var->data.location) { case VARYING_SLOT_COL0: this->color[0] = var; this->color_usage |= 1; @@ -358,9 +358,9 @@ public: new_var[i] = new(ctx) ir_variable(glsl_type::vec4_type, name, this->info->mode); - new_var[i]->location = start_location + i; - new_var[i]->explicit_location = true; - new_var[i]->explicit_index = 0; + new_var[i]->data.location = start_location + i; + new_var[i]->data.explicit_location = true; + new_var[i]->data.explicit_index = 0; } ir->head->insert_before(new_var[i]); diff --git a/mesalib/src/glsl/opt_dead_code.cpp b/mesalib/src/glsl/opt_dead_code.cpp index b65e5c2ce..a8d8b4a39 100644 --- a/mesalib/src/glsl/opt_dead_code.cpp +++ b/mesalib/src/glsl/opt_dead_code.cpp @@ -79,9 +79,9 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) /* Remove a single dead assignment to the variable we found. * Don't do so if it's a shader or function output, though. */ - if (entry->var->mode != ir_var_function_out && - entry->var->mode != ir_var_function_inout && - entry->var->mode != ir_var_shader_out) { + if (entry->var->data.mode != ir_var_function_out && + entry->var->data.mode != ir_var_function_inout && + entry->var->data.mode != ir_var_shader_out) { entry->assign->remove(); progress = true; @@ -99,7 +99,7 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) * stage. Also, once uniform locations have been assigned, the * declaration cannot be deleted. */ - if (entry->var->mode == ir_var_uniform && + if (entry->var->data.mode == ir_var_uniform && (uniform_locations_assigned || entry->var->constant_value)) continue; diff --git a/mesalib/src/glsl/opt_dead_code_local.cpp b/mesalib/src/glsl/opt_dead_code_local.cpp index 42a30b3d8..43a01662a 100644 --- a/mesalib/src/glsl/opt_dead_code_local.cpp +++ b/mesalib/src/glsl/opt_dead_code_local.cpp @@ -121,7 +121,7 @@ public: */ foreach_iter(exec_list_iterator, iter, *this->assignments) { assignment_entry *entry = (assignment_entry *)iter.get(); - if (entry->lhs->mode == ir_var_shader_out) { + if (entry->lhs->data.mode == ir_var_shader_out) { if (debug) printf("kill %s\n", entry->lhs->name); entry->remove(); diff --git a/mesalib/src/glsl/opt_flip_matrices.cpp b/mesalib/src/glsl/opt_flip_matrices.cpp index 2107b1d47..9044fd680 100644 --- a/mesalib/src/glsl/opt_flip_matrices.cpp +++ b/mesalib/src/glsl/opt_flip_matrices.cpp @@ -104,8 +104,8 @@ matrix_flipper::visit_enter(ir_expression *ir) var_ref->var = texmat_transpose; - texmat_transpose->max_array_access = - MAX2(texmat_transpose->max_array_access, mat_var->max_array_access); + texmat_transpose->data.max_array_access = + MAX2(texmat_transpose->data.max_array_access, mat_var->data.max_array_access); progress = true; } diff --git a/mesalib/src/glsl/opt_function_inlining.cpp b/mesalib/src/glsl/opt_function_inlining.cpp index f8033a095..c8f42a424 100644 --- a/mesalib/src/glsl/opt_function_inlining.cpp +++ b/mesalib/src/glsl/opt_function_inlining.cpp @@ -132,21 +132,21 @@ ir_call::generate_inline(ir_instruction *next_ir) parameters[i] = NULL; } else { parameters[i] = sig_param->clone(ctx, ht); - parameters[i]->mode = ir_var_auto; + parameters[i]->data.mode = ir_var_auto; /* Remove the read-only decoration becuase we're going to write * directly to this variable. If the cloned variable is left * read-only and the inlined function is inside a loop, the loop * analysis code will get confused. */ - parameters[i]->read_only = false; + parameters[i]->data.read_only = false; next_ir->insert_before(parameters[i]); } /* Move the actual param into our param variable if it's an 'in' type. */ - if (parameters[i] && (sig_param->mode == ir_var_function_in || - sig_param->mode == ir_var_const_in || - sig_param->mode == ir_var_function_inout)) { + if (parameters[i] && (sig_param->data.mode == ir_var_function_in || + sig_param->data.mode == ir_var_const_in || + sig_param->data.mode == ir_var_function_inout)) { ir_assignment *assign; assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]), @@ -202,8 +202,8 @@ ir_call::generate_inline(ir_instruction *next_ir) const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get(); /* Move our param variable into the actual param if it's an 'out' type. */ - if (parameters[i] && (sig_param->mode == ir_var_function_out || - sig_param->mode == ir_var_function_inout)) { + if (parameters[i] && (sig_param->data.mode == ir_var_function_out || + sig_param->data.mode == ir_var_function_inout)) { ir_assignment *assign; assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(), diff --git a/mesalib/src/glsl/opt_structure_splitting.cpp b/mesalib/src/glsl/opt_structure_splitting.cpp index 9f4b3dd8f..414f0000d 100644 --- a/mesalib/src/glsl/opt_structure_splitting.cpp +++ b/mesalib/src/glsl/opt_structure_splitting.cpp @@ -103,8 +103,8 @@ ir_structure_reference_visitor::get_variable_entry(ir_variable *var) { assert(var); - if (!var->type->is_record() || var->mode == ir_var_uniform - || var->mode == ir_var_shader_in || var->mode == ir_var_shader_out) + if (!var->type->is_record() || var->data.mode == ir_var_uniform + || var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out) return NULL; foreach_iter(exec_list_iterator, iter, this->variable_list) { diff --git a/mesalib/src/glsl/opt_tree_grafting.cpp b/mesalib/src/glsl/opt_tree_grafting.cpp index 46c06e6c4..6d75a1573 100644 --- a/mesalib/src/glsl/opt_tree_grafting.cpp +++ b/mesalib/src/glsl/opt_tree_grafting.cpp @@ -211,8 +211,8 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir) ir_rvalue *ir = (ir_rvalue *)iter.get(); ir_rvalue *new_ir = ir; - if (sig_param->mode != ir_var_function_in - && sig_param->mode != ir_var_const_in) { + if (sig_param->data.mode != ir_var_function_in + && sig_param->data.mode != ir_var_const_in) { if (check_graft(ir, sig_param) == visit_stop) return visit_stop; continue; @@ -361,9 +361,9 @@ tree_grafting_basic_block(ir_instruction *bb_first, if (!lhs_var) continue; - if (lhs_var->mode == ir_var_function_out || - lhs_var->mode == ir_var_function_inout || - lhs_var->mode == ir_var_shader_out) + if (lhs_var->data.mode == ir_var_function_out || + lhs_var->data.mode == ir_var_function_inout || + lhs_var->data.mode == ir_var_shader_out) continue; ir_variable_refcount_entry *entry = info->refs->get_variable_entry(lhs_var); diff --git a/mesalib/src/glsl/standalone_scaffolding.h b/mesalib/src/glsl/standalone_scaffolding.h index 7afb1c313..9f4818a8a 100644 --- a/mesalib/src/glsl/standalone_scaffolding.h +++ b/mesalib/src/glsl/standalone_scaffolding.h @@ -60,7 +60,7 @@ _mesa_shader_type_to_index(GLenum v) return MESA_SHADER_GEOMETRY; default: assert(!"bad value in _mesa_shader_type_to_index()"); - return MESA_SHADER_TYPES; + return MESA_SHADER_VERTEX; } } |