~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/shader/slang/slang_vartable.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "imports.h"
 
3
#include "slang_compile.h"
 
4
#include "slang_compile_variable.h"
 
5
#include "slang_mem.h"
 
6
#include "slang_vartable.h"
 
7
#include "slang_ir.h"
 
8
#include "prog_instruction.h"
 
9
 
 
10
 
 
11
static int dbg = 0;
 
12
 
 
13
 
 
14
typedef enum {
 
15
   FREE,
 
16
   VAR,
 
17
   TEMP
 
18
} TempState;
 
19
 
 
20
 
 
21
/**
 
22
 * Variable/register info for one variable scope.
 
23
 */
 
24
struct table
 
25
{
 
26
   int Level;
 
27
   int NumVars;
 
28
   slang_variable **Vars;  /* array [NumVars] */
 
29
 
 
30
   TempState Temps[MAX_PROGRAM_TEMPS * 4];  /* per-component state */
 
31
   int ValSize[MAX_PROGRAM_TEMPS];     /* For debug only */
 
32
 
 
33
   struct table *Parent;  /** Parent scope table */
 
34
};
 
35
 
 
36
 
 
37
/**
 
38
 * A variable table is a stack of tables, one per scope.
 
39
 */
 
40
struct slang_var_table_
 
41
{
 
42
   GLint CurLevel;
 
43
   GLuint MaxRegisters;
 
44
   struct table *Top;  /**< Table at top of stack */
 
45
};
 
46
 
 
47
 
 
48
 
 
49
slang_var_table *
 
50
_slang_new_var_table(GLuint maxRegisters)
 
51
{
 
52
   slang_var_table *vt
 
53
      = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
 
54
   if (vt) {
 
55
      vt->MaxRegisters = maxRegisters;
 
56
   }
 
57
   return vt;
 
58
}
 
59
 
 
60
 
 
61
void
 
62
_slang_delete_var_table(slang_var_table *vt)
 
63
{
 
64
   if (vt->Top) {
 
65
      _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
 
66
      return;
 
67
   }
 
68
   _slang_free(vt);
 
69
}
 
70
 
 
71
 
 
72
 
 
73
/**
 
74
 * Create new table, put at head, return ptr to it.
 
75
 * XXX we should take a maxTemps parameter to indicate how many temporaries
 
76
 * are available for the current shader/program target.
 
77
 */
 
78
void
 
79
_slang_push_var_table(slang_var_table *vt)
 
80
{
 
81
   struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
 
82
   if (t) {
 
83
      t->Level = vt->CurLevel++;
 
84
      t->Parent = vt->Top;
 
85
      if (t->Parent) {
 
86
         /* copy the info indicating which temp regs are in use */
 
87
         memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
 
88
         memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
 
89
      }
 
90
      vt->Top = t;
 
91
      if (dbg) printf("Pushing level %d\n", t->Level);
 
92
   }
 
93
}
 
94
 
 
95
 
 
96
/**
 
97
 * Destroy given table, return ptr to Parent
 
98
 */
 
99
void
 
100
_slang_pop_var_table(slang_var_table *vt)
 
101
{
 
102
   struct table *t = vt->Top;
 
103
   int i;
 
104
 
 
105
   if (dbg) printf("Popping level %d\n", t->Level);
 
106
 
 
107
   /* free the storage allocated for each variable */
 
108
   for (i = 0; i < t->NumVars; i++) {
 
109
      slang_ir_storage *store = (slang_ir_storage *) t->Vars[i]->aux;
 
110
      GLint j;
 
111
      GLuint comp;
 
112
      if (dbg) printf("  Free var %s, size %d at %d\n",
 
113
                      (char*) t->Vars[i]->a_name, store->Size,
 
114
                      store->Index);
 
115
 
 
116
      if (store->Size == 1)
 
117
         comp = GET_SWZ(store->Swizzle, 0);
 
118
      else
 
119
         comp = 0;
 
120
 
 
121
      assert(store->Index >= 0);
 
122
      for (j = 0; j < store->Size; j++) {
 
123
         assert(t->Temps[store->Index * 4 + j + comp] == VAR);
 
124
         t->Temps[store->Index * 4 + j + comp] = FREE;
 
125
      }
 
126
      store->Index = -1;
 
127
   }
 
128
   if (t->Parent) {
 
129
      /* just verify that any remaining allocations in this scope 
 
130
       * were for temps
 
131
       */
 
132
      for (i = 0; i < vt->MaxRegisters * 4; i++) {
 
133
         if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
 
134
            if (dbg) printf("  Free reg %d\n", i/4);
 
135
            assert(t->Temps[i] == TEMP);
 
136
         }
 
137
      }
 
138
   }
 
