From 115d938cea5f362c3c078bcc6e75da1245aa6675 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 21 Mar 2017 13:30:49 +0100 Subject: [PATCH] glsl: process bindless/bound layout qualifiers MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Timothy Arceri Reviewed-by: Nicolai Hähnle --- src/compiler/glsl/ast.h | 8 ++++ src/compiler/glsl/ast_to_hir.cpp | 66 ++++++++++++++++++++++++++++++++ src/compiler/glsl/ast_type.cpp | 53 +++++++++++++++++++++++++ src/compiler/glsl/glsl_parser.yy | 21 ++++++++++ src/compiler/glsl/glsl_parser_extras.cpp | 11 ++++++ src/compiler/glsl/glsl_parser_extras.h | 10 +++++ src/compiler/glsl/ir.cpp | 2 + src/compiler/glsl/ir.h | 12 ++++++ src/compiler/glsl/ir_print_visitor.cpp | 8 ++-- src/mesa/main/mtypes.h | 10 +++++ 10 files changed, 198 insertions(+), 3 deletions(-) diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h index 455cb81..9327e03 100644 --- a/src/compiler/glsl/ast.h +++ b/src/compiler/glsl/ast.h @@ -622,6 +622,14 @@ struct ast_type_qualifier { * is used. */ 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. */ q; diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index f301b39..53dd08f 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -3457,6 +3457,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 apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual, ir_variable *var, struct _mesa_glsl_parse_state *state, @@ -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 " "valid in fragment shader input layout declaration."); } + + if (state->has_bindless()) + apply_bindless_qualifier_to_variable(qual, var, state, loc); } static void diff --git a/src/compiler/glsl/ast_type.cpp b/src/compiler/glsl/ast_type.cpp index d302fc4..9e3e10f 100644 --- a/src/compiler/glsl/ast_type.cpp +++ b/src/compiler/glsl/ast_type.cpp @@ -69,6 +69,10 @@ ast_type_qualifier::has_layout() const || this->flags.q.column_major || this->flags.q.row_major || 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_component || this->flags.q.explicit_location @@ -181,6 +185,33 @@ validate_point_mode(MAYBE_UNUSED const ast_type_qualifier &qualifier, 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. * @@ -393,6 +424,18 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, if (q.flags.q.local_size_variable) 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; if (this->flags.q.in && @@ -427,6 +470,12 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, 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; } @@ -778,6 +827,10 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc, bad.flags.q.subroutine ? " subroutine" : "", bad.flags.q.blend_support ? " blend_support" : "", 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" : ""); return false; } diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy index e703073..9cdc37e 100644 --- a/src/compiler/glsl/glsl_parser.yy +++ b/src/compiler/glsl/glsl_parser.yy @@ -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) { _mesa_glsl_error(& @1, state, "unrecognized layout identifier " "`%s'", $1); diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index b7303ab..d731e35 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -307,6 +307,12 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, ctx->Const.AllowGLSLExtensionDirectiveMidShader; 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. */ 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" { diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h index 6045a61..3a84d65 100644 --- a/src/compiler/glsl/glsl_parser_extras.h +++ b/src/compiler/glsl/glsl_parser_extras.h @@ -428,6 +428,16 @@ struct _mesa_glsl_parse_state { 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), * and GLSL 4.00 (tessellation control shader). */ diff --git a/src/compiler/glsl/ir.cpp b/src/compiler/glsl/ir.cpp index 5b38a71..590d2ad 100644 --- a/src/compiler/glsl/ir.cpp +++ b/src/compiler/glsl/ir.cpp @@ -1729,6 +1729,8 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, this->data.memory_restrict = false; this->data.from_ssbo_unsized_array = false; this->data.fb_fetch_output = false; + this->data.bindless = false; + this->data.bound = false; if (type != NULL) { if (type->is_interface()) diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h index 5a5729c..7e125e6 100644 --- a/src/compiler/glsl/ir.h +++ b/src/compiler/glsl/ir.h @@ -850,6 +850,18 @@ public: 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. */ private: diff --git a/src/compiler/glsl/ir_print_visitor.cpp b/src/compiler/glsl/ir_print_visitor.cpp index 6c1c86a..f8d0dc4 100644 --- a/src/compiler/glsl/ir_print_visitor.cpp +++ b/src/compiler/glsl/ir_print_visitor.cpp @@ -193,6 +193,8 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const patc = (ir->data.patch) ? "patch " : ""; const char *const inv = (ir->data.invariant) ? "invariant " : ""; 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 ", "shader_shared ", "shader_in ", "shader_out ", "in ", "out ", "inout ", @@ -201,9 +203,9 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const interp[] = { "", "smooth", "flat", "noperspective" }; STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_MODE_COUNT); - fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s) ", - binding, loc, component, cent, samp, patc, inv, prec, mode[ir->data.mode], - stream, + fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s%s%s) ", + binding, loc, component, cent, bindless, bound, samp, patc, inv, + prec, mode[ir->data.mode], stream, interp[ir->data.interpolation]); print_type(f, ir->type); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 79c7e50..0d594bf 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2547,6 +2547,16 @@ struct gl_shader bool origin_upper_left; 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 */ GLuint TransformFeedbackBufferStride[MAX_FEEDBACK_BUFFERS]; -- 2.7.4