[Mesa-dev] [PATCH] TransformFeedback: Assign transform feedback varying slots in linker.

Marek Olšák maraeo at gmail.com
Sun Oct 23 13:19:38 PDT 2011


On Sat, Oct 22, 2011 at 2:14 AM, Dan McCabe <zen3d.linux at gmail.com> wrote:
> Modify the linker to assign additional slots for varying
> variables used by transform feedback. This is done after other
> varyings are already assigned slots.
>
> Since this is done after previous varying slot assignments,
> the code needs to know how many varyings are already assigned
> slots. A new function "max_varying()" is introduced to examine a
> previously processed shader to find the largest varying already
> assigned a slot. All new varyings will be assigned slots after
> this one. If varyings are found, -1 is returned.
> ---
>  src/glsl/linker.cpp |   84 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 84 insertions(+), 0 deletions(-)
>
> diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
> index a7c38a3..81f2658 100644
> --- a/src/glsl/linker.cpp
> +++ b/src/glsl/linker.cpp
> @@ -207,6 +207,25 @@ invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
>    }
>  }
>
> +
> +int
> +max_varying(gl_shader *sh, enum ir_variable_mode mode)
> +{
> +   int max_varying = -1;
> +
> +   foreach_list(node, sh->ir) {
> +      ir_variable *const var = ((ir_instruction *) node)->as_variable();
> +
> +      if ((var == NULL) || (var->mode != (unsigned) mode))
> +        continue;
> +
> +      if (var->location > max_varying)
> +        max_varying = var->location;
> +   }
> +
> +   return max_varying;
> +}
> +
>
>  /**
>  * Determine the number of attribute slots required for a particular type
> @@ -1597,6 +1616,69 @@ assign_varying_locations(struct gl_context *ctx,
>
>
>  void
> +assign_transform_feedback_varying_locations(struct gl_context *ctx,
> +                                           struct gl_shader_program *prog)
> +{
> +   struct gl_shader *vs = prog->_LinkedShaders[MESA_SHADER_VERTEX];
> +
> +   if (vs == NULL)
> +      return;
> +
> +   char **names = prog->TransformFeedback.VaryingNames;
> +   int num_names = prog->TransformFeedback.NumVarying;
> +
> +   if (num_names <= 0)
> +      return;
> +
> +   int num_varying = max_varying(vs, ir_var_out) + 1;
> +   unsigned output_index =
> +     (num_varying > VERT_RESULT_VAR0)
> +        ? num_varying
> +        : VERT_RESULT_VAR0;
> +
> +   foreach_list(node, vs->ir) {
> +      ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
> +
> +      if (output_var == NULL
> +      ||  output_var->mode != ir_var_out
> +      ||  output_var->location != -1)
> +        continue;
> +
> +      /* Find a transform feedback varying variable that has
> +       * the same name as the shader variable.
> +       */
> +      int varying_index = -1;
> +      for (int num_name = 0; num_name < num_names; num_name++) {
> +         char *name = *names++;

Hi Dan,

Sorry for the very late reply and thank you very much for the work. I
have just a few remarks.

1) *names++ doesn't seem correct and causes a segfault. You probably
wanted *(names++). I fixed this in my code by using names[num_name],
which is more readable.

2) I am not sure whether your code will work with varying arrays. With
"varying vec4 array[2];", "array[0]" and "array[1]" are possible names
for transform feedback varyings.

3) If a transform feedback varying is undeclared, linker_error should
be called and the linker should back off.

Other than that, transform feedback varying locations seem to be
assigned correctly.

Best regards,
Marek


More information about the mesa-dev mailing list