Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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
#include 
24
#include "main/compiler.h"
25
#include "main/mtypes.h"
26
#include "main/macros.h"
27
#include "util/ralloc.h"
28
#include "ir.h"
29
#include "program/hash_table.h"
30
 
31
/**
32
 * \file varyings_test.cpp
33
 *
34
 * Test various aspects of linking shader stage inputs and outputs.
35
 */
36
 
37
namespace linker {
38
bool
39
populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
40
                             hash_table *consumer_inputs,
41
                             hash_table *consumer_interface_inputs,
42
                             ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX]);
43
 
44
ir_variable *
45
get_matching_input(void *mem_ctx,
46
                   const ir_variable *output_var,
47
                   hash_table *consumer_inputs,
48
                   hash_table *consumer_interface_inputs,
49
                   ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX]);
50
}
51
 
52
class link_varyings : public ::testing::Test {
53
public:
54
   link_varyings();
55
 
56
   virtual void SetUp();
57
   virtual void TearDown();
58
 
59
   char *interface_field_name(const glsl_type *iface, unsigned field = 0)
60
   {
61
      return ralloc_asprintf(mem_ctx,
62
                             "%s.%s",
63
                             iface->name,
64
                             iface->fields.structure[field].name);
65
   }
66
 
67
   void *mem_ctx;
68
   exec_list ir;
69
   hash_table *consumer_inputs;
70
   hash_table *consumer_interface_inputs;
71
 
72
   const glsl_type *simple_interface;
73
   ir_variable *junk[VARYING_SLOT_MAX];
74
};
75
 
76
link_varyings::link_varyings()
77
{
78
   static const glsl_struct_field f[] = {
79
      {
80
         glsl_type::vec(4),
81
         "v",
82
         false,
83
         0,
84
         0,
85
         0,
86
 
87
      }
88
   };
89
 
90
   this->simple_interface =
91
      glsl_type::get_interface_instance(f,
92
                                        ARRAY_SIZE(f),
93
                                        GLSL_INTERFACE_PACKING_STD140,
94
                                        "simple_interface");
95
}
96
 
97
void
98
link_varyings::SetUp()
99
{
100
   this->mem_ctx = ralloc_context(NULL);
101
   this->ir.make_empty();
102
 
103
   this->consumer_inputs
104
      = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
105
 
106
   this->consumer_interface_inputs
107
      = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
108
}
109
 
110
void
111
link_varyings::TearDown()
112
{
113
   ralloc_free(this->mem_ctx);
114
   this->mem_ctx = NULL;
115
 
116
   hash_table_dtor(this->consumer_inputs);
117
   this->consumer_inputs = NULL;
118
   hash_table_dtor(this->consumer_interface_inputs);
119
   this->consumer_interface_inputs = NULL;
120
}
121
 
122
/**
123
 * Hash table callback function that counts the elements in the table
124
 *
125
 * \sa num_elements
126
 */
127
static void
128
ht_count_callback(const void *, void *, void *closure)
129
{
130
   unsigned int *counter = (unsigned int *) closure;
131
 
132
   (*counter)++;
133
}
134
 
135
/**
136
 * Helper function to count the number of elements in a hash table.
137
 */
138
static unsigned
139
num_elements(hash_table *ht)
140
{
141
   unsigned int counter = 0;
142
 
143
   hash_table_call_foreach(ht, ht_count_callback, (void *) &counter);
144
 
145
   return counter;
146
}
147
 
148
/**
149
 * Helper function to determine whether a hash table is empty.
150
 */
151
static bool
152
is_empty(hash_table *ht)
153
{
154
   return num_elements(ht) == 0;
155
}
156
 
157
TEST_F(link_varyings, single_simple_input)
158
{
159
   ir_variable *const v =
160
      new(mem_ctx) ir_variable(glsl_type::vec(4),
161
                               "a",
162
                               ir_var_shader_in);
163
 
164
 
165
   ir.push_tail(v);
166
 
167
   ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
168
                                                    &ir,
169
                                                    consumer_inputs,
170
                                                    consumer_interface_inputs,
171
                                                    junk));
172
 
173
   EXPECT_EQ((void *) v, hash_table_find(consumer_inputs, "a"));
174
   EXPECT_EQ(1u, num_elements(consumer_inputs));
175
   EXPECT_TRUE(is_empty(consumer_interface_inputs));
176
}
177
 
178
TEST_F(link_varyings, gl_ClipDistance)
179
{
180
   const glsl_type *const array_8_of_float =
181
      glsl_type::get_array_instance(glsl_type::vec(1), 8);
182
 
183
   ir_variable *const clipdistance =
184
      new(mem_ctx) ir_variable(array_8_of_float,
185
                               "gl_ClipDistance",
186
                               ir_var_shader_in);
187
 
188
   clipdistance->data.explicit_location = true;
189
   clipdistance->data.location = VARYING_SLOT_CLIP_DIST0;
190
   clipdistance->data.explicit_index = 0;
191
 
192
   ir.push_tail(clipdistance);
193
 
194
   ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
195
                                                    &ir,
196
                                                    consumer_inputs,
197
                                                    consumer_interface_inputs,
198
                                                    junk));
199
 
200
   EXPECT_EQ(clipdistance, junk[VARYING_SLOT_CLIP_DIST0]);
