[Mesa-dev] [PATCH 2/4] glsl: rewrite clip/cull distance lowering pass

Dave Airlie airlied at gmail.com
Mon May 23 21:12:03 UTC 2016


On 24 May 2016 at 06:56, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> On Thu, May 19, 2016 at 11:47 PM, Dave Airlie <airlied at gmail.com> wrote:
>> From: Dave Airlie <airlied at redhat.com>
>>
>> The last version of this broke clipping, and I had to spend
>> sometime getting this working properly.
>>
>> I had to introduce a third pass to count the clip/cull totals,
>> all due to one messy corner case. We have a piglit test
>> tes-input-gl_ClipDistance.shader_test
>> that doesn't actually output the clip distances, it just passes
>> them like a varying from TCS->TES, the older lowering pass worked
>> but to lower clip/cull we need to know the total number of clip+culls
>> used to defined the new variable correctly, and to offset culls
>> properly.
>>
>> This adds an extra pass that works out the sizes for clip/cull,
>> then lowers gl_ClipDistance then gl_CullDistance into the new
>> gl_ClipDistanceMESA.
>>
>> The pass checks using the fixed array sizes code if they array
>> has been referenced, or is actually never used, and ignores
>> it in the latter case.
>>
>> Signed-off-by: Dave Airlie <airlied at redhat.com>
>> ---
>>  src/compiler/glsl/ir_optimization.h  |   2 +-
>>  src/compiler/glsl/linker.cpp         |   2 +-
>>  src/compiler/glsl/lower_distance.cpp | 220 ++++++++++++++++++++++++++---------
>>  3 files changed, 164 insertions(+), 60 deletions(-)
>>
>> diff --git a/src/compiler/glsl/ir_optimization.h b/src/compiler/glsl/ir_optimization.h
>> index 5fc2740..71b10e4 100644
>> --- a/src/compiler/glsl/ir_optimization.h
>> +++ b/src/compiler/glsl/ir_optimization.h
>> @@ -119,7 +119,7 @@ bool lower_variable_index_to_cond_assign(gl_shader_stage stage,
>>      bool lower_temp, bool lower_uniform);
>>  bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz);
>>  bool lower_const_arrays_to_uniforms(exec_list *instructions);
>> -bool lower_clip_distance(gl_shader *shader);
>> +bool lower_clip_cull_distance(struct gl_shader_program *prog, gl_shader *shader);
>>  void lower_output_reads(unsigned stage, exec_list *instructions);
>>  bool lower_packing_builtins(exec_list *instructions, int op_mask);
>>  void lower_shared_reference(struct gl_shader *shader, unsigned *shared_size);
>> diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
>> index b856631..4b5b32c 100644
>> --- a/src/compiler/glsl/linker.cpp
>> +++ b/src/compiler/glsl/linker.cpp
>> @@ -4639,7 +4639,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
>>          goto done;
>>
>>        if (ctx->Const.ShaderCompilerOptions[i].LowerCombinedClipCullDistance) {
>> -         lower_clip_distance(prog->_LinkedShaders[i]);
>> +         lower_clip_cull_distance(prog, prog->_LinkedShaders[i]);
>>        }
>>
>>        if (ctx->Const.LowerTessLevel) {
>> diff --git a/src/compiler/glsl/lower_distance.cpp b/src/compiler/glsl/lower_distance.cpp
>> index 301afe4..f21a1be 100644
>> --- a/src/compiler/glsl/lower_distance.cpp
>> +++ b/src/compiler/glsl/lower_distance.cpp
>> @@ -45,19 +45,41 @@
>>   * LowerCombinedClipCullDistance flag in gl_shader_compiler_options to true.
>>   */
>>
>> +#include "main/macros.h"
>>  #include "glsl_symbol_table.h"
>>  #include "ir_rvalue_visitor.h"
>>  #include "ir.h"
>>  #include "program/prog_instruction.h" /* For WRITEMASK_* */
>>
>> +#define GLSL_CLIP_VAR_NAME "gl_ClipDistanceMESA"
>> +
>>  namespace {
>>
>>  class lower_distance_visitor : public ir_rvalue_visitor {
>>  public:
>> -   explicit lower_distance_visitor(gl_shader_stage shader_stage)
>> +   explicit lower_distance_visitor(gl_shader_stage shader_stage,
>> +                                  const char *in_name, int total_size,
>> +                                  int offset)
>>        : progress(false), old_distance_out_var(NULL),
>>          old_distance_in_var(NULL), new_distance_out_var(NULL),
>> -        new_distance_in_var(NULL), shader_stage(shader_stage)
>> +        new_distance_in_var(NULL), shader_stage(shader_stage),
>> +        in_name(in_name), total_size(total_size), offset(offset)
>> +   {
>> +   }
>> +
>> +   explicit lower_distance_visitor(gl_shader_stage shader_stage,
>> +                                  const char *in_name,
>> +                                  const lower_distance_visitor *orig,
>> +                                  int offset)
>> +      : progress(false),
>> +       old_distance_out_var(NULL),
>> +        old_distance_in_var(NULL),
>> +       new_distance_out_var(orig->new_distance_out_var),
>> +        new_distance_in_var(orig->new_distance_in_var),
>> +       shader_stage(shader_stage),
>> +        in_name(in_name),
>> +       total_size(orig->total_size),
>> +       offset(offset)
>
> Please don't mix tabs and spaces. Seems like this has a healthy mix
> with every other line alternating style...

remote emacs editing, doesn't always pick up the style files, will fix that.
>>
>> -   if (!ir->type->fields.array->is_array()) {
>> -      /* gl_ClipDistance (used for vertex, tessellation evaluation and
>> -       * geometry output, and fragment input).
>> -       */
>> -      assert((ir->data.mode == ir_var_shader_in &&
>> -              this->shader_stage == MESA_SHADER_FRAGMENT) ||
>> -             (ir->data.mode == ir_var_shader_out &&
>> -              (this->shader_stage == MESA_SHADER_VERTEX ||
>> -               this->shader_stage == MESA_SHADER_TESS_EVAL ||
>> -               this->shader_stage == MESA_SHADER_GEOMETRY)));
>> +   *old_var = ir;
>>
>> -      *old_var = ir;
>> -      assert (ir->type->fields.array == glsl_type::float_type);
>> -      unsigned new_size = (ir->type->array_size() + 3) / 4;
>> +   if (!(*new_var)) {
>
> This is a new check, the old code didn't have. When is *new_var going
> to be null?
>

Always at the start, the old code always assigned it, since it was all done
in a single pass, since we do two passes once for clip, once for cull,
but we only ever want to define one new_var (gl_ClipDistanceMESA).

>> +      cull_size = &out_cull_size;
>> +   } else if (ir->data.mode == ir_var_shader_in) {
>> +      clip_size = &in_clip_size;
>> +      cull_size = &in_cull_size;
>> +   } else
>> +      return visit_continue;
>> +
>> +   if (ir->type->is_unsized_array())
>
> || !ir->type->is_array() presumably? If some jerk did "float
> gl_CullDistance", the below would go rather poorly...

I don't think the compiler lets you do float gl_ClipDistance
or gl_CullDistance. It's definitely not something I need to care
about at this depth.

> Would it be cleaner to identify variables by location rather than
> name? e.g. what happens if I don't have cull enabled, and use that as
> a regular ol' varying name. Whereas the only way to have a
> VARYING_SLOT_CULL position is to go via the proper built-in path.

gl_ names aren't user useable, the compiler would block it.

Dave.


More information about the mesa-dev mailing list