On 10/24/2011 02:16 PM, Ian Romanick wrote:
> From: Ian Romanick <ian.d.roman...@intel.com>
> 
> Signed-off-by: Ian Romanick <ian.d.roman...@intel.com>
> ---
>  src/glsl/Makefile          |    1 +
>  src/glsl/link_uniforms.cpp |  116 
> ++++++++++++++++++++++++++++++++++++++++++++
>  src/glsl/linker.h          |   45 +++++++++++++++++
>  3 files changed, 162 insertions(+), 0 deletions(-)
>  create mode 100644 src/glsl/link_uniforms.cpp
> 
> diff --git a/src/glsl/Makefile b/src/glsl/Makefile
> index b2efb2a..504f1fb 100644
> --- a/src/glsl/Makefile
> +++ b/src/glsl/Makefile
> @@ -53,6 +53,7 @@ CXX_SOURCES = \
>       ir_variable_refcount.cpp \
>       linker.cpp \
>       link_functions.cpp \
> +     link_uniforms.cpp \
>       loop_analysis.cpp \
>       loop_controls.cpp \
>       loop_unroll.cpp \
> diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
> new file mode 100644
> index 0000000..38bc00c
> --- /dev/null
> +++ b/src/glsl/link_uniforms.cpp
> @@ -0,0 +1,116 @@
> +/*
> + * Copyright © 2011 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include "main/core.h"
> +#include "ir.h"
> +#include "linker.h"
> +#include "glsl_symbol_table.h"
> +#include "program/hash_table.h"
> +
> +/**
> + * \file link_uniforms.cpp
> + * Assign locations for GLSL uniforms.
> + *
> + * \author Ian Romanick <ian.d.roman...@intel.com>
> + */
> +
> +void uniform_field_visitor::process(ir_variable *var)
> +{
> +   char *name = const_cast<char *>(var->name);

I loathe const_cast<>---it's just evil.  I declare my variables const
for a reason, and I don't want people screwing them up.  Guess how fun
it is to debug issues caused by your supposedly const values changing
out from under you?

I see that you're trying to avoid a strdup in the common case, which is
good, but I'd prefer a less dirty solution.

> +   unsigned len = 0;
> +
> +   recursion(var->type, &name, strlen(name), len);
> +   if (name != var->name)
> +      free(name);
> +}
> +
> +void uniform_field_visitor::recursion(const glsl_type *t, char **name,
> +                                   unsigned name_length,
> +                                   unsigned &name_buffer_length)
> +{
> +   /* Records need to have each field processed individually.
> +    *
> +    * Arrays of records need to have each array element processed
> +    * individually, then each field of the resulting array elements processed
> +    * individually.
> +    */
> +   if (t->is_record()) {
> +      for (unsigned i = 0; i < t->length; i++) {
> +      const unsigned len = strlen(t->fields.structure[i].name);
> +
> +      /* Size of "name.field\0".
> +       */
> +      const unsigned field_length = name_length + 1 + len + 1;
> +
> +      /* Grow the name buffer if it is not large enough to hold the fully
> +       * qualified name of this field.
> +       */
> +      if (name_buffer_length < field_length) {
> +         if (name_buffer_length == 0) {
> +            name_buffer_length = field_length + 16;
> +            char *tmp = (char *) malloc(name_buffer_length);
> +            strcpy(tmp, *name);
> +
> +            *name = tmp;
> +         } else {
> +            name_buffer_length = field_length + 16;
> +            *name = (char *) realloc(*name, name_buffer_length);
> +         }
> +      }
> +
> +      /* Append '.field' to the current uniform name.
> +       */
> +      (*name)[name_length] = '.';
> +      memcpy(& (*name)[name_length+1], t->fields.structure[i].name, len);
> +      (*name)[field_length - 1] = '\0';

Maybe it's just me, but I find this code rather impenetrable what with
all the buffer management and string munging.  mallocs, reallocs,
memcpys, strcpys, extra parameters, the magic constant + 16...

Yet, all it does is generate names such as
  some_struct.foo
  some_struct.bar
  some_struct.baz
and call a function for each of those.  That's really simple.

I understand that you're trying to avoid unnecessary strlen() calls, but
there has to be a better way.

I've added some new functionality to ralloc that should make this a lot
cleaner.  I'll send it out shortly.

> +      recursion(t->fields.structure[i].type,
> +                name, field_length - 1, name_buffer_length);
> +      }
> +   } else if (t->is_array() && t->fields.array->is_record()) {
> +      const unsigned extra = unsigned(ceil(log10(float(t->length)))) + 2;
> +      const unsigned field_length = name_length + extra;
> +
> +      if (name_buffer_length < field_length) {
> +      if (name_buffer_length == 0) {
> +         name_buffer_length = field_length + 16;
> +         char *tmp = (char *) malloc(name_buffer_length);
> +         strcpy(tmp, *name);
> +
> +         *name = tmp;
> +      } else {
> +         name_buffer_length = field_length + 16;
> +         *name = (char *) realloc(*name, name_buffer_length);
> +      }
> +      }
> +
> +      for (unsigned i = 0; i < t->length; i++) {
> +      const unsigned len = name_length
> +         + sprintf(&(*name)[name_length], "[%d]", i);
> +
> +      recursion(t->fields.array, name, len, name_buffer_length);
> +      }
> +   } else {
> +      this->visit_field(t, *name);
> +   }
> +}
> diff --git a/src/glsl/linker.h b/src/glsl/linker.h
> index 769cf68..2bd2b47 100644
> --- a/src/glsl/linker.h
> +++ b/src/glsl/linker.h
> @@ -1,3 +1,4 @@
> +/* -*- c++ -*- */
>  /*
>   * Copyright © 2010 Intel Corporation
>   *
> @@ -29,4 +30,48 @@ extern bool
>  link_function_calls(gl_shader_program *prog, gl_shader *main,
>                   gl_shader **shader_list, unsigned num_shaders);
>  
> +
> +/**
> + * Class for processing all of the leaf fields of an uniform
> + *
> + * Leaves are, roughly speaking, the parts of the uniform that the 
> application
> + * could query with \c glGetUniformLocation (or that could be returned by
> + * \c glGetActiveUniforms).
> + *
> + * Classes my derive from this class to implement specific functionality.
> + * This class only provides the mechanism to iterate over the leaves.  
> Derived
> + * classes must implement \c ::visit_field and may override \c ::process.
> + */
> +class uniform_field_visitor {
> +public:
> +   /**
> +    * Begin processing a uniform
> +    *
> +    * Classes that overload this function should call \c ::process from the
> +    * base class to start the recursive processing of the uniform.
> +    *
> +    * \param var  The uniform variable that is to be processed
> +    *
> +    * Calls \c ::visit_field for each leaf of the uniform.
> +    */
> +   void process(ir_variable *var);
> +
> +protected:
> +   /**
> +    * Method invoked for each leaf of the uniform
> +    *
> +    * \param type  Type of the field.
> +    * \param name  Fully qualified name of the field.
> +    */
> +   virtual void visit_field(const glsl_type *type, const char *name) = 0;
> +
> +private:
> +   /**
> +    * \param name_length  Length of the current name \b not including the
> +    *                     terminating \c NUL character.
> +    */
> +   void recursion(const glsl_type *t, char **name, unsigned name_length,
> +               unsigned &name_buffer_length);
> +};
> +
>  #endif /* GLSL_LINKER_H */

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to