Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright © 2013 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
#include "link_uniform_block_active_visitor.h"
25
#include "program.h"
26
 
27
link_uniform_block_active *
28
process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
29
{
30
   const hash_entry *const existing_block =
31
      _mesa_hash_table_search(ht, var->get_interface_type()->name);
32
 
33
   const glsl_type *const block_type = var->is_interface_instance()
34
      ? var->type : var->get_interface_type();
35
 
36
 
37
   /* If a block with this block-name has not previously been seen, add it.
38
    * If a block with this block-name has been seen, it must be identical to
39
    * the block currently being examined.
40
    */
41
   if (existing_block == NULL) {
42
      link_uniform_block_active *const b =
43
	 rzalloc(mem_ctx, struct link_uniform_block_active);
44
 
45
      b->type = block_type;
46
      b->has_instance_name = var->is_interface_instance();
47
 
48
      if (var->data.explicit_binding) {
49
         b->has_binding = true;
50
         b->binding = var->data.binding;
51
      } else {
52
         b->has_binding = false;
53
         b->binding = 0;
54
      }
55
 
56
      _mesa_hash_table_insert(ht, var->get_interface_type()->name, (void *) b);
57
      return b;
58
   } else {
59
      link_uniform_block_active *const b =
60
	 (link_uniform_block_active *) existing_block->data;
61
 
62
      if (b->type != block_type
63
	  || b->has_instance_name != var->is_interface_instance())
64
	 return NULL;
65
      else
66
	 return b;
67
   }
68
 
69
   assert(!"Should not get here.");
70
   return NULL;
71
}
72
 
73
ir_visitor_status
74
link_uniform_block_active_visitor::visit(ir_variable *var)
75
{
76
   if (!var->is_in_uniform_block())
77
      return visit_continue;
78
 
79
   const glsl_type *const block_type = var->is_interface_instance()
80
      ? var->type : var->get_interface_type();
81
 
82
   /* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec says:
83
    *
84
    *     "All members of a named uniform block declared with a shared or
85
    *     std140 layout qualifier are considered active, even if they are not
86
    *     referenced in any shader in the program. The uniform block itself is
87
    *     also considered active, even if no member of the block is
88
    *     referenced."
89
    */
90
   if (block_type->interface_packing == GLSL_INTERFACE_PACKING_PACKED)
91
      return visit_continue;
92
 
93
   /* Process the block.  Bail if there was an error.
94
    */
95
   link_uniform_block_active *const b =
96
      process_block(this->mem_ctx, this->ht, var);
97
   if (b == NULL) {
98
      linker_error(this->prog,
99
                   "uniform block `%s' has mismatching definitions",
100
                   var->get_interface_type()->name);
101
      this->success = false;
102
      return visit_stop;
103
   }
104
 
105
   assert(b->num_array_elements == 0);
106
   assert(b->array_elements == NULL);
107
   assert(b->type != NULL);
108
 
109
   return visit_continue;
110
}
111
 
112
ir_visitor_status
113
link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir)
114
{
115
   ir_dereference_variable *const d = ir->array->as_dereference_variable();
116
   ir_variable *const var = (d == NULL) ? NULL : d->var;
117
 
118
   /* If the r-value being dereferenced is not a variable (e.g., a field of a
119
    * structure) or is not a uniform block instance, continue.
120
    *
121
    * WARNING: It is not enough for the variable to be part of uniform block.
122
    * It must represent the entire block.  Arrays (or matrices) inside blocks
123
    * that lack an instance name are handled by the ir_dereference_variable
124
    * function.
125
    */
126
   if (var == NULL
127
       || !var->is_in_uniform_block()
128
       || !var->is_interface_instance())
129
      return visit_continue;
130
 
131
   /* Process the block.  Bail if there was an error.
132
    */
133
   link_uniform_block_active *const b =
134
      process_block(this->mem_ctx, this->ht, var);
135
   if (b == NULL) {
136
      linker_error(prog,
137
		   "uniform block `%s' has mismatching definitions",
138
		   var->get_interface_type()->name);
139
      this->success = false;
140
      return visit_stop;
141
   }
142
 
143
   /* Block arrays must be declared with an instance name.
144
    */
145
   assert(b->has_instance_name);
146
   assert((b->num_array_elements == 0) == (b->array_elements == NULL));
147
   assert(b->type != NULL);
148
 
149
   ir_constant *c = ir->array_index->as_constant();
150
 
151
   if (c) {
152
      /* Index is a constant, so mark just that element used, if not already */
153
      const unsigned idx = c->get_uint_component(0);
154
 
155
      unsigned i;
156
      for (i = 0; i < b->num_array_elements; i++) {
157
         if (b->array_elements[i] == idx)
158
            break;
159
      }
160
 
161
      assert(i <= b->num_array_elements);
162
 
163
      if (i == b->num_array_elements) {
164
         b->array_elements = reralloc(this->mem_ctx,
165
                                      b->array_elements,
166
                                      unsigned,
167
                                      b->num_array_elements + 1);
168
 
169
         b->array_elements[b->num_array_elements] = idx;
170
 
171
         b->num_array_elements++;
172
      }
173
   } else {
174
      /* The array index is not a constant, so mark the entire array used. */
175
      assert(b->type->is_array());
176
      if (b->num_array_elements < b->type->length) {
177
         b->num_array_elements = b->type->length;
178
         b->array_elements = reralloc(this->mem_ctx,
179
                                      b->array_elements,
180
                                      unsigned,
181
                                      b->num_array_elements);
182
 
183
         for (unsigned i = 0; i < b->num_array_elements; i++) {
184
            b->array_elements[i] = i;
185
         }
186
      }
187
   }
188
 
189
   return visit_continue_with_parent;
190
}
191
 
192
ir_visitor_status
193
link_uniform_block_active_visitor::visit(ir_dereference_variable *ir)
194
{
195
   ir_variable *var = ir->var;
196
 
197
   if (!var->is_in_uniform_block())
198
      return visit_continue;
199
 
200
   assert(!var->is_interface_instance() || !var->type->is_array());
201
 
202
   /* Process the block.  Bail if there was an error.
203
    */
204
   link_uniform_block_active *const b =
205
      process_block(this->mem_ctx, this->ht, var);
206
   if (b == NULL) {
207
      linker_error(this->prog,
208
		   "uniform block `%s' has mismatching definitions",
209
		   var->get_interface_type()->name);
210
      this->success = false;
211
      return visit_stop;
212
   }
213
 
214
   assert(b->num_array_elements == 0);
215
   assert(b->array_elements == NULL);
216
   assert(b->type != NULL);
217
 
218
   return visit_continue;
219
}