139
 
 
140
   if (t->Vars) {
 
141
      _slang_free(t->Vars);
 
142
      t->Vars = NULL;
 
143
   }
 
144
 
 
145
   vt->Top = t->Parent;
 
146
   _slang_free(t);
 
147
   vt->CurLevel--;
 
148
}
 
149
 
 
150
 
 
151
/**
 
152
 * Add a new variable to the given symbol table.
 
153
 */
 
154
void
 
155
_slang_add_variable(slang_var_table *vt, slang_variable *v)
 
156
{
 
157
   struct table *t;
 
158
   assert(vt);
 
159
   t = vt->Top;
 
160
   assert(t);
 
161
   if (dbg) printf("Adding var %s\n", (char *) v->a_name);
 
162
   t->Vars = (slang_variable **)
 
163
      _slang_realloc(t->Vars,
 
164
                     t->NumVars * sizeof(slang_variable *),
 
165
                     (t->NumVars + 1) * sizeof(slang_variable *));
 
166
   t->Vars[t->NumVars] = v;
 
167
   t->NumVars++;
 
168
}
 
169
 
 
170
 
 
171
/**
 
172
 * Look for variable by name in given table.
 
173
 * If not found, Parent table will be searched.
 
174
 */
 
175
slang_variable *
 
176
_slang_find_variable(const slang_var_table *vt, slang_atom name)
 
177
{
 
178
   struct table *t = vt->Top;
 
179
   while (1) {
 
180
      int i;
 
181
      for (i = 0; i < t->NumVars; i++) {
 
182
         if (t->Vars[i]->a_name == name)
 
183
            return t->Vars[i];
 
184
      }
 
185
      if (t->Parent)
 
186
         t = t->Parent;
 
187
      else
 
188
         return NULL;
 
189
   }
 
190
}
 
191
 
 
192
 
 
193
/**
 
194
 * Allocation helper.
 
195
 * \param size  var size in floats
 
196
 * \return  position for var, measured in floats
 
197
 */
 
198
static GLint
 
199
alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
 
200
{
 
201
   struct table *t = vt->Top;
 
202
   /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
 
203
   const GLuint step = (size == 1) ? 1 : 4;
 
204
   GLuint i, j;
 
205
   assert(size > 0); /* number of floats */
 
206
 
 
207
   for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
 
208
      GLuint found = 0;
 
209
      for (j = 0; j < size; j++) {
 
210
         if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
 
211
            found++;
 
212
         }
 
213
         else {
 
214
            break;
 
215
         }
 
216
      }
 
217
      if (found == size) {
 
218
         /* found block of size free regs */
 
219
         if (size > 1)
 
220
            assert(i % 4 == 0);
 
221
         for (j = 0; j < size; j++)
 
222
            t->Temps[i + j] = isTemp ? TEMP : VAR;
 
223
         t->ValSize[i] = size;
 
224
         return i;
 
225
      }
 
226
   }
 
227
   return -1;
 
228
}
 
229
 
 
230
 
 
231
/**
 
232
 * Allocate temp register(s) for storing a variable.
 
233
 * \param size  size needed, in floats
 
234
 * \param swizzle  returns swizzle mask for accessing var in register
 
235
 * \return  register allocated, or -1
 
236
 */
 
237
GLboolean
 