201
   EXPECT_TRUE(is_empty(consumer_inputs));
202
   EXPECT_TRUE(is_empty(consumer_interface_inputs));
203
}
204
 
205
TEST_F(link_varyings, single_interface_input)
206
{
207
   ir_variable *const v =
208
      new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
209
                               simple_interface->fields.structure[0].name,
210
                               ir_var_shader_in);
211
 
212
   v->init_interface_type(simple_interface);
213
 
214
   ir.push_tail(v);
215
 
216
   ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
217
                                                    &ir,
218
                                                    consumer_inputs,
219
                                                    consumer_interface_inputs,
220
                                                    junk));
221
   char *const full_name = interface_field_name(simple_interface);
222
 
223
   EXPECT_EQ((void *) v, hash_table_find(consumer_interface_inputs, full_name));
224
   EXPECT_EQ(1u, num_elements(consumer_interface_inputs));
225
   EXPECT_TRUE(is_empty(consumer_inputs));
226
}
227
 
228
TEST_F(link_varyings, one_interface_and_one_simple_input)
229
{
230
   ir_variable *const v =
231
      new(mem_ctx) ir_variable(glsl_type::vec(4),
232
                               "a",
233
                               ir_var_shader_in);
234
 
235
 
236
   ir.push_tail(v);
237
 
238
   ir_variable *const iface =
239
      new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
240
                               simple_interface->fields.structure[0].name,
241
                               ir_var_shader_in);
242
 
243
   iface->init_interface_type(simple_interface);
244
 
245
   ir.push_tail(iface);
246
 
247
   ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
248
                                                    &ir,
249
                                                    consumer_inputs,
250
                                                    consumer_interface_inputs,
251
                                                    junk));
252
 
253
   char *const iface_field_name = interface_field_name(simple_interface);
254
 
255
   EXPECT_EQ((void *) iface, hash_table_find(consumer_interface_inputs,
256
                                             iface_field_name));
257
   EXPECT_EQ(1u, num_elements(consumer_interface_inputs));
258
 
259
   EXPECT_EQ((void *) v, hash_table_find(consumer_inputs, "a"));
260
   EXPECT_EQ(1u, num_elements(consumer_inputs));
261
}
262
 
263
TEST_F(link_varyings, invalid_interface_input)
264
{
265
   ir_variable *const v =
266
      new(mem_ctx) ir_variable(simple_interface,
267
                               "named_interface",
268
                               ir_var_shader_in);
269
 
270
   ASSERT_EQ(simple_interface, v->get_interface_type());
271
 
272
   ir.push_tail(v);
273
 
274
   EXPECT_FALSE(linker::populate_consumer_input_sets(mem_ctx,
275
                                                    &ir,
276
                                                    consumer_inputs,
277
                                                     consumer_interface_inputs,
278
                                                     junk));
279
}
280
 
281
TEST_F(link_varyings, interface_field_doesnt_match_noninterface)
282
{
283
   char *const iface_field_name = interface_field_name(simple_interface);
284
 
285
   /* The input shader has a single input variable name "a.v"
286
    */
287
   ir_variable *const in_v =
288
      new(mem_ctx) ir_variable(glsl_type::vec(4),
289
                               iface_field_name,
290
                               ir_var_shader_in);
291
 
292
   ir.push_tail(in_v);
293
 
294
   ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
295
                                                    &ir,
296
                                                    consumer_inputs,
297
                                                    consumer_interface_inputs,
298
                                                    junk));
299
 
300
   /* Create an output variable, "v", that is part of an interface block named
301
    * "a".  They should not match.
302
    */
303
   ir_variable *const out_v =
304
      new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
305
                               simple_interface->fields.structure[0].name,
306
                               ir_var_shader_in);
307
 
308
   out_v->init_interface_type(simple_interface);
309
 
310
   ir_variable *const match =
311
      linker::get_matching_input(mem_ctx,
312
                                 out_v,
313
                                 consumer_inputs,
314
                                 consumer_interface_inputs,
315
                                 junk);
316
 
317
   EXPECT_EQ(NULL, match);
318
}
319
 
320
TEST_F(link_varyings, interface_field_doesnt_match_noninterface_vice_versa)
321
{
322
   char *const iface_field_name = interface_field_name(simple_interface);
323
 
324
   /* In input shader has a single variable, "v", that is part of an interface
325
    * block named "a".
326
    */
327
   ir_variable *const in_v =
328
      new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
329
                               simple_interface->fields.structure[0].name,
330
                               ir_var_shader_in);
331
 
332
   in_v->init_interface_type(simple_interface);
333
 
334
   ir.push_tail(in_v);
335
 
336
   ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
337
                                                    &ir,
338
                                                    consumer_inputs,
339
                                                    consumer_interface_inputs,
340
                                                    junk));
341
 
342
   /* Create an output variable "a.v".  They should not match.
343
    */
344
   ir_variable *const out_v =
345
      new(mem_ctx) ir_variable(glsl_type::vec(4),
346
                               iface_field_name,
347
                               ir_var_shader_out);
348
 
349
   ir_variable *const match =
350
      linker::get_matching_input(mem_ctx,
351
                                 out_v,
352
                                 consumer_inputs,
353
                                 consumer_interface_inputs,
354
                                 junk);
355
 
356
   EXPECT_EQ(NULL, match);
357
}