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
/**
25
 * \file link_interface_blocks.cpp
26
 * Linker support for GLSL's interface blocks.
27
 */
28
 
29
#include "ir.h"
30
#include "glsl_symbol_table.h"
31
#include "linker.h"
32
#include "main/macros.h"
33
#include "program/hash_table.h"
34
 
35
 
36
namespace {
37
 
38
/**
39
 * Information about a single interface block definition that we need to keep
40
 * track of in order to check linkage rules.
41
 *
42
 * Note: this class is expected to be short lived, so it doesn't make copies
43
 * of the strings it references; it simply borrows the pointers from the
44
 * ir_variable class.
45
 */
46
struct interface_block_definition
47
{
48
   /**
49
    * Extract an interface block definition from an ir_variable that
50
    * represents either the interface instance (for named interfaces), or a
51
    * member of the interface (for unnamed interfaces).
52
    */
53
   explicit interface_block_definition(ir_variable *var)
54
      : var(var),
55
        type(var->get_interface_type()),
56
        instance_name(NULL)
57
   {
58
      if (var->is_interface_instance()) {
59
         instance_name = var->name;
60
      }
61
      explicitly_declared = (var->data.how_declared != ir_var_declared_implicitly);
62
   }
63
   /**
64
    * Interface block ir_variable
65
    */
66
   ir_variable *var;
67
 
68
   /**
69
    * Interface block type
70
    */
71
   const glsl_type *type;
72
 
73
   /**
74
    * For a named interface block, the instance name.  Otherwise NULL.
75
    */
76
   const char *instance_name;
77
 
78
   /**
79
    * True if this interface block was explicitly declared in the shader;
80
    * false if it was an implicitly declared built-in interface block.
81
    */
82
   bool explicitly_declared;
83
};
84
 
85
 
86
/**
87
 * Check if two interfaces match, according to intrastage interface matching
88
 * rules.  If they do, and the first interface uses an unsized array, it will
89
 * be updated to reflect the array size declared in the second interface.
90
 */
91
bool
92
intrastage_match(interface_block_definition *a,
93
                 const interface_block_definition *b,
94
                 ir_variable_mode mode,
95
                 struct gl_shader_program *prog)
96
{
97
   /* Types must match. */
98
   if (a->type != b->type) {
99
      /* Exception: if both the interface blocks are implicitly declared,
100
       * don't force their types to match.  They might mismatch due to the two
101
       * shaders using different GLSL versions, and that's ok.
102
       */
103
      if (a->explicitly_declared || b->explicitly_declared)
104
         return false;
105
   }
106
 
107
   /* Presence/absence of interface names must match. */
108
   if ((a->instance_name == NULL) != (b->instance_name == NULL))
109
      return false;
110
 
111
   /* For uniforms, instance names need not match.  For shader ins/outs,
112
    * it's not clear from the spec whether they need to match, but
113
    * Mesa's implementation relies on them matching.
114
    */
115
   if (a->instance_name != NULL && mode != ir_var_uniform &&
116
       strcmp(a->instance_name, b->instance_name) != 0) {
117
      return false;
118
   }
119
 
120
   /* If a block is an array then it must match across the shader.
121
    * Unsized arrays are also processed and matched agaist sized arrays.
122
    */
123
   if (b->var->type != a->var->type &&
124
       (b->instance_name != NULL || a->instance_name != NULL) &&
125
       !validate_intrastage_arrays(prog, b->var, a->var))
126
      return false;
127
 
128
   return true;
129
}
130
 
131
 
132
/**
133
 * Check if two interfaces match, according to interstage (in/out) interface
134
 * matching rules.
135
 *
136
 * If \c extra_array_level is true, then vertex-to-geometry shader matching
137
 * rules are enforced (i.e. a successful match requires the consumer interface
138
 * to be an array and the producer interface to be a non-array).
139
 */
140
bool
141
interstage_match(const interface_block_definition *producer,
142
                 const interface_block_definition *consumer,
143
                 bool extra_array_level)
144
{
145
   /* Unsized arrays should not occur during interstage linking.  They
146
    * should have all been assigned a size by link_intrastage_shaders.
147
    */
148
   assert(!consumer->var->type->is_unsized_array());
149
   assert(!producer->var->type->is_unsized_array());
150
 
151
   /* Types must match. */
152
   if (consumer->type != producer->type) {
153
      /* Exception: if both the interface blocks are implicitly declared,
154
       * don't force their types to match.  They might mismatch due to the two
155
       * shaders using different GLSL versions, and that's ok.
156
       */
157
      if (consumer->explicitly_declared || producer->explicitly_declared)
158
         return false;
159
   }
160
 
161
   /* Ignore outermost array if geom shader */
162
   const glsl_type *consumer_instance_type;
163
   if (extra_array_level) {
164
      consumer_instance_type = consumer->var->type->fields.array;
165
   } else {
166
      consumer_instance_type = consumer->var->type;
167
   }
168
 
169
   /* If a block is an array then it must match across shaders.
170
    * Since unsized arrays have been ruled out, we can check this by just
171
    * making sure the types are equal.
172
    */
173
   if ((consumer->instance_name != NULL &&
174
        consumer_instance_type->is_array()) ||
175
       (producer->instance_name != NULL &&
176
        producer->var->type->is_array())) {
177
      if (consumer_instance_type != producer->var->type)
178
         return false;
179
   }
180
 
181
   return true;
182
}
183
 
184
 
185
/**
186
 * This class keeps track of a mapping from an interface block name to the
187
 * necessary information about that interface block to determine whether to
188
 * generate a link error.
189
 *
190
 * Note: this class is expected to be short lived, so it doesn't make copies
191
 * of the strings it references; it simply borrows the pointers from the
192
 * ir_variable class.
193
 */
194
class interface_block_definitions
195
{
196
public:
197
   interface_block_definitions()
198
      : mem_ctx(ralloc_context(NULL)),
199
        ht(hash_table_ctor(0, hash_table_string_hash,
200
                           hash_table_string_compare))
201
   {
202
   }
203
 
204
   ~interface_block_definitions()
205
   {
206
      hash_table_dtor(ht);
207
      ralloc_free(mem_ctx);
208
   }
209
 
210
   /**
211
    * Lookup the interface definition having the given block name.  Return
212
    * NULL if none is found.
213
    */
214
   interface_block_definition *lookup(const char *block_name)
215
   {
216
      return (interface_block_definition *) hash_table_find(ht, block_name);
217
   }
218
 
219
   /**
220
    * Add a new interface definition.
221
    */
222
   void store(const interface_block_definition &def)
223
   {
224
      interface_block_definition *hash_entry =
225
         rzalloc(mem_ctx, interface_block_definition);
226
      *hash_entry = def;
227
      hash_table_insert(ht, hash_entry, def.type->name);
228
   }
229
 
230
private:
231
   /**
232
    * Ralloc context for data structures allocated by this class.
233
    */
234
   void *mem_ctx;
235
 
236
   /**
237
    * Hash table mapping interface block name to an \c
238
    * interface_block_definition struct.  interface_block_definition structs
239
    * are allocated using \c mem_ctx.
240
    */
241
   hash_table *ht;
242
};
243
 
244
 
245
}; /* anonymous namespace */
246
 
