summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang/slang_vartable.c
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-01-13 14:49:52 -0700
committerBrian <brian@yutani.localnet.net>2007-01-13 14:49:52 -0700
commit691ed5e54b0dc305c9a117a6a9804435041a86f0 (patch)
treef43dcd52cfd382c4d1f0c3c90fb28140d55e44dc /src/mesa/shader/slang/slang_vartable.c
parent5daa99d2a40fa12d51043c4e326bf62f66ef727d (diff)
Rework code related to temp register allocation, both for user variables
and expression temporarires. Much better register utilization now. Lots of other fixes. The OpenGL GLSL "orange book" brick shader demo works now.
Diffstat (limited to 'src/mesa/shader/slang/slang_vartable.c')
-rw-r--r--src/mesa/shader/slang/slang_vartable.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/src/mesa/shader/slang/slang_vartable.c b/src/mesa/shader/slang/slang_vartable.c
new file mode 100644
index 0000000000..cd6a081e04
--- /dev/null
+++ b/src/mesa/shader/slang/slang_vartable.c
@@ -0,0 +1,202 @@
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "slang_compile_variable.h"
+#include "slang_vartable.h"
+
+
+static int dbg = 0;
+
+
+typedef enum {
+ FREE,
+ VAR,
+ TEMP
+} TempState;
+
+static int Level = 0;
+
+struct slang_var_table_
+{
+ int level;
+ int num_entries;
+ slang_variable **vars; /* array [num_entries] */
+
+ TempState temps[MAX_PROGRAM_TEMPS];
+
+ struct slang_var_table_ *parent;
+};
+
+
+
+/**
+ * Create new table, put at head, return ptr to it.
+ */
+slang_var_table *
+_slang_push_var_table(slang_var_table *parent)
+{
+ slang_var_table *t
+ = (slang_var_table *) _mesa_calloc(sizeof(slang_var_table));
+ if (t) {
+ t->level = Level++;
+ t->parent = parent;
+ if (parent) {
+ /* copy the info indicating which temp regs are in use */
+ memcpy(t->temps, parent->temps, sizeof(t->temps));
+ }
+ if (dbg) printf("Pushing level %d\n", t->level);
+ }
+ return t;
+}
+
+
+/**
+ * Destroy given table, return ptr to parent
+ */
+slang_var_table *
+_slang_pop_var_table(slang_var_table *t)
+{
+ slang_var_table *parent = t->parent;
+ int i;
+ if (dbg) printf("Popping level %d\n", t->level);
+ if (t->parent) {
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (t->temps[i] && !t->parent->temps[i])
+ if (dbg) printf(" Free reg %d\n", i);
+ }
+ }
+ for (i = 0; i < t->num_entries; i++) {
+ if (dbg) printf(" Free var %s\n", (char*) t->vars[i]->a_name);
+ }
+
+ if (t->vars)
+ free(t->vars);
+ free(t);
+ Level--;
+ return parent;
+}
+
+
+/**
+ * Add a new variable to the given symbol table.
+ */
+void
+_slang_add_variable(slang_var_table *t, slang_variable *v)
+{
+ assert(t);
+ t->vars = realloc(t->vars, (t->num_entries + 1) * sizeof(slang_variable *));
+ t->vars[t->num_entries] = v;
+ t->num_entries++;
+}
+
+
+/**
+ * Look for variable by name in given table.
+ * If not found, parent table will be searched.
+ */
+slang_variable *
+_slang_find_variable(const slang_var_table *t, slang_atom name)
+{
+ while (1) {
+ int i;
+ for (i = 0; i < t->num_entries; i++) {
+ if (t->vars[i]->a_name == name)
+ return t->vars[i];
+ }
+ if (t->parent)
+ t = t->parent;
+ else
+ return NULL;
+ }
+}
+
+
+static GLint
+alloc_reg(slang_var_table *t, GLint size, GLboolean isTemp)
+{
+ const GLuint sz4 = (size + 3) / 4;
+ GLuint i, j;
+ assert(size > 0); /* number of floats */
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ GLuint found = 0;
+ for (j = 0; j < sz4; j++) {
+ if (!t->temps[i + j]) {
+ found++;
+ }
+ else {
+ break;
+ }
+ }
+ if (found == sz4) {
+ /* found block of size/4 free regs */
+ for (j = 0; j < sz4; j++)
+ t->temps[i + j] = isTemp ? TEMP : VAR;
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Allocate temp register(s) for storing a variable.
+ */
+GLint
+_slang_alloc_var(slang_var_table *t, GLint size)
+{
+ int i = alloc_reg(t, size, GL_FALSE);
+ if (dbg) printf("Alloc var %d (level %d)\n", i, t->level);
+ return i;
+}
+
+
+void
+_slang_reserve_var(slang_var_table *t, GLint r, GLint size)
+{
+ const GLint sz4 = (size + 3) / 4;
+ GLint i;
+ for (i = 0; i < sz4; i++) {
+ t->temps[r + i] = VAR;
+ }
+}
+
+
+/**
+ * Allocate temp register(s) for storing an unnamed intermediate value.
+ */
+GLint
+_slang_alloc_temp(slang_var_table *t, GLint size)
+{
+ int i = alloc_reg(t, size, GL_TRUE);
+ if (dbg) printf("Alloc temp %d (level %d)\n", i, t->level);
+ return i;
+}
+
+
+void
+_slang_free_temp(slang_var_table *t, GLint r, GLint size)
+{
+ const GLuint sz4 = (size + 3) / 4;
+ GLuint i;
+ assert(size > 0);
+ assert(r >= 0);
+ assert(r < MAX_PROGRAM_TEMPS);
+ if (dbg) printf("Free temp %d (level %d)\n", r, t->level);
+ for (i = 0; i < sz4; i++) {
+ assert(t->temps[r + i] == TEMP);
+ t->temps[r + i] = FREE;
+ }
+}
+
+
+GLboolean
+_slang_is_temp(slang_var_table *t, GLint r)
+{
+ assert(r >= 0);
+ assert(r < MAX_PROGRAM_TEMPS);
+ if (t->temps[r] == TEMP)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}