gallium/tgsi: Introduce the "LOCAL" register declaration modifier.
authorFrancisco Jerez <currojerez@riseup.net>
Sun, 18 Mar 2012 18:21:36 +0000 (19:21 +0100)
committerFrancisco Jerez <currojerez@riseup.net>
Fri, 11 May 2012 10:39:41 +0000 (12:39 +0200)
This change will be useful to implement function parameter passing on
top of TGSI.  As we don't have a proper stack, a register-based
calling convention will be used instead, which isn't necessarily a bad
thing given that GPUs often have plenty of registers to spare.

Using the same register space for local temporaries and
inter-procedural communication caused some inefficiencies, because in
some cases the register allocator would lose the freedom to merge
temporary values together into the same physical register, leading to
suboptimal register (and sometimes, as a side effect, instruction)
usage.

The LOCAL declaration modifier specifies that the value isn't intended
for parameter passing and as a result the compiler doesn't have to
give any guarantees of it being preserved across function boundaries.

Ignoring the LOCAL flag doesn't change the semantics of a valid
program in any way, because local variables are just supposed to get a
more relaxed treatment.  IOW, this should be a backwards-compatible
change.

src/gallium/auxiliary/tgsi/tgsi_build.c
src/gallium/auxiliary/tgsi/tgsi_dump.c
src/gallium/auxiliary/tgsi/tgsi_text.c
src/gallium/docs/source/tgsi.rst
src/gallium/include/pipe/p_shader_tokens.h

index 8378075b3e94dfc7db4f7c33f09bffc6e8bd902f..ed725c53966b09545b5268ad6ef693b5915bb55e 100644 (file)
@@ -108,6 +108,7 @@ tgsi_default_declaration( void )
    declaration.Dimension = 0;
    declaration.Semantic = 0;
    declaration.Invariant = 0;
+   declaration.Local = 0;
 
    return declaration;
 }
@@ -120,6 +121,7 @@ tgsi_build_declaration(
    unsigned dimension,
    unsigned semantic,
    unsigned invariant,
+   unsigned local,
    struct tgsi_header *header )
 {
    struct tgsi_declaration declaration;
@@ -134,6 +136,7 @@ tgsi_build_declaration(
    declaration.Dimension = dimension;
    declaration.Semantic = semantic;
    declaration.Invariant = invariant;
+   declaration.Local = local;
 
    header_bodysize_grow( header );
 
@@ -359,6 +362,7 @@ tgsi_build_full_declaration(
       full_decl->Declaration.Dimension,
       full_decl->Declaration.Semantic,
       full_decl->Declaration.Invariant,
+      full_decl->Declaration.Local,
       header );
 
    if (maxsize <= size)
index 3685946687726b80f40d6505495cd1c5183bf1f8..383c54590afca5de65b8a578e74dd58117223791 100644 (file)
@@ -271,6 +271,9 @@ iter_declaration(
       ctx,
       decl->Declaration.UsageMask );
 
+   if (decl->Declaration.Local)
+      TXT( ", LOCAL" );
+
    if (decl->Declaration.Semantic) {
       TXT( ", " );
       ENM( decl->Semantic.Name, tgsi_semantic_names );
index 52e30b401692c76f3aa2b97a127892102488a1f5..c87313a3c16d1c7ce0e6f197894965c4d9dc03ed 100644 (file)
@@ -1161,38 +1161,51 @@ static boolean parse_declaration( struct translate_ctx *ctx )
          }
          ctx->cur = cur;
       } else {
-         for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
-            if (str_match_no_case( &cur, tgsi_semantic_names[i] )) {
-               const char *cur2 = cur;
-               uint index;
+         if (str_match_no_case(&cur, "LOCAL") &&
+             !is_digit_alpha_underscore(cur)) {
+            decl.Declaration.Local = 1;
+            ctx->cur = cur;
+         }
 
-               if (is_digit_alpha_underscore( cur ))
-                  continue;
-               eat_opt_white( &cur2 );
-               if (*cur2 == '[') {
-                  cur2++;
-                  eat_opt_white( &cur2 );
-                  if (!parse_uint( &cur2, &index )) {
-                     report_error( ctx, "Expected literal integer" );
-                     return FALSE;
-                  }
+         cur = ctx->cur;
+         eat_opt_white( &cur );
+         if (*cur == ',') {
+            cur++;
+            eat_opt_white( &cur );
+
+            for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
+               if (str_match_no_case( &cur, tgsi_semantic_names[i] )) {
+                  uint index;
+
+                  if (is_digit_alpha_underscore( cur ))
+                     continue;
+                  cur2 = cur;
                   eat_opt_white( &cur2 );
-                  if (*cur2 != ']') {
-                     report_error( ctx, "Expected `]'" );
-                     return FALSE;
-                  }
-                  cur2++;
+                  if (*cur2 == '[') {
+                     cur2++;
+                     eat_opt_white( &cur2 );
+                     if (!parse_uint( &cur2, &index )) {
+                        report_error( ctx, "Expected literal integer" );
+                        return FALSE;
+                     }
+                     eat_opt_white( &cur2 );
+                     if (*cur2 != ']') {
+                        report_error( ctx, "Expected `]'" );
+                        return FALSE;
+                     }
+                     cur2++;
 
-                  decl.Semantic.Index = index;
+                     decl.Semantic.Index = index;
 
-                  cur = cur2;
-               }
+                     cur = cur2;
+                  }
 
-               decl.Declaration.Semantic = 1;
-               decl.Semantic.Name = i;
+                  decl.Declaration.Semantic = 1;
+                  decl.Semantic.Name = i;
 
-               ctx->cur = cur;
-               break;
+                  ctx->cur = cur;
+                  break;
+               }
             }
          }
       }
index 1155ff391c1302e67f60e92cb895d398764bc15f..548a9a398556d79368c910a67be8f0b90b7736f8 100644 (file)
@@ -1795,6 +1795,12 @@ of TGSI_FILE.
 UsageMask field specifies which of the register components can be accessed
 and is one of TGSI_WRITEMASK.
 
+The Local flag specifies that a given value isn't intended for
+subroutine parameter passing and, as a result, the implementation
+isn't required to give any guarantees of it being preserved across
+subroutine boundaries.  As it's merely a compiler hint, the
+implementation is free to ignore it.
+
 If Dimension flag is set to 1, a Declaration Dimension token follows.
 
 If Semantic flag is set to 1, a Declaration Semantic token follows.
index 2579112a25b1651af5bec201602b89e0135b3a47..5325e43896c91ff6bb7c530abda1fc1ba6539e54 100644 (file)
@@ -120,7 +120,8 @@ struct tgsi_declaration
    unsigned Semantic    : 1;  /**< BOOL, any semantic info? */
    unsigned Interpolate : 1;  /**< any interpolation info? */
    unsigned Invariant   : 1;  /**< invariant optimization? */
-   unsigned Padding     : 8;
+   unsigned Local       : 1;  /**< optimize as subroutine local variable? */
+   unsigned Padding     : 7;
 };
 
 struct tgsi_declaration_range