[Mesa-dev] [PATCH 02/11] glsl: Add link time checks for GLSL precision qualifiers
Ian Romanick
idr at freedesktop.org
Mon Jan 19 19:39:10 PST 2015
On 01/19/2015 03:32 AM, Eduardo Lima Mitev wrote:
> From: Iago Toral Quiroga <itoral at igalia.com>
>
> Currently, we only consider precision qualifiers at compile-time. This patch
> adds precision information to ir_variable so we can also do link time checks.
> Specifically, from the GLSL ES3 spec, 4.5.3 Precision Qualifiers:
>
> "The same uniform declared in different shaders that are linked together
> must have the same precision qualification."
>
> Notice that this patch will check the above also for GLSL ES globals that are
> not uniforms. This is not explicitly stated in the spec, but seems to be
> the only consistent choice: since we can only have one definition of a global
> all its declarations should be identical, including precision qualifiers.
Probably not. In ES you can only have one compilation unit per stage,
so you can never have such a conflict.
> No piglit regressions.
>
> Fixes the following 4 dEQP tests:
> dEQP-GLES3.functional.shaders.linkage.uniform.struct.precision_conflict_1
> dEQP-GLES3.functional.shaders.linkage.uniform.struct.precision_conflict_2
> dEQP-GLES3.functional.shaders.linkage.uniform.struct.precision_conflict_3
> dEQP-GLES3.functional.shaders.linkage.uniform.struct.precision_conflict_4
> ---
> src/glsl/ast_to_hir.cpp | 12 ++++++++++++
> src/glsl/glsl_types.cpp | 4 ++++
> src/glsl/glsl_types.h | 13 +++++++++++++
> src/glsl/ir.h | 15 +++++++++++++++
> src/glsl/linker.cpp | 48 ++++++++++++++++++++++++++++++++++++++++--------
> 5 files changed, 84 insertions(+), 8 deletions(-)
>
> diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
> index 811a955..2b67e14 100644
> --- a/src/glsl/ast_to_hir.cpp
> +++ b/src/glsl/ast_to_hir.cpp
> @@ -2460,6 +2460,10 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
> if (qual->flags.q.sample)
> var->data.sample = 1;
>
> + /* Precision qualifiers do not hold any meaning in Desktop GLSL */
> + if (state->es_shader && qual->precision)
> + var->data.precision = qual->precision;
> +
> if (state->stage == MESA_SHADER_GEOMETRY &&
> qual->flags.q.out && qual->flags.q.stream) {
> var->data.stream = qual->stream;
> @@ -5213,6 +5217,10 @@ ast_process_structure_or_interface_block(exec_list *instructions,
> fields[i].centroid = qual->flags.q.centroid ? 1 : 0;
> fields[i].sample = qual->flags.q.sample ? 1 : 0;
>
> + /* Precision qualifiers do not hold any meaning in Desktop GLSL */
> + fields[i].precision = state->es_shader ? qual->precision :
> + GLSL_PRECISION_NONE;
> +
> /* Only save explicitly defined streams in block's field */
> fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1;
>
> @@ -5688,6 +5696,10 @@ ast_interface_block::hir(exec_list *instructions,
> var->data.sample = fields[i].sample;
> var->init_interface_type(block_type);
>
> + /* Precision qualifiers do not hold any meaning in Desktop GLSL */
> + var->data.precision = state->es_shader ? fields[i].precision :
> + GLSL_PRECISION_NONE;
> +
> if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) {
> var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
> ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
> diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
> index b4223f4..e35c2aa 100644
> --- a/src/glsl/glsl_types.cpp
> +++ b/src/glsl/glsl_types.cpp
> @@ -122,6 +122,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
> this->fields.structure[i].centroid = fields[i].centroid;
> this->fields.structure[i].sample = fields[i].sample;
> this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
> + this->fields.structure[i].precision = fields[i].precision;
> }
>
> mtx_unlock(&glsl_type::mutex);
> @@ -668,6 +669,9 @@ glsl_type::record_compare(const glsl_type *b) const
> if (this->fields.structure[i].sample
> != b->fields.structure[i].sample)
> return false;
> + if (this->fields.structure[i].precision
> + != b->fields.structure[i].precision)
> + return false;
> }
>
> return true;
> diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
> index 441015c..2405006 100644
> --- a/src/glsl/glsl_types.h
> +++ b/src/glsl/glsl_types.h
> @@ -100,6 +100,13 @@ enum glsl_matrix_layout {
> GLSL_MATRIX_LAYOUT_ROW_MAJOR
> };
>
> +enum {
> + GLSL_PRECISION_NONE = 0,
> + GLSL_PRECISION_HIGH,
> + GLSL_PRECISION_MEDIUM,
> + GLSL_PRECISION_LOW
> +};
> +
> #ifdef __cplusplus
> #include "GL/gl.h"
> #include "util/ralloc.h"
> @@ -117,6 +124,7 @@ struct glsl_type {
> * and \c GLSL_TYPE_UINT are valid.
> */
> unsigned interface_packing:2;
> + unsigned precision:2;
Eh... putting precision in the GLSL type doesn't seem right. It seems
that will cause problems with type checking things like:
lowp float x = 1.0;
highp float y = x;
>
> /* Callers of this ralloc-based new need not call delete. It's
> * easier to just ralloc_free 'mem_ctx' (or any of its ancestors). */
> @@ -741,6 +749,11 @@ struct glsl_struct_field {
> * streams (as in ir_variable::stream). -1 otherwise.
> */
> int stream;
> +
> + /**
> + * Precission qualifier
> + */
> + unsigned precision;
> };
>
> static inline unsigned int
> diff --git a/src/glsl/ir.h b/src/glsl/ir.h
> index a0f48b2..b17c244 100644
> --- a/src/glsl/ir.h
> +++ b/src/glsl/ir.h
> @@ -825,6 +825,21 @@ public:
> unsigned max_array_access;
>
> /**
> + * Precision qualifier.
> + *
> + * In desktop GLSL we do not care about precision qualifiers at all, in
> + * fact the spec does not care about some incoherent uses of qualifiers
> + * that do raise an error in GLSL ES (specifically, declaring the same
> + * uniform in multiple shaders with different precision qualifiers).
Instead, I would say, "in fact, the spec says that precision qualifiers
are ignored."
> + *
> + * To make things easy, we make it so that this field is always
> + * GLSL_PRECISION_NONE on desktop shaders. This way all the variables
> + * have the same precision value and the checks we add in the compiler
> + * for this field will never break a desktop shader compile.
> + */
> + unsigned precision;
I'm not very comfortable putting this in ir_variable. This class is one
of the main sources of memory (over-)usage in the compiler. Making
every ir_variable 4 bytes bigger is pretty painful.
Unless we can come up with a different way, I think I'm going to have to
make subclassing ir_variable work. This hasn't already been done
because we don't know the kind of ir_variable (e.g., local, uniform,
shader input, etc.) until after we allocate the object and add it to the
symbol table.
> +
> + /**
> * Allow (only) ir_variable direct access private members.
> */
> friend class ir_variable;
> diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
> index 3f5eac1..485b7e1 100644
> --- a/src/glsl/linker.cpp
> +++ b/src/glsl/linker.cpp
> @@ -756,14 +756,23 @@ cross_validate_globals(struct gl_shader_program *prog,
> && existing->type->is_record()
> && existing->type->record_compare(var->type)) {
> existing->type = var->type;
> - } else {
> - linker_error(prog, "%s `%s' declared as type "
> - "`%s' and type `%s'\n",
> - mode_string(var),
> - var->name, var->type->name,
> - existing->type->name);
> - return;
> - }
> + } else if (strcmp(var->type->name, existing->type->name)) {
> + linker_error(prog, "%s `%s' declared as type "
> + "`%s' and type `%s'\n",
> + mode_string(var),
> + var->name, var->type->name,
> + existing->type->name);
> + return;
> + } else {
> + /* The global is declared with the same type name but the type
> + * declarations mismatch (e.g. the same struct type name, but
> + * the actual struct declarations mismatch).
> + */
> + linker_error(prog, "%s `%s' declared with mismatching definitions "
> + "of type `%s'\n",
> + mode_string(var), var->name, var->type->name);
> + return;
> + }
> }
>
> if (var->data.explicit_location) {
> @@ -918,6 +927,29 @@ cross_validate_globals(struct gl_shader_program *prog,
> mode_string(var), var->name);
> return;
> }
> + /* From the GLSL ES3 spec, 4.5.3 Precision qualifiers:
> + *
> + * "The same uniform declared in different shaders that are linked
> + * together must have the same precision qualification."
> + *
> + * In the GLSL ES2 spec this was resolved in the issue amendments
> + * (10.3 Precision Qualifiers). The GLSL ES1 spec overlooked this,
> + * but seems like an obvious error since we can only have one
> + * consistent definition of a global.
> + *
> + * The desktop GLSL spec does not include this reference, probably
> + * because it basically ignores precision qualifiers. We will never
* The desktop GLSL spec does not include this reference
* because precision qualifiers are ignored. We will never
> + * hit this scenario in desktop GLSL though because we always set
> + * the precision of variables to GLSL_PRECISION_NONE.
> + */
> + if (var->data.mode == ir_var_uniform) {
> + if (existing->data.precision != var->data.precision) {
> + linker_error(prog, "declarations for %s `%s` have "
> + "mismatching precision qualifiers\n",
> + mode_string(var), var->name);
> + return;
> + }
> + }
> } else
> variables.add_variable(var);
> }
>
More information about the mesa-dev
mailing list