aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/tgsi
diff options
context:
space:
mode:
authorFrancisco Jerez <[email protected]>2012-03-26 17:55:30 +0200
committerFrancisco Jerez <[email protected]>2012-05-11 12:39:42 +0200
commitb52e374ad3b568fc1eb35df80e90a39b4cb99289 (patch)
treefa48dd0e03093a8125e1d840a0a11a21a61db36f /src/gallium/auxiliary/tgsi
parent1b8aecc797b72a84c4a571639e952fe1f84e0fa5 (diff)
gallium/tgsi/ureg: Support local temporary emission.
Diffstat (limited to 'src/gallium/auxiliary/tgsi')
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.c58
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.h8
2 files changed, 60 insertions, 6 deletions
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index 4cf8a9696ba..e427585db19 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -152,6 +152,7 @@ struct ureg_program
unsigned nr_sampler_views;
struct util_bitmask *free_temps;
+ struct util_bitmask *local_temps;
unsigned nr_temps;
struct const_decl const_decls;
@@ -530,11 +531,19 @@ out:
return ureg_src_register(TGSI_FILE_CONSTANT, index);
}
-struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
+static struct ureg_dst alloc_temporary( struct ureg_program *ureg,
+ boolean local )
{
+ unsigned i;
+
/* Look for a released temporary.
*/
- unsigned i = util_bitmask_get_first_index(ureg->free_temps);
+ for (i = util_bitmask_get_first_index(ureg->free_temps);
+ i != UTIL_BITMASK_INVALID_INDEX;
+ i = util_bitmask_get_next_index(ureg->free_temps, i + 1)) {
+ if (util_bitmask_get(ureg->local_temps, i) == local)
+ break;
+ }
/* Or allocate a new one.
*/
@@ -543,9 +552,22 @@ struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
util_bitmask_clear(ureg->free_temps, i);
+ if (local)
+ util_bitmask_set(ureg->local_temps, i);
+
return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
}
+struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
+{
+ return alloc_temporary(ureg, FALSE);
+}
+
+struct ureg_dst ureg_DECL_local_temporary( struct ureg_program *ureg )
+{
+ return alloc_temporary(ureg, TRUE);
+}
+
void ureg_release_temporary( struct ureg_program *ureg,
struct ureg_dst tmp )
{
@@ -1239,6 +1261,25 @@ emit_decl_fs(struct ureg_program *ureg,
}
+static void emit_decl( struct ureg_program *ureg,
+ unsigned file,
+ unsigned index,
+ boolean local )
+{
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
+
+ out[0].value = 0;
+ out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
+ out[0].decl.NrTokens = 2;
+ out[0].decl.File = file;
+ out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
+ out[0].decl.Local = local;
+
+ out[1].value = 0;
+ out[1].decl_range.First = index;
+ out[1].decl_range.Last = index;
+}
+
static void emit_decl_range( struct ureg_program *ureg,
unsigned file,
unsigned first,
@@ -1493,10 +1534,9 @@ static void emit_decls( struct ureg_program *ureg )
}
}
- if (ureg->nr_temps) {
- emit_decl_range( ureg,
- TGSI_FILE_TEMPORARY,
- 0, ureg->nr_temps );
+ for (i = 0; i < ureg->nr_temps; i++) {
+ emit_decl( ureg, TGSI_FILE_TEMPORARY, i,
+ util_bitmask_get(ureg->local_temps, i) );
}
if (ureg->nr_addrs) {
@@ -1658,9 +1698,14 @@ struct ureg_program *ureg_create( unsigned processor )
if (ureg->free_temps == NULL)
goto fail;
+ ureg->local_temps = util_bitmask_create();
+ if (ureg->local_temps == NULL)
+ goto fail;
+
return ureg;
fail:
+ FREE(ureg->free_temps);
FREE(ureg);
return NULL;
}
@@ -1677,6 +1722,7 @@ void ureg_destroy( struct ureg_program *ureg )
}
util_bitmask_destroy(ureg->free_temps);
+ util_bitmask_destroy(ureg->local_temps);
FREE(ureg);
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
index b1297a25a94..e6131f25aae 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
@@ -272,6 +272,14 @@ ureg_DECL_constant( struct ureg_program *,
struct ureg_dst
ureg_DECL_temporary( struct ureg_program * );
+/**
+ * Emit a temporary with the LOCAL declaration flag set. For use when
+ * the register value is not required to be preserved across
+ * subroutine boundaries.
+ */
+struct ureg_dst
+ureg_DECL_local_temporary( struct ureg_program * );
+
void
ureg_release_temporary( struct ureg_program *ureg,
struct ureg_dst tmp );