[Mesa-dev] [PATCH 1/4] glsl: Check TCS barrier restrictions at ast_to_hir time, not link time.

Ian Romanick idr at freedesktop.org
Thu Sep 22 10:43:30 UTC 2016


This is much simpler.  This patch is

Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>

On 09/21/2016 10:20 PM, Kenneth Graunke wrote:
> We want to check prior to optimization - otherwise we might fail to
> detect cases where barrier() is in control flow which is always taken
> (and therefore gets optimized away).
> 
> We don't currently loop unroll if there are function calls inside;
> otherwise we might have a problem detecting barrier() in loops that
> get unrolled as well.
> 
> Tapani's switch handling code adds a loop around switch statements, so
> even with the mess of if ladders, we'll properly reject it.
> 
> Enforcing these rules at compile time makes more sense more sense than
> link time.  Doing it at ast-to-hir time (rather than as an IR pass)
> allows us to emit an error message with proper line numbers.
> (Otherwise, I would have preferred the IR pass...)
> 
> Fixes spec/arb_tessellation_shader/compiler/barrier-switch-always.tesc.
> 
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  src/compiler/glsl/ast_function.cpp | 19 ++++++++
>  src/compiler/glsl/linker.cpp       | 99 --------------------------------------
>  2 files changed, 19 insertions(+), 99 deletions(-)
> 
> diff --git a/src/compiler/glsl/ast_function.cpp b/src/compiler/glsl/ast_function.cpp
> index ea3ac87..7e62ab7 100644
> --- a/src/compiler/glsl/ast_function.cpp
> +++ b/src/compiler/glsl/ast_function.cpp
> @@ -2143,6 +2143,25 @@ ast_function_expression::hir(exec_list *instructions,
>           /* an error has already been emitted */
>           value = ir_rvalue::error_value(ctx);
>        } else {
> +         if (state->stage == MESA_SHADER_TESS_CTRL &&
> +             sig->is_builtin() && strcmp(func_name, "barrier") == 0) {
> +            if (state->current_function == NULL ||
> +                strcmp(state->current_function->function_name(), "main") != 0) {
> +               _mesa_glsl_error(&loc, state,
> +                                "barrier() may only be used in main()");
> +            }
> +
> +            if (state->found_return) {
> +               _mesa_glsl_error(&loc, state,
> +                                "barrier() may not be used after return");
> +            }
> +
> +            if (instructions != &state->current_function->body) {
> +               _mesa_glsl_error(&loc, state,
> +                                "barrier() may not be used in control flow");
> +            }
> +         }
> +
>           value = generate_call(instructions, sig,
>                                 &actual_parameters, sub_var, array_idx, state);
>           if (!value) {
> diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
> index f3eece2..606d006 100644
> --- a/src/compiler/glsl/linker.cpp
> +++ b/src/compiler/glsl/linker.cpp
> @@ -260,97 +260,6 @@ public:
>     }
>  };
>  
> -class barrier_use_visitor : public ir_hierarchical_visitor {
> -public:
> -   barrier_use_visitor(gl_shader_program *prog)
> -      : prog(prog), in_main(false), after_return(false), control_flow(0)
> -   {
> -   }
> -
> -   virtual ~barrier_use_visitor()
> -   {
> -      /* empty */
> -   }
> -
> -   virtual ir_visitor_status visit_enter(ir_function *ir)
> -   {
> -      if (strcmp(ir->name, "main") == 0)
> -         in_main = true;
> -
> -      return visit_continue;
> -   }
> -
> -   virtual ir_visitor_status visit_leave(ir_function *)
> -   {
> -      in_main = false;
> -      after_return = false;
> -      return visit_continue;
> -   }
> -
> -   virtual ir_visitor_status visit_leave(ir_return *)
> -   {
> -      after_return = true;
> -      return visit_continue;
> -   }
> -
> -   virtual ir_visitor_status visit_enter(ir_if *)
> -   {
> -      ++control_flow;
> -      return visit_continue;
> -   }
> -
> -   virtual ir_visitor_status visit_leave(ir_if *)
> -   {
> -      --control_flow;
> -      return visit_continue;
> -   }
> -
> -   virtual ir_visitor_status visit_enter(ir_loop *)
> -   {
> -      ++control_flow;
> -      return visit_continue;
> -   }
> -
> -   virtual ir_visitor_status visit_leave(ir_loop *)
> -   {
> -      --control_flow;
> -      return visit_continue;
> -   }
> -
> -   /* FINISHME: `switch` is not expressed at the IR level -- it's already
> -    * been lowered to a mess of `if`s. We'll correctly disallow any use of
> -    * barrier() in a conditional path within the switch, but not in a path
> -    * which is always hit.
> -    */
> -
> -   virtual ir_visitor_status visit_enter(ir_call *ir)
> -   {
> -      if (ir->use_builtin && strcmp(ir->callee_name(), "barrier") == 0) {
> -         /* Use of barrier(); determine if it is legal: */
> -         if (!in_main) {
> -            linker_error(prog, "Builtin barrier() may only be used in main");
> -            return visit_stop;
> -         }
> -
> -         if (after_return) {
> -            linker_error(prog, "Builtin barrier() may not be used after return");
> -            return visit_stop;
> -         }
> -
> -         if (control_flow != 0) {
> -            linker_error(prog, "Builtin barrier() may not be used inside control flow");
> -            return visit_stop;
> -         }
> -      }
> -      return visit_continue;
> -   }
> -
> -private:
> -   gl_shader_program *prog;
> -   bool in_main, after_return;
> -   int control_flow;
> -};
> -
>  /**
>   * Visitor that determines the highest stream id to which a (geometry) shader
>   * emits vertices. It also checks whether End{Stream}Primitive is ever called.
> @@ -2355,14 +2264,6 @@ link_intrastage_shaders(void *mem_ctx,
>     if (ctx->Const.VertexID_is_zero_based)
>        lower_vertex_id(linked);
>  
> -   /* Validate correct usage of barrier() in the tess control shader */
> -   if (linked->Stage == MESA_SHADER_TESS_CTRL) {
> -      barrier_use_visitor visitor(prog);
> -      foreach_in_list(ir_instruction, ir, linked->ir) {
> -         ir->accept(&visitor);
> -      }
> -   }
> -
>     return linked;
>  }
>  
> 



More information about the mesa-dev mailing list