247
 
248
void
249
validate_intrastage_interface_blocks(struct gl_shader_program *prog,
250
                                     const gl_shader **shader_list,
251
                                     unsigned num_shaders)
252
{
253
   interface_block_definitions in_interfaces;
254
   interface_block_definitions out_interfaces;
255
   interface_block_definitions uniform_interfaces;
256
 
257
   for (unsigned int i = 0; i < num_shaders; i++) {
258
      if (shader_list[i] == NULL)
259
         continue;
260
 
261
      foreach_in_list(ir_instruction, node, shader_list[i]->ir) {
262
         ir_variable *var = node->as_variable();
263
         if (!var)
264
            continue;
265
 
266
         const glsl_type *iface_type = var->get_interface_type();
267
 
268
         if (iface_type == NULL)
269
            continue;
270
 
271
         interface_block_definitions *definitions;
272
         switch (var->data.mode) {
273
         case ir_var_shader_in:
274
            definitions = &in_interfaces;
275
            break;
276
         case ir_var_shader_out:
277
            definitions = &out_interfaces;
278
            break;
279
         case ir_var_uniform:
280
            definitions = &uniform_interfaces;
281
            break;
282
         default:
283
            /* Only in, out, and uniform interfaces are legal, so we should
284
             * never get here.
285
             */
286
            assert(!"illegal interface type");
287
            continue;
288
         }
289
 
290
         const interface_block_definition def(var);
291
         interface_block_definition *prev_def =
292
            definitions->lookup(iface_type->name);
293
 
294
         if (prev_def == NULL) {
295
            /* This is the first time we've seen the interface, so save
296
             * it into the appropriate data structure.
297
             */
298
            definitions->store(def);
299
         } else if (!intrastage_match(prev_def, &def,
300
                                      (ir_variable_mode) var->data.mode,
301
                                      prog)) {
302
            linker_error(prog, "definitions of interface block `%s' do not"
303
                         " match\n", iface_type->name);
304
            return;
305
         }
306
      }
307
   }
308
}
309
 
