[Mesa-dev] [PATCH] glsl_to_tgsi: allocate and enlarge arrays for temporaries on demand

Ilia Mirkin imirkin at alum.mit.edu
Sun Aug 24 09:15:15 PDT 2014


On Sun, Aug 24, 2014 at 7:44 AM, Marek Olšák <maraeo at gmail.com> wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> This fixes crashes if the number of temporaries is greater than 4096.
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66184
> Cc: 10.2 10.3 mesa-stable at lists.freedesktop.org
> ---
>  src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 45 ++++++++++++++++++------------
>  1 file changed, 27 insertions(+), 18 deletions(-)
>
> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> index 84bdc4f..9beecf8 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> @@ -75,14 +75,6 @@ extern "C" {
>                             (1 << PROGRAM_UNIFORM))
>
>  /**
> - * Maximum number of temporary registers.
> - *
> - * It is too big for stack allocated arrays -- it will cause stack overflow on
> - * Windows and likely Mac OS X.
> - */
> -#define MAX_TEMPS         4096
> -
> -/**
>   * Maximum number of arrays
>   */
>  #define MAX_ARRAYS        256
> @@ -3301,14 +3293,10 @@ get_src_arg_mask(st_dst_reg dst, st_src_reg src)
>  void
>  glsl_to_tgsi_visitor::simplify_cmp(void)
>  {
> -   unsigned *tempWrites;
> +   int tempWritesSize = 0;
> +   unsigned *tempWrites = NULL;
>     unsigned outputWrites[MAX_PROGRAM_OUTPUTS];
>
> -   tempWrites = new unsigned[MAX_TEMPS];
> -   if (!tempWrites) {
> -      return;
> -   }
> -   memset(tempWrites, 0, sizeof(unsigned) * MAX_TEMPS);
>     memset(outputWrites, 0, sizeof(outputWrites));
>
>     foreach_in_list(glsl_to_tgsi_instruction, inst, &this->instructions) {
> @@ -3330,7 +3318,16 @@ glsl_to_tgsi_visitor::simplify_cmp(void)
>           prevWriteMask = outputWrites[inst->dst.index];
>           outputWrites[inst->dst.index] |= inst->dst.writemask;
>        } else if (inst->dst.file == PROGRAM_TEMPORARY) {
> -         assert(inst->dst.index < MAX_TEMPS);
> +         if (inst->dst.index >= tempWritesSize) {
> +            const int inc = 4096;
> +
> +            tempWrites = (unsigned*)
> +                         realloc(tempWrites,
> +                                 (tempWritesSize + inc) * sizeof(unsigned));

This can fail, the old code dealt with new returning NULL. Not sure
what the general policy for that is in mesa, but I have seen a lot of
allocation checks. Probably makes sense here too.

> +            memset(tempWrites + tempWritesSize, 0, inc * sizeof(unsigned));
> +            tempWritesSize += inc;
> +         }
> +
>           prevWriteMask = tempWrites[inst->dst.index];
>           tempWrites[inst->dst.index] |= inst->dst.writemask;
>        } else
> @@ -3349,7 +3346,7 @@ glsl_to_tgsi_visitor::simplify_cmp(void)
>        }
>     }
>
> -   delete [] tempWrites;
> +   free(tempWrites);
>  }
>
>  /* Replaces all references to a temporary register index with another index. */
> @@ -4158,7 +4155,9 @@ struct label {
>  struct st_translate {
>     struct ureg_program *ureg;
>
> -   struct ureg_dst temps[MAX_TEMPS];
> +   unsigned temps_size;
> +   struct ureg_dst *temps;
> +
>     struct ureg_dst arrays[MAX_ARRAYS];
>     struct ureg_src *constants;
>     struct ureg_src *immediates;
> @@ -4299,7 +4298,16 @@ dst_register(struct st_translate *t,
>        return ureg_dst_undef();
>
>     case PROGRAM_TEMPORARY:
> -      assert(index < Elements(t->temps));
> +      /* Allocate space for temporaries on demand. */
> +      if (index >= t->temps_size) {
> +         const int inc = 4096;
> +
> +         t->temps = (struct ureg_dst*)
> +                    realloc(t->temps,
> +                            (t->temps_size + inc) * sizeof(struct ureg_dst));

Check alloc?

With that fixed,

Reviewed-by: Ilia Mirkin <imirkin at alum.mit.edu>

BTW, should this in any way be related to PIPE_SHADER_CAP_MAX_TEMPS?
Looking at what drivers set this to, it's fairly small values. e.g.
nvc0 returns 128. I guess there's limited spilling space. OTOH, it can
do a *lot* better than TGSI at storing stuff due to optimizations,
register reuse, etc.

> +         memset(t->temps + t->temps_size, 0, inc * sizeof(struct ureg_dst));
> +         t->temps_size += inc;
> +      }
>
>        if (ureg_dst_is_undef(t->temps[index]))
>           t->temps[index] = ureg_DECL_local_temporary(t->ureg);
> @@ -5158,6 +5166,7 @@ st_translate_program(
>
>  out:
>     if (t) {
> +      free(t->temps);
>        free(t->insn);
>        free(t->labels);
>        free(t->constants);
> --
> 1.9.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list