glsl: process bindless/bound layout qualifiers
This adds bindless_sampler and bound_sampler (and respectively bindless_image and bound_image) to the parser. v3: - add an extra space in apply_bindless_qualifier_to_variable() - fix indentation in merge_qualifier() Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com> Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
@@ -622,6 +622,14 @@ struct ast_type_qualifier {
|
|||||||
* is used.
|
* is used.
|
||||||
*/
|
*/
|
||||||
unsigned inner_coverage:1;
|
unsigned inner_coverage:1;
|
||||||
|
|
||||||
|
/** \name Layout qualifiers for GL_ARB_bindless_texture */
|
||||||
|
/** \{ */
|
||||||
|
unsigned bindless_sampler:1;
|
||||||
|
unsigned bindless_image:1;
|
||||||
|
unsigned bound_sampler:1;
|
||||||
|
unsigned bound_image:1;
|
||||||
|
/** \} */
|
||||||
}
|
}
|
||||||
/** \brief Set of flags, accessed by name. */
|
/** \brief Set of flags, accessed by name. */
|
||||||
q;
|
q;
|
||||||
|
@@ -3456,6 +3456,69 @@ validate_array_dimensions(const glsl_type *t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
|
apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
|
||||||
ir_variable *var,
|
ir_variable *var,
|
||||||
@@ -3753,6 +3816,9 @@ apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
|
|||||||
_mesa_glsl_error(loc, state, "post_depth_coverage layout qualifier only "
|
_mesa_glsl_error(loc, state, "post_depth_coverage layout qualifier only "
|
||||||
"valid in fragment shader input layout declaration.");
|
"valid in fragment shader input layout declaration.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state->has_bindless())
|
||||||
|
apply_bindless_qualifier_to_variable(qual, var, state, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -69,6 +69,10 @@ ast_type_qualifier::has_layout() const
|
|||||||
|| this->flags.q.column_major
|
|| this->flags.q.column_major
|
||||||
|| this->flags.q.row_major
|
|| this->flags.q.row_major
|
||||||
|| this->flags.q.packed
|
|| this->flags.q.packed
|
||||||
|
|| this->flags.q.bindless_sampler
|
||||||
|
|| this->flags.q.bindless_image
|
||||||
|
|| this->flags.q.bound_sampler
|
||||||
|
|| this->flags.q.bound_image
|
||||||
|| this->flags.q.explicit_align
|
|| this->flags.q.explicit_align
|
||||||
|| this->flags.q.explicit_component
|
|| this->flags.q.explicit_component
|
||||||
|| this->flags.q.explicit_location
|
|| this->flags.q.explicit_location
|
||||||
@@ -181,6 +185,33 @@ validate_point_mode(MAYBE_UNUSED const ast_type_qualifier &qualifier,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
merge_bindless_qualifier(YYLTYPE *loc,
|
||||||
|
_mesa_glsl_parse_state *state,
|
||||||
|
const ast_type_qualifier &qualifier,
|
||||||
|
const ast_type_qualifier &new_qualifier)
|
||||||
|
{
|
||||||
|
if (state->default_uniform_qualifier->flags.q.bindless_sampler) {
|
||||||
|
state->bindless_sampler_specified = true;
|
||||||
|
state->default_uniform_qualifier->flags.q.bindless_sampler = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->default_uniform_qualifier->flags.q.bindless_image) {
|
||||||
|
state->bindless_image_specified = true;
|
||||||
|
state->default_uniform_qualifier->flags.q.bindless_image = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->default_uniform_qualifier->flags.q.bound_sampler) {
|
||||||
|
state->bound_sampler_specified = true;
|
||||||
|
state->default_uniform_qualifier->flags.q.bound_sampler = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->default_uniform_qualifier->flags.q.bound_image) {
|
||||||
|
state->bound_image_specified = true;
|
||||||
|
state->default_uniform_qualifier->flags.q.bound_image = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function merges duplicate layout identifiers.
|
* This function merges duplicate layout identifiers.
|
||||||
*
|
*
|
||||||
@@ -393,6 +424,18 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
|
|||||||
if (q.flags.q.local_size_variable)
|
if (q.flags.q.local_size_variable)
|
||||||
this->flags.q.local_size_variable = true;
|
this->flags.q.local_size_variable = true;
|
||||||
|
|
||||||
|
if (q.flags.q.bindless_sampler)
|
||||||
|
this->flags.q.bindless_sampler = true;
|
||||||
|
|
||||||
|
if (q.flags.q.bindless_image)
|
||||||
|
this->flags.q.bindless_image = true;
|
||||||
|
|
||||||
|
if (q.flags.q.bound_sampler)
|
||||||
|
this->flags.q.bound_sampler = true;
|
||||||
|
|
||||||
|
if (q.flags.q.bound_image)
|
||||||
|
this->flags.q.bound_image = true;
|
||||||
|
|
||||||
this->flags.i |= q.flags.i;
|
this->flags.i |= q.flags.i;
|
||||||
|
|
||||||
if (this->flags.q.in &&
|
if (this->flags.q.in &&
|
||||||
@@ -427,6 +470,12 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
|
|||||||
this->image_base_type = q.image_base_type;
|
this->image_base_type = q.image_base_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (q.flags.q.bindless_sampler ||
|
||||||
|
q.flags.q.bindless_image ||
|
||||||
|
q.flags.q.bound_sampler ||
|
||||||
|
q.flags.q.bound_image)
|
||||||
|
merge_bindless_qualifier(loc, state, *this, q);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,6 +827,10 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc,
|
|||||||
bad.flags.q.subroutine ? " subroutine" : "",
|
bad.flags.q.subroutine ? " subroutine" : "",
|
||||||
bad.flags.q.blend_support ? " blend_support" : "",
|
bad.flags.q.blend_support ? " blend_support" : "",
|
||||||
bad.flags.q.inner_coverage ? " inner_coverage" : "",
|
bad.flags.q.inner_coverage ? " inner_coverage" : "",
|
||||||
|
bad.flags.q.bindless_sampler ? " bindless_sampler" : "",
|
||||||
|
bad.flags.q.bindless_image ? " bindless_image" : "",
|
||||||
|
bad.flags.q.bound_sampler ? " bound_sampler" : "",
|
||||||
|
bad.flags.q.bound_image ? " bound_image" : "",
|
||||||
bad.flags.q.post_depth_coverage ? " post_depth_coverage" : "");
|
bad.flags.q.post_depth_coverage ? " post_depth_coverage" : "");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -1589,6 +1589,27 @@ layout_qualifier_id:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Layout qualifiers for ARB_bindless_texture. */
|
||||||
|
if (!$$.flags.i) {
|
||||||
|
if (match_layout_qualifier($1, "bindless_sampler", state) == 0)
|
||||||
|
$$.flags.q.bindless_sampler = 1;
|
||||||
|
if (match_layout_qualifier($1, "bound_sampler", state) == 0)
|
||||||
|
$$.flags.q.bound_sampler = 1;
|
||||||
|
|
||||||
|
if (state->has_shader_image_load_store()) {
|
||||||
|
if (match_layout_qualifier($1, "bindless_image", state) == 0)
|
||||||
|
$$.flags.q.bindless_image = 1;
|
||||||
|
if (match_layout_qualifier($1, "bound_image", state) == 0)
|
||||||
|
$$.flags.q.bound_image = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($$.flags.i && !state->has_bindless()) {
|
||||||
|
_mesa_glsl_error(& @1, state,
|
||||||
|
"qualifier `%s` requires "
|
||||||
|
"ARB_bindless_texture", $1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!$$.flags.i) {
|
if (!$$.flags.i) {
|
||||||
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
|
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
|
||||||
"`%s'", $1);
|
"`%s'", $1);
|
||||||
|
@@ -307,6 +307,12 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
|
|||||||
ctx->Const.AllowGLSLExtensionDirectiveMidShader;
|
ctx->Const.AllowGLSLExtensionDirectiveMidShader;
|
||||||
|
|
||||||
this->cs_input_local_size_variable_specified = false;
|
this->cs_input_local_size_variable_specified = false;
|
||||||
|
|
||||||
|
/* ARB_bindless_texture */
|
||||||
|
this->bindless_sampler_specified = false;
|
||||||
|
this->bindless_image_specified = false;
|
||||||
|
this->bound_sampler_specified = false;
|
||||||
|
this->bound_image_specified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1849,6 +1855,11 @@ set_shader_inout_layout(struct gl_shader *shader,
|
|||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shader->bindless_sampler = state->bindless_sampler_specified;
|
||||||
|
shader->bindless_image = state->bindless_image_specified;
|
||||||
|
shader->bound_sampler = state->bound_sampler_specified;
|
||||||
|
shader->bound_image = state->bound_image_specified;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@@ -427,6 +427,16 @@ struct _mesa_glsl_parse_state {
|
|||||||
*/
|
*/
|
||||||
bool cs_input_local_size_variable_specified;
|
bool cs_input_local_size_variable_specified;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if a shader declare bindless_sampler/bindless_image, and
|
||||||
|
* respectively bound_sampler/bound_image at global scope as specified by
|
||||||
|
* ARB_bindless_texture.
|
||||||
|
*/
|
||||||
|
bool bindless_sampler_specified;
|
||||||
|
bool bindless_image_specified;
|
||||||
|
bool bound_sampler_specified;
|
||||||
|
bool bound_image_specified;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output layout qualifiers from GLSL 1.50 (geometry shader controls),
|
* Output layout qualifiers from GLSL 1.50 (geometry shader controls),
|
||||||
* and GLSL 4.00 (tessellation control shader).
|
* and GLSL 4.00 (tessellation control shader).
|
||||||
|
@@ -1729,6 +1729,8 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
|
|||||||
this->data.memory_restrict = false;
|
this->data.memory_restrict = false;
|
||||||
this->data.from_ssbo_unsized_array = false;
|
this->data.from_ssbo_unsized_array = false;
|
||||||
this->data.fb_fetch_output = false;
|
this->data.fb_fetch_output = false;
|
||||||
|
this->data.bindless = false;
|
||||||
|
this->data.bound = false;
|
||||||
|
|
||||||
if (type != NULL) {
|
if (type != NULL) {
|
||||||
if (type->is_interface())
|
if (type->is_interface())
|
||||||
|
@@ -849,6 +849,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
unsigned fb_fetch_output:1;
|
unsigned fb_fetch_output:1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-zero if this variable is considered bindless as defined by
|
||||||
|
* ARB_bindless_texture.
|
||||||
|
*/
|
||||||
|
unsigned bindless:1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-zero if this variable is considered bound as defined by
|
||||||
|
* ARB_bindless_texture.
|
||||||
|
*/
|
||||||
|
unsigned bound:1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit a warning if this variable is accessed.
|
* Emit a warning if this variable is accessed.
|
||||||
*/
|
*/
|
||||||
|
@@ -193,6 +193,8 @@ void ir_print_visitor::visit(ir_variable *ir)
|
|||||||
const char *const patc = (ir->data.patch) ? "patch " : "";
|
const char *const patc = (ir->data.patch) ? "patch " : "";
|
||||||
const char *const inv = (ir->data.invariant) ? "invariant " : "";
|
const char *const inv = (ir->data.invariant) ? "invariant " : "";
|
||||||
const char *const prec = (ir->data.precise) ? "precise " : "";
|
const char *const prec = (ir->data.precise) ? "precise " : "";
|
||||||
|
const char *const bindless = (ir->data.bindless) ? "bindless " : "";
|
||||||
|
const char *const bound = (ir->data.bound) ? "bound " : "";
|
||||||
const char *const mode[] = { "", "uniform ", "shader_storage ",
|
const char *const mode[] = { "", "uniform ", "shader_storage ",
|
||||||
"shader_shared ", "shader_in ", "shader_out ",
|
"shader_shared ", "shader_in ", "shader_out ",
|
||||||
"in ", "out ", "inout ",
|
"in ", "out ", "inout ",
|
||||||
@@ -201,9 +203,9 @@ void ir_print_visitor::visit(ir_variable *ir)
|
|||||||
const char *const interp[] = { "", "smooth", "flat", "noperspective" };
|
const char *const interp[] = { "", "smooth", "flat", "noperspective" };
|
||||||
STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_MODE_COUNT);
|
STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_MODE_COUNT);
|
||||||
|
|
||||||
fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s) ",
|
fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s%s%s) ",
|
||||||
binding, loc, component, cent, samp, patc, inv, prec, mode[ir->data.mode],
|
binding, loc, component, cent, bindless, bound, samp, patc, inv,
|
||||||
stream,
|
prec, mode[ir->data.mode], stream,
|
||||||
interp[ir->data.interpolation]);
|
interp[ir->data.interpolation]);
|
||||||
|
|
||||||
print_type(f, ir->type);
|
print_type(f, ir->type);
|
||||||
|
@@ -2547,6 +2547,16 @@ struct gl_shader
|
|||||||
bool origin_upper_left;
|
bool origin_upper_left;
|
||||||
bool pixel_center_integer;
|
bool pixel_center_integer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether bindless_sampler/bindless_image, and respectively
|
||||||
|
* bound_sampler/bound_image are declared at global scope as defined by
|
||||||
|
* ARB_bindless_texture.
|
||||||
|
*/
|
||||||
|
bool bindless_sampler;
|
||||||
|
bool bindless_image;
|
||||||
|
bool bound_sampler;
|
||||||
|
bool bound_image;
|
||||||
|
|
||||||
/** Global xfb_stride out qualifier if any */
|
/** Global xfb_stride out qualifier if any */
|
||||||
GLuint TransformFeedbackBufferStride[MAX_FEEDBACK_BUFFERS];
|
GLuint TransformFeedbackBufferStride[MAX_FEEDBACK_BUFFERS];
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user