238
_slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
 
239
{
 
240
   struct table *t = vt->Top;
 
241
   const int i = alloc_reg(vt, store->Size, GL_FALSE);
 
242
   if (i < 0)
 
243
      return GL_FALSE;
 
244
 
 
245
   store->Index = i / 4;
 
246
   if (store->Size == 1) {
 
247
      const GLuint comp = i % 4;
 
248
      store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
 
249
      if (dbg) printf("Alloc var sz %d at %d.%c (level %d)\n",
 
250
                      store->Size, store->Index, "xyzw"[comp], t->Level);
 
251
   }
 
252
   else {
 
253
      store->Swizzle = SWIZZLE_NOOP;
 
254
      if (dbg) printf("Alloc var sz %d at %d.xyzw (level %d)\n",
 
255
                      store->Size, store->Index, t->Level);
 
256
   }
 
257
   return GL_TRUE;
 
258
}
 
259
 
 
260
 
 
261
 
 
262
/**
 
263
 * Allocate temp register(s) for storing an unnamed intermediate value.
 
264
 */
 
265
GLboolean
 
266
_slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
 
267
{
 
268
   struct table *t = vt->Top;
 
269
   const int i = alloc_reg(vt, store->Size, GL_TRUE);
 
270
   if (i < 0)
 
271
      return GL_FALSE;
 
272
 
 
273
   store->Index = i / 4;
 
274
   if (store->Size == 1) {
 
275
      const GLuint comp = i % 4;
 
276
      store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
 
277
      if (dbg) printf("Alloc temp sz %d at %d.%c (level %d)\n",
 
278
                      store->Size, store->Index, "xyzw"[comp], t->Level);
 
279
   }
 
280
   else {
 
281
      store->Swizzle = SWIZZLE_NOOP;
 
282
      if (dbg) printf("Alloc temp sz %d at %d.xyzw (level %d)\n",
 
283
                      store->Size, store->Index, t->Level);
 
284
   }
 
285
   return GL_TRUE;
 
286
}
 
287
 
 
288
 
 
289
void
 
290
_slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
 
291
{
 
292
   struct table *t = vt->Top;
 
293
   GLuint i;
 
294
   GLuint r = store->Index;
 
295
   assert(store->Size > 0);
 
296
   assert(r >= 0);
 
297
   assert(r + store->Size <= vt->MaxRegisters * 4);
 
298
   if (dbg) printf("Free temp sz %d at %d (level %d)\n", store->Size, r, t->Level);
 
299
   if (store->Size == 1) {
 
300
      const GLuint comp = GET_SWZ(store->Swizzle, 0);
 
301
      assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
 
302
      assert(comp < 4);
 
303
      assert(t->ValSize[r * 4 + comp] == 1);
 
304
      assert(t->Temps[r * 4 + comp] == TEMP);
 
305
      t->Temps[r * 4 + comp] = FREE;
 
306
   }
 
307
   else {
 
308
      /*assert(store->Swizzle == SWIZZLE_NOOP);*/
 
309
      assert(t->ValSize[r*4] == store->Size);
 
310
      for (i = 0; i < store->Size; i++) {
 
311
         assert(t->Temps[r * 4 + i] == TEMP);
 
312
         t->Temps[r * 4 + i] = FREE;
 
313
      }
 
314
   }
 
315
}
 
316
 
 
317
 
 
318
GLboolean
 
319
_slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
 
320
{
 
321
   struct table *t = vt->Top;
 
322
   GLuint comp;
 
323
   assert(store->Index >= 0);
 
324
   assert(store->Index < vt->MaxRegisters);
 
325
   if (store->Swizzle == SWIZZLE_NOOP)
 
326
      comp = 0;
 
327
   else
 
328
      comp = GET_SWZ(store->Swizzle, 0);
 
329
 
 
330
   if (t->Temps[store->Index * 4 + comp] == TEMP)
 
331
      return GL_TRUE;
 
332
   else
 
333
      return GL_FALSE;
 
334
}