~ubuntu-branches/ubuntu/natty/mesa/natty-proposed

« back to all changes in this revision

Viewing changes to src/glsl/ir_validate.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Robert Hooker, Robert Hooker, Christopher James Halse Rogers
  • Date: 2010-09-14 08:55:40 UTC
  • mfrom: (1.2.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20100914085540-m4fpl0hdjlfd4jgz
Tags: 7.9~git20100909-0ubuntu1
[ Robert Hooker ]
* New upstream git snapshot up to commit 94118fe2d4b1e5 (LP: #631413)
* New features include ATI HD5xxx series support in r600, and a vastly
  improved glsl compiler.
* Remove pre-generated .pc's, use the ones generated at build time
  instead.
* Remove all references to mesa-utils now that its no longer shipped
  with the mesa source.
* Disable the experimental ARB_fragment_shader option by default on
  i915, it exposes incomplete functionality that breaks KDE compositing
  among other things. It can be enabled via driconf still. (LP: #628930).

[ Christopher James Halse Rogers ]
* debian/patches/04_osmesa_version.diff:
  - Refresh for new upstream
* Bugs fixed in this release:
  - Fixes severe rendering corruption in Unity on radeon (LP: #628727,
    LP: #596292, LP: #599741, LP: #630315, LP: #613694, LP: #599741).
  - Also fixes rendering in gnome-shell (LP: #578619).
  - Flickering in OpenGL apps on radeon (LP: #626943, LP: #610541).
  - Provides preliminary support for new intel chips (LP: #601052).
* debian/rules:
  - Update configure flags to match upstream reshuffling.
  - Explicitly remove gallium DRI drivers that we don't want to ship.
* Update debian/gbp.conf for this Maverick-specific packaging
* libegl1-mesa-dri-x11,kms: There are no longer separate kms or x11 drivers
  for EGL, libegl1-mesa-drivers now contains a single driver that provides
  both backends.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2010 Intel Corporation
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice (including the next
 
12
 * paragraph) shall be included in all copies or substantial portions of the
 
13
 * Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
21
 * DEALINGS IN THE SOFTWARE.
 
22
 */
 
23
 
 
24
/**
 
25
 * \file ir_validate.cpp
 
26
 *
 
27
 * Attempts to verify that various invariants of the IR tree are true.
 
28
 *
 
29
 * In particular, at the moment it makes sure that no single
 
30
 * ir_instruction node except for ir_variable appears multiple times
 
31
 * in the ir tree.  ir_variable does appear multiple times: Once as a
 
32
 * declaration in an exec_list, and multiple times as the endpoint of
 
33
 * a dereference chain.
 
34
 */
 
35
 
 
36
#include <inttypes.h>
 
37
#include "ir.h"
 
38
#include "ir_hierarchical_visitor.h"
 
39
#include "program/hash_table.h"
 
40
#include "glsl_types.h"
 
41
 
 
42
class ir_validate : public ir_hierarchical_visitor {
 
43
public:
 
44
   ir_validate()
 
45
   {
 
46
      this->ht = hash_table_ctor(0, hash_table_pointer_hash,
 
47
                                 hash_table_pointer_compare);
 
48
 
 
49
      this->current_function = NULL;
 
50
 
 
51
      this->callback = ir_validate::validate_ir;
 
52
      this->data = ht;
 
53
   }
 
54
 
 
55
   ~ir_validate()
 
56
   {
 
57
      hash_table_dtor(this->ht);
 
58
   }
 
59
 
 
60
   virtual ir_visitor_status visit(ir_variable *v);
 
61
   virtual ir_visitor_status visit(ir_dereference_variable *ir);
 
62
   virtual ir_visitor_status visit(ir_if *ir);
 
63
 
 
64
   virtual ir_visitor_status visit_leave(ir_loop *ir);
 
65
   virtual ir_visitor_status visit_enter(ir_function *ir);
 
66
   virtual ir_visitor_status visit_leave(ir_function *ir);
 
67
   virtual ir_visitor_status visit_enter(ir_function_signature *ir);
 
68
 
 
69
   virtual ir_visitor_status visit_leave(ir_expression *ir);
 
70
 
 
71
   virtual ir_visitor_status visit_enter(ir_assignment *ir);
 
72
 
 
73
   static void validate_ir(ir_instruction *ir, void *data);
 
74
 
 
75
   ir_function *current_function;
 
76
 
 
77
   struct hash_table *ht;
 
78
};
 
79
 
 
80
 
 
81
ir_visitor_status
 
82
ir_validate::visit(ir_dereference_variable *ir)
 
83
{
 
84
   if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
 
85
      printf("ir_dereference_variable @ %p does not specify a variable %p\n",
 
86
             (void *) ir, (void *) ir->var);
 
87
      abort();
 
88
   }
 
89
 
 
90
   if (hash_table_find(ht, ir->var) == NULL) {
 
91
      printf("ir_dereference_variable @ %p specifies undeclared variable "
 
92
             "`%s' @ %p\n",
 
93
             (void *) ir, ir->var->name, (void *) ir->var);
 
94
      abort();
 
95
   }
 
96
 
 
97
   this->validate_ir(ir, this->data);
 
98
 
 
99
   return visit_continue;
 
100
}
 
101
 
 
102
ir_visitor_status
 
103
ir_validate::visit(ir_if *ir)
 
104
{
 
105
   if (ir->condition->type != glsl_type::bool_type) {
 
106
      printf("ir_if condition %s type instead of bool.\n",
 
107
             ir->condition->type->name);
 
108
      ir->print();
 
109
      printf("\n");
 
110
      abort();
 
111
   }
 
112
 
 
113
   return visit_continue;
 
114
}
 
115
 
 
116
 
 
117
ir_visitor_status
 
118
ir_validate::visit_leave(ir_loop *ir)
 
119
{
 
120
   if (ir->counter != NULL) {
 
121
      if ((ir->from == NULL) || (ir->from == NULL) || (ir->increment == NULL)) {
 
122
         printf("ir_loop has invalid loop controls:\n"
 
123
                "    counter:   %p\n"
 
124
                "    from:      %p\n"
 
125
                "    to:        %p\n"
 
126
                "    increment: %p\n",
 
127
                ir->counter, ir->from, ir->to, ir->increment);
 
128
         abort();
 
129
      }
 
130
 
 
131
      if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) {
 
132
         printf("ir_loop has invalid comparitor %d\n", ir->cmp);
 
133
         abort();
 
134
      }
 
135
   } else {
 
136
      if ((ir->from != NULL) || (ir->from != NULL) || (ir->increment != NULL)) {
 
137
         printf("ir_loop has invalid loop controls:\n"
 
138
                "    counter:   %p\n"
 
139
                "    from:      %p\n"
 
140
                "    to:        %p\n"
 
141
                "    increment: %p\n",
 
142
                ir->counter, ir->from, ir->to, ir->increment);
 
143
         abort();
 
144
      }
 
145
   }
 
146
 
 
147
   return visit_continue;
 
148
}
 
149
 
 
150
 
 
151
ir_visitor_status
 
152
ir_validate::visit_enter(ir_function *ir)
 
153
{
 
154
   /* Function definitions cannot be nested.
 
155
    */
 
156
   if (this->current_function != NULL) {
 
157
      printf("Function definition nested inside another function "
 
158
             "definition:\n");
 
159
      printf("%s %p inside %s %p\n",
 
160
             ir->name, (void *) ir,
 
161
             this->current_function->name, (void *) this->current_function);
 
162
      abort();
 
163
   }
 
164
 
 
165
   /* Store the current function hierarchy being traversed.  This is used
 
166
    * by the function signature visitor to ensure that the signatures are
 
167
    * linked with the correct functions.
 
168
    */
 
169
   this->current_function = ir;
 
170
 
 
171
   this->validate_ir(ir, this->data);
 
172
 
 
173
   return visit_continue;
 
174
}
 
175
 
 
176
ir_visitor_status
 
177
ir_validate::visit_leave(ir_function *ir)
 
178
{
 
179
   assert(talloc_parent(ir->name) == ir);
 
180
 
 
181
   this->current_function = NULL;
 
182
   return visit_continue;
 
183
}
 
184
 
 
185
ir_visitor_status
 
186
ir_validate::visit_enter(ir_function_signature *ir)
 
187
{
 
188
   if (this->current_function != ir->function()) {
 
189
      printf("Function signature nested inside wrong function "
 
190
             "definition:\n");
 
191
      printf("%p inside %s %p instead of %s %p\n",
 
192
             (void *) ir,
 
193
             this->current_function->name, (void *) this->current_function,
 
194
             ir->function_name(), (void *) ir->function());
 
195
      abort();
 
196
   }
 
197
 
 
198
   this->validate_ir(ir, this->data);
 
199
 
 
200
   return visit_continue;
 
201
}
 
202
 
 
203
ir_visitor_status
 
204
ir_validate::visit_leave(ir_expression *ir)
 
205
{
 
206
   switch (ir->operation) {
 
207
   case ir_unop_bit_not:
 
208
      assert(ir->operands[0]->type == ir->type);
 
209
      break;
 
210
   case ir_unop_logic_not:
 
211
      assert(ir->type->base_type == GLSL_TYPE_BOOL);
 
212
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
 
213
      break;
 
214
 
 
215
   case ir_unop_neg:
 
216
   case ir_unop_abs:
 
217
   case ir_unop_sign:
 
218
   case ir_unop_rcp:
 
219
   case ir_unop_rsq:
 
220
   case ir_unop_sqrt:
 
221
      assert(ir->type == ir->operands[0]->type);
 
222
      break;
 
223
 
 
224
   case ir_unop_exp:
 
225
   case ir_unop_log:
 
226
   case ir_unop_exp2:
 
227
   case ir_unop_log2:
 
228
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
 
229
      assert(ir->type == ir->operands[0]->type);
 
230
      break;
 
231
 
 
232
   case ir_unop_f2i:
 
233
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
 
234
      assert(ir->type->base_type == GLSL_TYPE_INT);
 
235
      break;
 
236
   case ir_unop_i2f:
 
237
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
 
238
      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
 
239
      break;
 
240
   case ir_unop_f2b:
 
241
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
 
242
      assert(ir->type->base_type == GLSL_TYPE_BOOL);
 
243
      break;
 
244
   case ir_unop_b2f:
 
245
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
 
246
      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
 
247
      break;
 
248
   case ir_unop_i2b:
 
249
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
 
250
      assert(ir->type->base_type == GLSL_TYPE_BOOL);
 
251
      break;
 
252
   case ir_unop_b2i:
 
253
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
 
254
      assert(ir->type->base_type == GLSL_TYPE_INT);
 
255
      break;
 
256
   case ir_unop_u2f:
 
257
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
 
258
      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
 
259
      break;
 
260
 
 
261
   case ir_unop_any:
 
262
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
 
263
      assert(ir->type == glsl_type::bool_type);
 
264
      break;
 
265
 
 
266
   case ir_unop_trunc:
 
267
   case ir_unop_ceil:
 
268
   case ir_unop_floor:
 
269
   case ir_unop_fract:
 
270
   case ir_unop_sin:
 
271
   case ir_unop_cos:
 
272
   case ir_unop_dFdx:
 
273
   case ir_unop_dFdy:
 
274
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
 
275
      assert(ir->operands[0]->type == ir->type);
 
276
      break;
 
277
 
 
278
   case ir_binop_add:
 
279
   case ir_binop_sub:
 
280
   case ir_binop_mul:
 
281
   case ir_binop_div:
 
282
   case ir_binop_mod:
 
283
   case ir_binop_min:
 
284
   case ir_binop_max:
 
285
   case ir_binop_pow:
 
286
      if (ir->operands[0]->type->is_scalar())
 
287
         assert(ir->operands[1]->type == ir->type);
 
288
      else if (ir->operands[1]->type->is_scalar())
 
289
         assert(ir->operands[0]->type == ir->type);
 
290
      else if (ir->operands[0]->type->is_vector() &&
 
291
               ir->operands[1]->type->is_vector()) {
 
292
         assert(ir->operands[0]->type == ir->operands[1]->type);
 
293
         assert(ir->operands[0]->type == ir->type);
 
294
      }
 
295
      break;
 
296
   case ir_binop_less:
 
297
   case ir_binop_greater:
 
298
   case ir_binop_lequal:
 
299
   case ir_binop_gequal:
 
300
      /* GLSL < > <= >= operators take scalar floats/ints, but in the
 
301
       * IR we may want to do them for vectors instead to support the
 
302
       * lessEqual() and friends builtins.
 
303
       */
 
304
      assert(ir->type == glsl_type::bool_type);
 
305
      assert(ir->operands[0]->type == ir->operands[1]->type);
 
306
      break;
 
307
 
 
308
   case ir_binop_equal:
 
309
   case ir_binop_nequal:
 
310
      /* GLSL == and != operate on vectors and return a bool, and the
 
311
       * IR matches that.  We may want to switch up the IR to work on
 
312
       * vectors and return a bvec and make the operators break down
 
313
       * to ANDing/ORing the results of the vector comparison.
 
314
       */
 
315
      assert(ir->type == glsl_type::bool_type);
 
316
      assert(ir->operands[0]->type == ir->operands[1]->type);
 
317
      break;
 
318
 
 
319
   case ir_binop_lshift:
 
320
   case ir_binop_rshift:
 
321
   case ir_binop_bit_and:
 
322
   case ir_binop_bit_xor:
 
323
   case ir_binop_bit_or:
 
324
      assert(ir->operands[0]->type == ir->operands[1]->type);
 
325
      assert(ir->type == ir->operands[0]->type);
 
326
      assert(ir->type->base_type == GLSL_TYPE_INT ||
 
327
             ir->type->base_type == GLSL_TYPE_UINT);
 
328
      break;
 
329
 
 
330
   case ir_binop_logic_and:
 
331
   case ir_binop_logic_xor:
 
332
   case ir_binop_logic_or:
 
333
      assert(ir->type == glsl_type::bool_type);
 
334
      assert(ir->operands[0]->type == glsl_type::bool_type);
 
335
      assert(ir->operands[1]->type == glsl_type::bool_type);
 
336
      break;
 
337
 
 
338
   case ir_binop_dot:
 
339
      assert(ir->type == glsl_type::float_type);
 
340
      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
 
341
      assert(ir->operands[0]->type->is_vector());
 
342
      assert(ir->operands[0]->type == ir->operands[1]->type);
 
343
      break;
 
344
 
 
345
   case ir_binop_cross:
 
346
      assert(ir->operands[0]->type == glsl_type::vec3_type);
 
347
      assert(ir->operands[1]->type == glsl_type::vec3_type);
 
348
      assert(ir->type == glsl_type::vec3_type);
 
349
      break;
 
350
   }
 
351
 
 
352
   return visit_continue;
 
353
}
 
354
 
 
355
ir_visitor_status
 
356
ir_validate::visit(ir_variable *ir)
 
357
{
 
358
   /* An ir_variable is the one thing that can (and will) appear multiple times
 
359
    * in an IR tree.  It is added to the hashtable so that it can be used
 
360
    * in the ir_dereference_variable handler to ensure that a variable is
 
361
    * declared before it is dereferenced.
 
362
    */
 
363
   if (ir->name)
 
364
      assert(talloc_parent(ir->name) == ir);
 
365
 
 
366
   hash_table_insert(ht, ir, ir);
 
367
   return visit_continue;
 
368
}
 
369
 
 
370
ir_visitor_status
 
371
ir_validate::visit_enter(ir_assignment *ir)
 
372
{
 
373
   const ir_dereference *const lhs = ir->lhs;
 
374
   if (lhs->type->is_scalar() || lhs->type->is_vector()) {
 
375
      if (ir->write_mask == 0) {
 
376
         printf("Assignment LHS is %s, but write mask is 0:\n",
 
377
                lhs->type->is_scalar() ? "scalar" : "vector");
 
378
         ir->print();
 
379
         abort();
 
380
      }
 
381
 
 
382
      /* Mask of fields that do not exist in the destination.  These should
 
383
       * not be written by the assignment.
 
384
       */
 
385
      const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1);
 
386
 
 
387
      if ((invalid_mask & ir->write_mask) != 0) {
 
388
         printf("Assignment write mask enables invalid components for "
 
389
                "type %s:\n", lhs->type->name);
 
390
         ir->print();
 
391
         abort();
 
392
      }
 
393
   }
 
394
 
 
395
   this->validate_ir(ir, this->data);
 
396
 
 
397
   return visit_continue;
 
398
}
 
399
 
 
400
void
 
401
ir_validate::validate_ir(ir_instruction *ir, void *data)
 
402
{
 
403
   struct hash_table *ht = (struct hash_table *) data;
 
404
 
 
405
   if (hash_table_find(ht, ir)) {
 
406
      printf("Instruction node present twice in ir tree:\n");
 
407
      ir->print();
 
408
      printf("\n");
 
409
      abort();
 
410
   }
 
411
   hash_table_insert(ht, ir, ir);
 
412
}
 
413
 
 
414
void
 
415
check_node_type(ir_instruction *ir, void *data)
 
416
{
 
417
   (void) data;
 
418
 
 
419
   if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
 
420
      printf("Instruction node with unset type\n");
 
421
      ir->print(); printf("\n");
 
422
   }
 
423
   assert(ir->type != glsl_type::error_type);
 
424
}
 
425
 
 
426
void
 
427
validate_ir_tree(exec_list *instructions)
 
428
{
 
429
   ir_validate v;
 
430
 
 
431
   v.run(instructions);
 
432
 
 
433
   foreach_iter(exec_list_iterator, iter, *instructions) {
 
434
      ir_instruction *ir = (ir_instruction *)iter.get();
 
435
 
 
436
      visit_tree(ir, check_node_type, NULL);
 
437
   }
 
438
}