[Mesa-dev] [PATCH 2/4] glsl: rewrite clip/cull distance lowering pass
Ilia Mirkin
imirkin at alum.mit.edu
Mon May 23 21:19:31 UTC 2016
On Mon, May 23, 2016 at 5:12 PM, Dave Airlie <airlied at gmail.com> wrote:
> 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).
Oh right, that makes sense. So if you've already defined the new var,
just remove the new thing.
+ (*new_var)->data.max_array_access = ir->data.max_array_access / 4;
That's wrong in both sides of the if though, no? Shouldn't it just be
new_size - 1 for the non-primitive-input case? And I don't even know
what it should be in the primitive input case since the outer array
should stay the same while the inner array should have new_size - 1.
>
>>> + 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.
How about asserting then?
>
>> 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.
Hm ok. I'd still prefer avoiding strcmp, but I'll leave it to you.
More information about the mesa-dev
mailing list