tgsi: add simple facility for releasing and reusing temporaries
authorKeith Whitwell <keithw@vmware.com>
Thu, 13 Aug 2009 16:22:16 +0000 (17:22 +0100)
committerKeith Whitwell <keithw@vmware.com>
Thu, 13 Aug 2009 16:32:25 +0000 (17:32 +0100)
src/gallium/auxiliary/tgsi/tgsi_ureg.c
src/gallium/auxiliary/tgsi/tgsi_ureg.h

index 368b7a6f9e5073e8328a1dba61dcb3ab58d98723..ba84a82b2b0edc7d0730bac0551c23f73188be6f 100644 (file)
@@ -69,6 +69,7 @@ struct ureg_tokens {
 #define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
 #define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS
 #define UREG_MAX_IMMEDIATE 32
+#define UREG_MAX_TEMP 256
 
 #define DOMAIN_DECL 0
 #define DOMAIN_INSN 1
@@ -94,12 +95,13 @@ struct ureg_program
    struct {
       float v[4];
       unsigned nr;
-   } immediate[UREG_MAX_OUTPUT];
+   } immediate[UREG_MAX_IMMEDIATE];
    unsigned nr_immediates;
 
+   unsigned temps_active[UREG_MAX_TEMP / 32];
+   unsigned nr_temps;
 
    unsigned nr_constants;
-   unsigned nr_temps;
    unsigned nr_samplers;
 
    struct ureg_tokens domain[2];
@@ -303,11 +305,41 @@ struct ureg_src ureg_DECL_constant(struct ureg_program *ureg )
 }
 
 
-/* Allocate a new temporary.  No way to release temporaries in this code. 
+/* Allocate a new temporary.  Temporaries greater than UREG_MAX_TEMP
+ * are legal, but will not be released.
  */
 struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
 {
-   return ureg_dst_register( TGSI_FILE_TEMPORARY, ureg->nr_temps++ );
+   unsigned i;
+
+   for (i = 0; i < UREG_MAX_TEMP; i += 32) {
+      int bit = ffs(~ureg->temps_active[i/32]);
+      if (bit != 0) {
+         i += bit - 1;
+         goto out;
+      }
+   }
+
+   /* No reusable temps, so allocate a new one:
+    */
+   i = ureg->nr_temps++;
+
+out:
+   if (i < UREG_MAX_TEMP)
+      ureg->temps_active[i/32] |= 1 << (i % 32);
+
+   if (i >= ureg->nr_temps)
+      ureg->nr_temps = i + 1;
+
+   return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
+}
+
+
+void ureg_release_temporary( struct ureg_program *ureg,
+                             struct ureg_dst tmp )
+{
+   if (tmp.Index < UREG_MAX_TEMP)
+      ureg->temps_active[tmp.Index/32] &= ~(1 << (tmp.Index % 32));
 }
 
 
index ad7cd8e69c009940d72871c7ac79e9abcaabf7a7..0a976fd63b7f70166d1e9c66a7bb45f5e3ec0a75 100644 (file)
@@ -122,6 +122,10 @@ ureg_DECL_constant( struct ureg_program * );
 struct ureg_dst
 ureg_DECL_temporary( struct ureg_program * );
 
+void 
+ureg_release_temporary( struct ureg_program *ureg,
+                        struct ureg_dst tmp );
+
 struct ureg_src
 ureg_DECL_sampler( struct ureg_program * );