[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