310
void
311
validate_interstage_inout_blocks(struct gl_shader_program *prog,
312
                                 const gl_shader *producer,
313
                                 const gl_shader *consumer)
314
{
315
   interface_block_definitions definitions;
316
   const bool extra_array_level = consumer->Stage == MESA_SHADER_GEOMETRY;
317
 
318
   /* Add input interfaces from the consumer to the symbol table. */
319
   foreach_in_list(ir_instruction, node, consumer->ir) {
320
      ir_variable *var = node->as_variable();
321
      if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_in)
322
         continue;
323
 
324
      definitions.store(interface_block_definition(var));
325
   }
326
 
327
   /* Verify that the producer's output interfaces match. */
328
   foreach_in_list(ir_instruction, node, producer->ir) {
329
      ir_variable *var = node->as_variable();
330
      if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_out)
331
         continue;
332
 
333
      interface_block_definition *consumer_def =
334
         definitions.lookup(var->get_interface_type()->name);
335
 
336
      /* The consumer doesn't use this output block.  Ignore it. */
337
      if (consumer_def == NULL)
338
         continue;
339
 
340
      const interface_block_definition producer_def(var);
341
 
342
      if (!interstage_match(&producer_def, consumer_def, extra_array_level)) {
343
         linker_error(prog, "definitions of interface block `%s' do not "
344
                      "match\n", var->get_interface_type()->name);
345
         return;
346
      }
347
   }
348
}
349
 
350
 
351
void
352
validate_interstage_uniform_blocks(struct gl_shader_program *prog,
353
                                   gl_shader **stages, int num_stages)
354
{
355
   interface_block_definitions definitions;
356
 
357
   for (int i = 0; i < num_stages; i++) {
358
      if (stages[i] == NULL)
359
         continue;
360
 
361
      const gl_shader *stage = stages[i];
362
      foreach_in_list(ir_instruction, node, stage->ir) {
363
         ir_variable *var = node->as_variable();
364
         if (!var || !var->get_interface_type() || var->data.mode != ir_var_uniform)
365
            continue;
366
 
367
         interface_block_definition *old_def =
368
            definitions.lookup(var->get_interface_type()->name);
369
         const interface_block_definition new_def(var);
370
         if (old_def == NULL) {
371
            definitions.store(new_def);
372
         } else {
373
            /* Interstage uniform matching rules are the same as intrastage
374
             * uniform matchin rules (for uniforms, it is as though all
375
             * shaders are in the same shader stage).
376
             */
377
            if (!intrastage_match(old_def, &new_def, ir_var_uniform, prog)) {
378
               linker_error(prog, "definitions of interface block `%s' do not "
379
                            "match\n", var->get_interface_type()->name);
380
               return;
381
            }
382
         }
383
      }
384
   }
385
}