return visit_continue;
ir_variable *var = ir->variable_referenced();
- /* We can have image_write_only set on both images and buffer variables,
+ /* We can have memory_write_only set on both images and buffer variables,
* but in the former there is a distinction between reads from
* the variable itself (write_only) and from the memory they point to
- * (image_write_only), while in the case of buffer variables there is
+ * (memory_write_only), while in the case of buffer variables there is
* no such distinction, that is why this check here is limited to
* buffer variables alone.
*/
if (!var || var->data.mode != ir_var_shader_storage)
return visit_continue;
- if (var->data.image_write_only) {
+ if (var->data.memory_write_only) {
found = var;
return visit_stop;
}
* type of both operands must be float.
*/
assert(type_a->is_matrix() || type_b->is_matrix());
- assert(type_a->base_type == GLSL_TYPE_FLOAT ||
- type_a->base_type == GLSL_TYPE_DOUBLE);
- assert(type_b->base_type == GLSL_TYPE_FLOAT ||
- type_b->base_type == GLSL_TYPE_DOUBLE);
+ assert(type_a->is_float() || type_a->is_double());
+ assert(type_b->is_float() || type_b->is_double());
/* "* The operator is add (+), subtract (-), or divide (/), and the
* operands are matrices with the same number of rows and the same
error_emitted = true;
} else if (lhs_var != NULL && (lhs_var->data.read_only ||
(lhs_var->data.mode == ir_var_shader_storage &&
- lhs_var->data.image_read_only))) {
- /* We can have image_read_only set on both images and buffer variables,
+ lhs_var->data.memory_read_only))) {
+ /* We can have memory_read_only set on both images and buffer variables,
* but in the former there is a distinction between assignments to
* the variable itself (read_only) and to the memory they point to
- * (image_read_only), while in the case of buffer variables there is
+ * (memory_read_only), while in the case of buffer variables there is
* no such distinction, that is why this check here is limited to
* buffer variables alone.
*/
* in a scalar boolean. See page 57 of the GLSL 1.50 spec.
*/
assert(type->is_error()
- || ((type->base_type == GLSL_TYPE_BOOL)
- && type->is_scalar()));
+ || (type->is_boolean() && type->is_scalar()));
result = new(ctx) ir_expression(operations[this->oper], type,
op[0], op[1]);
case GLSL_TYPE_SAMPLER: {
const unsigned type_idx =
type->sampler_array + 2 * type->sampler_shadow;
- const unsigned offset = type->base_type == GLSL_TYPE_SAMPLER ? 0 : 4;
+ const unsigned offset = type->is_sampler() ? 0 : 4;
assert(type_idx < 4);
switch (type->sampled_type) {
case GLSL_TYPE_FLOAT:
switch (type->sampler_dimensionality) {
case GLSL_SAMPLER_DIM_1D: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"sampler1D", "sampler1DArray",
"sampler1DShadow", "sampler1DArrayShadow"
return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_MS: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"sampler2DMS", "sampler2DMSArray", NULL, NULL
};
return names[type_idx];
}
case GLSL_SAMPLER_DIM_RECT: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"samplerRect", NULL, "samplerRectShadow", NULL
};
return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_EXTERNAL: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"samplerExternalOES", NULL, NULL, NULL
};
case GLSL_TYPE_INT:
switch (type->sampler_dimensionality) {
case GLSL_SAMPLER_DIM_1D: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"isampler1D", "isampler1DArray", NULL, NULL
};
return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_MS: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"isampler2DMS", "isampler2DMSArray", NULL, NULL
};
return names[type_idx];
}
case GLSL_SAMPLER_DIM_RECT: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"isamplerRect", NULL, "isamplerRectShadow", NULL
};
case GLSL_TYPE_UINT:
switch (type->sampler_dimensionality) {
case GLSL_SAMPLER_DIM_1D: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"usampler1D", "usampler1DArray", NULL, NULL
};
return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_MS: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"usampler2DMS", "usampler2DMSArray", NULL, NULL
};
return names[type_idx];
}
case GLSL_SAMPLER_DIM_RECT: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"usamplerRect", NULL, "usamplerRectShadow", NULL
};
* declare an atomic type with a different precision or to specify the
* default precision for an atomic type to be lowp or mediump."
*/
- if (type->base_type == GLSL_TYPE_ATOMIC_UINT &&
- precision != ast_precision_high) {
+ if (type->is_atomic_uint() && precision != ast_precision_high) {
_mesa_glsl_error(loc, state,
"atomic_uint can only have highp precision qualifier");
}
assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS);
if (qual_binding >= ctx->Const.MaxAtomicBufferBindings) {
_mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the "
- " maximum number of atomic counter buffer bindings"
+ "maximum number of atomic counter buffer bindings "
"(%u)", qual_binding,
ctx->Const.MaxAtomicBufferBindings);
assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS);
if (max_index >= ctx->Const.MaxImageUnits) {
_mesa_glsl_error(loc, state, "Image binding %d exceeds the "
- " maximum number of image units (%d)", max_index,
+ "maximum number of image units (%d)", max_index,
ctx->Const.MaxImageUnits);
return;
}
} else {
_mesa_glsl_error(loc, state,
"the \"binding\" qualifier only applies to uniform "
- "blocks, opaque variables, or arrays thereof");
+ "blocks, storage blocks, opaque variables, or arrays "
+ "thereof");
return;
}
return;
}
+static void
+validate_fragment_flat_interpolation_input(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ const glsl_interp_mode interpolation,
+ const struct glsl_type *var_type,
+ ir_variable_mode mode)
+{
+ if (state->stage != MESA_SHADER_FRAGMENT ||
+ interpolation == INTERP_MODE_FLAT ||
+ mode != ir_var_shader_in)
+ return;
+
+ /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES,
+ * so must integer vertex outputs.
+ *
+ * From section 4.3.4 ("Inputs") of the GLSL 1.50 spec:
+ * "Fragment shader inputs that are signed or unsigned integers or
+ * integer vectors must be qualified with the interpolation qualifier
+ * flat."
+ *
+ * From section 4.3.4 ("Input Variables") of the GLSL 3.00 ES spec:
+ * "Fragment shader inputs that are, or contain, signed or unsigned
+ * integers or integer vectors must be qualified with the
+ * interpolation qualifier flat."
+ *
+ * From section 4.3.6 ("Output Variables") of the GLSL 3.00 ES spec:
+ * "Vertex shader outputs that are, or contain, signed or unsigned
+ * integers or integer vectors must be qualified with the
+ * interpolation qualifier flat."
+ *
+ * Note that prior to GLSL 1.50, this requirement applied to vertex
+ * outputs rather than fragment inputs. That creates problems in the
+ * presence of geometry shaders, so we adopt the GLSL 1.50 rule for all
+ * desktop GL shaders. For GLSL ES shaders, we follow the spec and
+ * apply the restriction to both vertex outputs and fragment inputs.
+ *
+ * Note also that the desktop GLSL specs are missing the text "or
+ * contain"; this is presumably an oversight, since there is no
+ * reasonable way to interpolate a fragment shader input that contains
+ * an integer. See Khronos bug #15671.
+ */
+ if (state->is_version(130, 300)
+ && var_type->contains_integer()) {
+ _mesa_glsl_error(loc, state, "if a fragment input is (or contains) "
+ "an integer, then it must be qualified with 'flat'");
+ }
+
+ /* Double fragment inputs must be qualified with 'flat'.
+ *
+ * From the "Overview" of the ARB_gpu_shader_fp64 extension spec:
+ * "This extension does not support interpolation of double-precision
+ * values; doubles used as fragment shader inputs must be qualified as
+ * "flat"."
+ *
+ * From section 4.3.4 ("Inputs") of the GLSL 4.00 spec:
+ * "Fragment shader inputs that are signed or unsigned integers, integer
+ * vectors, or any double-precision floating-point type must be
+ * qualified with the interpolation qualifier flat."
+ *
+ * Note that the GLSL specs are missing the text "or contain"; this is
+ * presumably an oversight. See Khronos bug #15671.
+ *
+ * The 'double' type does not exist in GLSL ES so far.
+ */
+ if (state->has_double()
+ && var_type->contains_double()) {
+ _mesa_glsl_error(loc, state, "if a fragment input is (or contains) "
+ "a double, then it must be qualified with 'flat'");
+ }
+}
static void
validate_interpolation_qualifier(struct _mesa_glsl_parse_state *state,
"deprecated storage qualifier '%s'", i, s);
}
- /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES,
- * so must integer vertex outputs.
- *
- * From section 4.3.4 ("Inputs") of the GLSL 1.50 spec:
- * "Fragment shader inputs that are signed or unsigned integers or
- * integer vectors must be qualified with the interpolation qualifier
- * flat."
- *
- * From section 4.3.4 ("Input Variables") of the GLSL 3.00 ES spec:
- * "Fragment shader inputs that are, or contain, signed or unsigned
- * integers or integer vectors must be qualified with the
- * interpolation qualifier flat."
- *
- * From section 4.3.6 ("Output Variables") of the GLSL 3.00 ES spec:
- * "Vertex shader outputs that are, or contain, signed or unsigned
- * integers or integer vectors must be qualified with the
- * interpolation qualifier flat."
- *
- * Note that prior to GLSL 1.50, this requirement applied to vertex
- * outputs rather than fragment inputs. That creates problems in the
- * presence of geometry shaders, so we adopt the GLSL 1.50 rule for all
- * desktop GL shaders. For GLSL ES shaders, we follow the spec and
- * apply the restriction to both vertex outputs and fragment inputs.
- *
- * Note also that the desktop GLSL specs are missing the text "or
- * contain"; this is presumably an oversight, since there is no
- * reasonable way to interpolate a fragment shader input that contains
- * an integer. See Khronos bug #15671.
- */
- if (state->is_version(130, 300)
- && var_type->contains_integer()
- && interpolation != INTERP_MODE_FLAT
- && state->stage == MESA_SHADER_FRAGMENT
- && mode == ir_var_shader_in) {
- _mesa_glsl_error(loc, state, "if a fragment input is (or contains) "
- "an integer, then it must be qualified with 'flat'");
- }
-
- /* Double fragment inputs must be qualified with 'flat'.
- *
- * From the "Overview" of the ARB_gpu_shader_fp64 extension spec:
- * "This extension does not support interpolation of double-precision
- * values; doubles used as fragment shader inputs must be qualified as
- * "flat"."
- *
- * From section 4.3.4 ("Inputs") of the GLSL 4.00 spec:
- * "Fragment shader inputs that are signed or unsigned integers, integer
- * vectors, or any double-precision floating-point type must be
- * qualified with the interpolation qualifier flat."
- *
- * Note that the GLSL specs are missing the text "or contain"; this is
- * presumably an oversight. See Khronos bug #15671.
- *
- * The 'double' type does not exist in GLSL ES so far.
- */
- if (state->has_double()
- && var_type->contains_double()
- && interpolation != INTERP_MODE_FLAT
- && state->stage == MESA_SHADER_FRAGMENT
- && mode == ir_var_shader_in) {
- _mesa_glsl_error(loc, state, "if a fragment input is (or contains) "
- "a double, then it must be qualified with 'flat'");
- }
+ validate_fragment_flat_interpolation_input(state, loc, interpolation,
+ var_type, mode);
}
static glsl_interp_mode
}
/* Check if index was set for the uniform instead of the function */
- if (qual->flags.q.explicit_index && qual->flags.q.subroutine) {
+ if (qual->flags.q.explicit_index && qual->is_subroutine_decl()) {
_mesa_glsl_error(loc, state, "an index qualifier can only be "
"used with subroutine functions");
return;
}
}
+static bool
+validate_storage_for_sampler_image_types(ir_variable *var,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc)
+{
+ /* From section 4.1.7 of the GLSL 4.40 spec:
+ *
+ * "[Opaque types] can only be declared as function
+ * parameters or uniform-qualified variables."
+ *
+ * From section 4.1.7 of the ARB_bindless_texture spec:
+ *
+ * "Samplers may be declared as shader inputs and outputs, as uniform
+ * variables, as temporary variables, and as function parameters."
+ *
+ * From section 4.1.X of the ARB_bindless_texture spec:
+ *
+ * "Images may be declared as shader inputs and outputs, as uniform
+ * variables, as temporary variables, and as function parameters."
+ */
+ if (state->has_bindless()) {
+ if (var->data.mode != ir_var_auto &&
+ var->data.mode != ir_var_uniform &&
+ var->data.mode != ir_var_shader_in &&
+ var->data.mode != ir_var_shader_out &&
+ var->data.mode != ir_var_function_in &&
+ var->data.mode != ir_var_function_out &&
+ var->data.mode != ir_var_function_inout) {
+ _mesa_glsl_error(loc, state, "bindless image/sampler variables may "
+ "only be declared as shader inputs and outputs, as "
+ "uniform variables, as temporary variables and as "
+ "function parameters");
+ return false;
+ }
+ } else {
+ if (var->data.mode != ir_var_uniform &&
+ var->data.mode != ir_var_function_in) {
+ _mesa_glsl_error(loc, state, "image/sampler variables may only be "
+ "declared as function parameters or "
+ "uniform-qualified global variables");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool
+validate_memory_qualifier_for_type(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ const struct ast_type_qualifier *qual,
+ const glsl_type *type)
+{
+ /* From Section 4.10 (Memory Qualifiers) of the GLSL 4.50 spec:
+ *
+ * "Memory qualifiers are only supported in the declarations of image
+ * variables, buffer variables, and shader storage blocks; it is an error
+ * to use such qualifiers in any other declarations.
+ */
+ if (!type->is_image() && !qual->flags.q.buffer) {
+ if (qual->flags.q.read_only ||
+ qual->flags.q.write_only ||
+ qual->flags.q.coherent ||
+ qual->flags.q._volatile ||
+ qual->flags.q.restrict_flag) {
+ _mesa_glsl_error(loc, state, "memory qualifiers may only be applied "
+ "in the declarations of image variables, buffer "
+ "variables, and shader storage blocks");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool
+validate_image_format_qualifier_for_type(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ const struct ast_type_qualifier *qual,
+ const glsl_type *type)
+{
+ /* From section 4.4.6.2 (Format Layout Qualifiers) of the GLSL 4.50 spec:
+ *
+ * "Format layout qualifiers can be used on image variable declarations
+ * (those declared with a basic type having “image ” in its keyword)."
+ */
+ if (!type->is_image() && qual->flags.q.explicit_image_format) {
+ _mesa_glsl_error(loc, state, "format layout qualifiers may only be "
+ "applied to images");
+ return false;
+ }
+ return true;
+}
+
static void
apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
ir_variable *var,
{
const glsl_type *base_type = var->type->without_array();
- if (base_type->is_image()) {
- if (var->data.mode != ir_var_uniform &&
- var->data.mode != ir_var_function_in) {
- _mesa_glsl_error(loc, state, "image variables may only be declared as "
- "function parameters or uniform-qualified "
- "global variables");
- }
+ if (!validate_image_format_qualifier_for_type(state, loc, qual, base_type) ||
+ !validate_memory_qualifier_for_type(state, loc, qual, base_type))
+ return;
- var->data.image_read_only |= qual->flags.q.read_only;
- var->data.image_write_only |= qual->flags.q.write_only;
- var->data.image_coherent |= qual->flags.q.coherent;
- var->data.image_volatile |= qual->flags.q._volatile;
- var->data.image_restrict |= qual->flags.q.restrict_flag;
- var->data.read_only = true;
+ if (!base_type->is_image())
+ return;
- if (qual->flags.q.explicit_image_format) {
- if (var->data.mode == ir_var_function_in) {
- _mesa_glsl_error(loc, state, "format qualifiers cannot be "
- "used on image function parameters");
- }
+ if (!validate_storage_for_sampler_image_types(var, state, loc))
+ return;
- if (qual->image_base_type != base_type->sampled_type) {
- _mesa_glsl_error(loc, state, "format qualifier doesn't match the "
- "base data type of the image");
- }
+ var->data.memory_read_only |= qual->flags.q.read_only;
+ var->data.memory_write_only |= qual->flags.q.write_only;
+ var->data.memory_coherent |= qual->flags.q.coherent;
+ var->data.memory_volatile |= qual->flags.q._volatile;
+ var->data.memory_restrict |= qual->flags.q.restrict_flag;
- var->data.image_format = qual->image_format;
- } else {
- if (var->data.mode == ir_var_uniform) {
- if (state->es_shader) {
- _mesa_glsl_error(loc, state, "all image uniforms "
- "must have a format layout qualifier");
+ if (qual->flags.q.explicit_image_format) {
+ if (var->data.mode == ir_var_function_in) {
+ _mesa_glsl_error(loc, state, "format qualifiers cannot be used on "
+ "image function parameters");
+ }
- } else if (!qual->flags.q.write_only) {
- _mesa_glsl_error(loc, state, "image uniforms not qualified with "
- "`writeonly' must have a format layout "
- "qualifier");
- }
- }
+ if (qual->image_base_type != base_type->sampled_type) {
+ _mesa_glsl_error(loc, state, "format qualifier doesn't match the base "
+ "data type of the image");
+ }
- var->data.image_format = GL_NONE;
+ var->data.image_format = qual->image_format;
+ } else {
+ if (var->data.mode == ir_var_uniform) {
+ if (state->es_shader) {
+ _mesa_glsl_error(loc, state, "all image uniforms must have a "
+ "format layout qualifier");
+ } else if (!qual->flags.q.write_only) {
+ _mesa_glsl_error(loc, state, "image uniforms not qualified with "
+ "`writeonly' must have a format layout qualifier");
+ }
}
+ var->data.image_format = GL_NONE;
+ }
- /* From page 70 of the GLSL ES 3.1 specification:
- *
- * "Except for image variables qualified with the format qualifiers
- * r32f, r32i, and r32ui, image variables must specify either memory
- * qualifier readonly or the memory qualifier writeonly."
- */
- if (state->es_shader &&
- var->data.image_format != GL_R32F &&
- var->data.image_format != GL_R32I &&
- var->data.image_format != GL_R32UI &&
- !var->data.image_read_only &&
- !var->data.image_write_only) {
- _mesa_glsl_error(loc, state, "image variables of format other than "
- "r32f, r32i or r32ui must be qualified `readonly' or "
- "`writeonly'");
- }
-
- } else if (qual->flags.q.read_only ||
- qual->flags.q.write_only ||
- qual->flags.q.coherent ||
- qual->flags.q._volatile ||
- qual->flags.q.restrict_flag ||
- qual->flags.q.explicit_image_format) {
- _mesa_glsl_error(loc, state, "memory qualifiers may only be applied to "
- "images");
+ /* From page 70 of the GLSL ES 3.1 specification:
+ *
+ * "Except for image variables qualified with the format qualifiers r32f,
+ * r32i, and r32ui, image variables must specify either memory qualifier
+ * readonly or the memory qualifier writeonly."
+ */
+ if (state->es_shader &&
+ var->data.image_format != GL_R32F &&
+ var->data.image_format != GL_R32I &&
+ var->data.image_format != GL_R32UI &&
+ !var->data.memory_read_only &&
+ !var->data.memory_write_only) {
+ _mesa_glsl_error(loc, state, "image variables of format other than r32f, "
+ "r32i or r32ui must be qualified `readonly' or "
+ "`writeonly'");
}
}
}
}
+static void
+apply_bindless_qualifier_to_variable(const struct ast_type_qualifier *qual,
+ ir_variable *var,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc)
+{
+ bool has_local_qualifiers = qual->flags.q.bindless_sampler ||
+ qual->flags.q.bindless_image ||
+ qual->flags.q.bound_sampler ||
+ qual->flags.q.bound_image;
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "Modify Section 4.4.6 Opaque-Uniform Layout Qualifiers of the GLSL 4.30
+ * spec"
+ *
+ * "If these layout qualifiers are applied to other types of default block
+ * uniforms, or variables with non-uniform storage, a compile-time error
+ * will be generated."
+ */
+ if (has_local_qualifiers && !qual->flags.q.uniform) {
+ _mesa_glsl_error(loc, state, "ARB_bindless_texture layout qualifiers "
+ "can only be applied to default block uniforms or "
+ "variables with uniform storage");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec doesn't state anything in this situation,
+ * but it makes sense to only allow bindless_sampler/bound_sampler for
+ * sampler types, and respectively bindless_image/bound_image for image
+ * types.
+ */
+ if ((qual->flags.q.bindless_sampler || qual->flags.q.bound_sampler) &&
+ !var->type->contains_sampler()) {
+ _mesa_glsl_error(loc, state, "bindless_sampler or bound_sampler can only "
+ "be applied to sampler types");
+ return;
+ }
+
+ if ((qual->flags.q.bindless_image || qual->flags.q.bound_image) &&
+ !var->type->contains_image()) {
+ _mesa_glsl_error(loc, state, "bindless_image or bound_image can only be "
+ "applied to image types");
+ return;
+ }
+
+ /* The bindless_sampler/bindless_image (and respectively
+ * bound_sampler/bound_image) layout qualifiers can be set at global and at
+ * local scope.
+ */
+ if (var->type->contains_sampler() || var->type->contains_image()) {
+ var->data.bindless = qual->flags.q.bindless_sampler ||
+ qual->flags.q.bindless_image ||
+ state->bindless_sampler_specified ||
+ state->bindless_image_specified;
+
+ var->data.bound = qual->flags.q.bound_sampler ||
+ qual->flags.q.bound_image ||
+ state->bound_sampler_specified ||
+ state->bound_image_specified;
+ }
+}
+
static void
apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
ir_variable *var,
}
}
} else if (qual->flags.q.explicit_index) {
- if (!qual->flags.q.subroutine_def)
+ if (!qual->subroutine_list)
_mesa_glsl_error(loc, state,
"explicit index requires explicit location");
} else if (qual->flags.q.explicit_component) {
}
}
+ if (var->type->contains_sampler() &&
+ !validate_storage_for_sampler_image_types(var, state, loc))
+ return;
+
/* Is the 'layout' keyword used with parameters that allow relaxed checking.
* Many implementations of GL_ARB_fragment_coord_conventions_enable and some
* implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable
/* Layout qualifiers for gl_FragDepth, which are enabled by extension
* AMD_conservative_depth.
*/
- int depth_layout_count = qual->flags.q.depth_any
- + qual->flags.q.depth_greater
- + qual->flags.q.depth_less
- + qual->flags.q.depth_unchanged;
- if (depth_layout_count > 0
+ if (qual->flags.q.depth_type
&& !state->is_version(420, 0)
&& !state->AMD_conservative_depth_enable
&& !state->ARB_conservative_depth_enable) {
"extension GL_AMD_conservative_depth or "
"GL_ARB_conservative_depth must be enabled "
"to use depth layout qualifiers");
- } else if (depth_layout_count > 0
+ } else if (qual->flags.q.depth_type
&& strcmp(var->name, "gl_FragDepth") != 0) {
_mesa_glsl_error(loc, state,
"depth layout qualifiers can be applied only to "
"gl_FragDepth");
- } else if (depth_layout_count > 1
- && strcmp(var->name, "gl_FragDepth") == 0) {
- _mesa_glsl_error(loc, state,
- "at most one depth layout qualifier can be applied to "
- "gl_FragDepth");
}
- if (qual->flags.q.depth_any)
+
+ switch (qual->depth_type) {
+ case ast_depth_any:
var->data.depth_layout = ir_depth_layout_any;
- else if (qual->flags.q.depth_greater)
+ break;
+ case ast_depth_greater:
var->data.depth_layout = ir_depth_layout_greater;
- else if (qual->flags.q.depth_less)
+ break;
+ case ast_depth_less:
var->data.depth_layout = ir_depth_layout_less;
- else if (qual->flags.q.depth_unchanged)
- var->data.depth_layout = ir_depth_layout_unchanged;
- else
- var->data.depth_layout = ir_depth_layout_none;
+ break;
+ case ast_depth_unchanged:
+ var->data.depth_layout = ir_depth_layout_unchanged;
+ break;
+ default:
+ var->data.depth_layout = ir_depth_layout_none;
+ break;
+ }
if (qual->flags.q.std140 ||
qual->flags.q.std430 ||
_mesa_glsl_error(loc, state, "post_depth_coverage layout qualifier only "
"valid in fragment shader input layout declaration.");
}
+
+ if (state->has_bindless())
+ apply_bindless_qualifier_to_variable(qual, var, state, loc);
}
static void
}
}
- if (qual->flags.q.subroutine && !qual->flags.q.uniform) {
+ if (qual->is_subroutine_decl() && !qual->flags.q.uniform) {
_mesa_glsl_error(loc, state,
"`subroutine' may only be applied to uniforms, "
"subroutine type declarations, or function definitions");
* 3.00 spec allows structs as well. Varying structs are also allowed
* in GLSL 1.50.
*/
- switch (var->type->get_scalar_type()->base_type) {
+ switch (var->type->without_array()->base_type) {
case GLSL_TYPE_FLOAT:
/* Ok in all GLSL versions */
break;
}
/**
- * Get the variable that is being redeclared by this declaration
+ * Get the variable that is being redeclared by this declaration or if it
+ * does not exist, the current declared variable.
*
* Semantic checks to verify the validity of the redeclaration are also
* performed. If semantic checks fail, compilation error will be emitted via
*
* \returns
* A pointer to an existing variable in the current scope if the declaration
- * is a redeclaration, \c NULL otherwise.
+ * is a redeclaration, current variable otherwise. \c is_declared boolean
+ * will return \c true if the declaration is a redeclaration, \c false
+ * otherwise.
*/
static ir_variable *
get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
struct _mesa_glsl_parse_state *state,
- bool allow_all_redeclarations)
+ bool allow_all_redeclarations,
+ bool *is_redeclaration)
{
/* Check if this declaration is actually a re-declaration, either to
* resize an array or add qualifiers to an existing variable.
if (earlier == NULL ||
(state->current_function != NULL &&
!state->symbols->name_declared_this_scope(var->name))) {
- return NULL;
+ *is_redeclaration = false;
+ return var;
}
+ *is_redeclaration = true;
/* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
*
if (var->data.patch)
return;
- var->data.tess_varying_implicit_sized_array = var->type->is_unsized_array();
-
validate_layout_qualifier_vertex_count(state, loc, var, num_vertices,
&state->tcs_output_size,
"tessellation control shader output");
if (var->type->is_unsized_array()) {
var->type = glsl_type::get_array_instance(var->type->fields.array,
state->Const.MaxPatchVertices);
- var->data.tess_varying_implicit_sized_array = true;
} else if (var->type->length != state->Const.MaxPatchVertices) {
_mesa_glsl_error(&loc, state,
"per-vertex tessellation shader input arrays must be "
"invalid type `%s' in empty declaration",
type_name);
} else {
- if (decl_type->base_type == GLSL_TYPE_ARRAY) {
+ if (decl_type->is_array()) {
/* From Section 13.22 (Array Declarations) of the GLSL ES 3.2
* spec:
*
validate_array_dimensions(decl_type, state, &loc);
}
- if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) {
+ if (decl_type->is_atomic_uint()) {
/* Empty atomic counter declarations are allowed and useful
* to set the default offset qualifier.
*/
continue;
}
- if (this->type->qualifier.flags.q.subroutine) {
+ if (this->type->qualifier.is_subroutine_decl()) {
const glsl_type *t;
const char *name;
if ((var->data.mode == ir_var_auto || var->data.mode == ir_var_temporary)
&& (var->type->is_numeric() || var->type->is_boolean())
&& state->zero_init) {
- const ir_constant_data data = {0};
+ const ir_constant_data data = { { 0 } };
var->data.has_initializer = true;
var->constant_initializer = new(var) ir_constant(var->type, &data);
}
*/
if (this->type->qualifier.flags.q.attribute) {
mode = "attribute";
- } else if (this->type->qualifier.flags.q.subroutine) {
+ } else if (this->type->qualifier.is_subroutine_decl()) {
mode = "subroutine uniform";
} else if (this->type->qualifier.flags.q.uniform) {
mode = "uniform";
if (state->is_version(120, 300))
break;
case GLSL_TYPE_DOUBLE:
- if (check_type->base_type == GLSL_TYPE_DOUBLE && (state->is_version(410, 0) || state->ARB_vertex_attrib_64bit_enable))
+ if (check_type->is_double() && (state->is_version(410, 0) || state->ARB_vertex_attrib_64bit_enable))
break;
/* FALLTHROUGH */
default:
} else if (var->data.mode == ir_var_shader_out) {
const glsl_type *check_type = var->type->without_array();
- /* From section 4.3.6 (Output variables) of the GLSL 4.40 spec:
- *
- * It is a compile-time error to declare a vertex, tessellation
- * evaluation, tessellation control, or geometry shader output
- * that contains any of the following:
- *
- * * A Boolean type (bool, bvec2 ...)
- * * An opaque type
- */
- if (check_type->is_boolean() || check_type->contains_opaque())
- _mesa_glsl_error(&loc, state,
- "%s shader output cannot have type %s",
- _mesa_shader_stage_to_string(state->stage),
- check_type->name);
-
/* From section 4.3.6 (Output variables) of the GLSL 4.40 spec:
*
* It is a compile-time error to declare a fragment shader output
*
* "[Opaque types] can only be declared as function
* parameters or uniform-qualified variables."
+ *
+ * From section 4.1.7 of the ARB_bindless_texture spec:
+ *
+ * "Samplers may be declared as shader inputs and outputs, as uniform
+ * variables, as temporary variables, and as function parameters."
+ *
+ * From section 4.1.X of the ARB_bindless_texture spec:
+ *
+ * "Images may be declared as shader inputs and outputs, as uniform
+ * variables, as temporary variables, and as function parameters."
*/
- if (var_type->contains_opaque() &&
- !this->type->qualifier.flags.q.uniform) {
+ if (!this->type->qualifier.flags.q.uniform &&
+ (var_type->contains_atomic() ||
+ (!state->has_bindless() && var_type->contains_opaque()))) {
_mesa_glsl_error(&loc, state,
- "opaque variables must be declared uniform");
+ "%s variables must be declared uniform",
+ state->has_bindless() ? "atomic" : "opaque");
}
/* Process the initializer and add its instructions to a temporary
/* Examine var name here since var may get deleted in the next call */
bool var_is_gl_id = is_gl_identifier(var->name);
- ir_variable *earlier =
+ bool is_redeclaration;
+ ir_variable *declared_var =
get_variable_being_redeclared(var, decl->get_location(), state,
- false /* allow_all_redeclarations */);
- if (earlier != NULL) {
+ false /* allow_all_redeclarations */,
+ &is_redeclaration);
+ if (is_redeclaration) {
if (var_is_gl_id &&
- earlier->data.how_declared == ir_var_declared_in_block) {
+ declared_var->data.how_declared == ir_var_declared_in_block) {
_mesa_glsl_error(&loc, state,
"`%s' has already been redeclared using "
- "gl_PerVertex", earlier->name);
+ "gl_PerVertex", declared_var->name);
}
- earlier->data.how_declared = ir_var_declared_normally;
+ declared_var->data.how_declared = ir_var_declared_normally;
}
if (decl->initializer != NULL) {
- result = process_initializer((earlier == NULL) ? var : earlier,
+ result = process_initializer(declared_var,
decl, this->type,
&initializer_instructions, state);
} else {
}
if (state->es_shader) {
- const glsl_type *const t = (earlier == NULL)
- ? var->type : earlier->type;
+ const glsl_type *const t = declared_var->type;
/* Skip the unsized array check for TCS/TES/GS inputs & TCS outputs.
*
* present, as per the following table."
*/
const bool implicitly_sized =
- (var->data.mode == ir_var_shader_in &&
+ (declared_var->data.mode == ir_var_shader_in &&
state->stage >= MESA_SHADER_TESS_CTRL &&
state->stage <= MESA_SHADER_GEOMETRY) ||
- (var->data.mode == ir_var_shader_out &&
+ (declared_var->data.mode == ir_var_shader_out &&
state->stage == MESA_SHADER_TESS_CTRL);
if (t->is_unsized_array() && !implicitly_sized)
* semantic checks that must be applied. In addition, variable that was
* created for the declaration should be added to the IR stream.
*/
- if (earlier == NULL) {
+ if (!is_redeclaration) {
validate_identifier(decl->identifier, loc, state);
/* Add the variable to the symbol table. Note that the initializer's
* after the initializer if present or immediately after the name
* being declared if not."
*/
- if (!state->symbols->add_variable(var)) {
+ if (!state->symbols->add_variable(declared_var)) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state, "name `%s' already taken in the "
"current scope", decl->identifier);
* global var is decled, then the function is defined with usage of
* the global var. See glslparsertest's CorrectModule.frag.
*/
- instructions->push_head(var);
+ instructions->push_head(declared_var);
}
instructions->append_list(&initializer_instructions);
* "Opaque variables cannot be treated as l-values; hence cannot
* be used as out or inout function parameters, nor can they be
* assigned into."
+ *
+ * From section 4.1.7 of the ARB_bindless_texture spec:
+ *
+ * "Samplers can be used as l-values, so can be assigned into and used
+ * as "out" and "inout" function parameters."
+ *
+ * From section 4.1.X of the ARB_bindless_texture spec:
+ *
+ * "Images can be used as l-values, so can be assigned into and used as
+ * "out" and "inout" function parameters."
*/
if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out)
- && type->contains_opaque()) {
+ && (type->contains_atomic() ||
+ (!state->has_bindless() && type->contains_opaque()))) {
_mesa_glsl_error(&loc, state, "out and inout parameters cannot "
- "contain opaque variables");
+ "contain %s variables",
+ state->has_bindless() ? "atomic" : "opaque");
type = glsl_type::error_type;
}
* "Subroutine declarations cannot be prototyped. It is an error to prepend
* subroutine(...) to a function declaration."
*/
- if (this->return_type->qualifier.flags.q.subroutine_def && !is_definition) {
+ if (this->return_type->qualifier.subroutine_list && !is_definition) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state,
"function declaration `%s' cannot have subroutine prepended",
*
* "[Opaque types] can only be declared as function parameters
* or uniform-qualified variables."
+ *
+ * The ARB_bindless_texture spec doesn't clearly state this, but as it says
+ * "Replace Section 4.1.7 (Samplers), p. 25" and, "Replace Section 4.1.X,
+ * (Images)", this should be allowed.
*/
- if (return_type->contains_opaque()) {
+ if (return_type->contains_atomic() ||
+ (!state->has_bindless() && return_type->contains_opaque())) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state,
- "function `%s' return type can't contain an opaque type",
- name);
+ "function `%s' return type can't contain an %s type",
+ name, state->has_bindless() ? "atomic" : "opaque");
}
/**/
f = state->symbols->get_function(name);
if (f == NULL) {
f = new(ctx) ir_function(name);
- if (!this->return_type->qualifier.flags.q.subroutine) {
+ if (!this->return_type->qualifier.is_subroutine_decl()) {
if (!state->symbols->add_function(f)) {
/* This function name shadows a non-function use of the same name. */
YYLTYPE loc = this->get_location();
if (state->es_shader && state->language_version >= 300) {
/* Local shader has no exact candidates; check the built-ins. */
_mesa_glsl_initialize_builtin_functions();
- if (_mesa_glsl_find_builtin_function_by_name(name)) {
+ if (_mesa_glsl_has_builtin_function(name)) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(& loc, state,
"A shader cannot redefine or overload built-in "
sig->replace_parameters(&hir_parameters);
signature = sig;
- if (this->return_type->qualifier.flags.q.subroutine_def) {
+ if (this->return_type->qualifier.subroutine_list) {
int idx;
if (this->return_type->qualifier.flags.q.explicit_index) {
}
- if (this->return_type->qualifier.flags.q.subroutine) {
+ if (this->return_type->qualifier.is_subroutine_decl()) {
if (!state->symbols->add_type(this->identifier, glsl_type::get_subroutine_instance(this->identifier))) {
_mesa_glsl_error(& loc, state, "type '%s' previously defined", this->identifier);
return NULL;
"to struct or interface block members");
}
+ validate_memory_qualifier_for_type(state, &loc, qual, decl_type);
+ validate_image_format_qualifier_for_type(state, &loc, qual, decl_type);
+
/* From Section 4.4.2.3 (Geometry Outputs) of the GLSL 4.50 spec:
*
* "A block member may be declared with a stream identifier, but
* if set, overwrites the layout qualifier.
*/
if (qual->flags.q.read_only) {
- fields[i].image_read_only = true;
- fields[i].image_write_only = false;
+ fields[i].memory_read_only = true;
+ fields[i].memory_write_only = false;
} else if (qual->flags.q.write_only) {
- fields[i].image_read_only = false;
- fields[i].image_write_only = true;
+ fields[i].memory_read_only = false;
+ fields[i].memory_write_only = true;
} else {
- fields[i].image_read_only = layout->flags.q.read_only;
- fields[i].image_write_only = layout->flags.q.write_only;
+ fields[i].memory_read_only = layout->flags.q.read_only;
+ fields[i].memory_write_only = layout->flags.q.write_only;
}
/* For other qualifiers, we set the flag if either the layout
* qualifier or the field qualifier are set
*/
- fields[i].image_coherent = qual->flags.q.coherent ||
+ fields[i].memory_coherent = qual->flags.q.coherent ||
layout->flags.q.coherent;
- fields[i].image_volatile = qual->flags.q._volatile ||
+ fields[i].memory_volatile = qual->flags.q._volatile ||
layout->flags.q._volatile;
- fields[i].image_restrict = qual->flags.q.restrict_flag ||
+ fields[i].memory_restrict = qual->flags.q.restrict_flag ||
layout->flags.q.restrict_flag;
}
static void
apply_memory_qualifiers(ir_variable *var, glsl_struct_field field)
{
- var->data.image_read_only = field.image_read_only;
- var->data.image_write_only = field.image_write_only;
- var->data.image_coherent = field.image_coherent;
- var->data.image_volatile = field.image_volatile;
- var->data.image_restrict = field.image_restrict;
+ var->data.memory_read_only = field.memory_read_only;
+ var->data.memory_write_only = field.memory_write_only;
+ var->data.memory_coherent = field.memory_coherent;
+ var->data.memory_volatile = field.memory_volatile;
+ var->data.memory_restrict = field.memory_restrict;
}
ir_rvalue *
return NULL;
} else {
if (expl_align == 0 || expl_align & (expl_align - 1)) {
- _mesa_glsl_error(&loc, state, "align layout qualifier in not a "
+ _mesa_glsl_error(&loc, state, "align layout qualifier is not a "
"power of 2.");
return NULL;
}
bool var_is_gl_id = is_gl_identifier(var->name);
if (redeclaring_per_vertex) {
- ir_variable *earlier =
+ bool is_redeclaration;
+ ir_variable *declared_var =
get_variable_being_redeclared(var, loc, state,
- true /* allow_all_redeclarations */);
- if (!var_is_gl_id || earlier == NULL) {
+ true /* allow_all_redeclarations */,
+ &is_redeclaration);
+ if (!var_is_gl_id || !is_redeclaration) {
_mesa_glsl_error(&loc, state,
"redeclaration of gl_PerVertex can only "
"include built-in variables");
- } else if (earlier->data.how_declared == ir_var_declared_normally) {
+ } else if (declared_var->data.how_declared == ir_var_declared_normally) {
_mesa_glsl_error(&loc, state,
"`%s' has already been redeclared",
- earlier->name);
+ declared_var->name);
} else {
- earlier->data.how_declared = ir_var_declared_in_block;
- earlier->reinit_interface_type(block_type);
+ declared_var->data.how_declared = ir_var_declared_in_block;
+ declared_var->reinit_interface_type(block_type);
}
continue;
}
}
if (var->type->is_unsized_array()) {
- if (var->is_in_shader_storage_block()) {
- if (is_unsized_array_last_element(var)) {
- var->data.from_ssbo_unsized_array = true;
- }
+ if (var->is_in_shader_storage_block() &&
+ is_unsized_array_last_element(var)) {
+ var->data.from_ssbo_unsized_array = true;
} else {
/* From GLSL ES 3.10 spec, section 4.1.9 "Arrays":
*
* block and the size is not specified at compile-time, it is
* sized at run-time. In all other cases, arrays are sized only
* at compile-time."
+ *
+ * In desktop GLSL it is allowed to have unsized-arrays that are
+ * not last, as long as we can determine that they are implicitly
+ * sized.
*/
if (state->es_shader) {
_mesa_glsl_error(&loc, state, "unsized array `%s' "