2 * Copyright © 2013 Intel Corporation
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:
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
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.
23 #include <gtest/gtest.h>
24 #include "main/compiler.h"
25 #include "main/mtypes.h"
26 #include "main/macros.h"
27 #include "util/ralloc.h"
29 #include "program/hash_table.h"
32 * \file varyings_test.cpp
34 * Test various aspects of linking shader stage inputs and outputs.
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
]);
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
]);
52 class link_varyings
: public ::testing::Test
{
57 virtual void TearDown();
59 char *interface_field_name(const glsl_type
*iface
, unsigned field
= 0)
61 return ralloc_asprintf(mem_ctx
,
64 iface
->fields
.structure
[field
].name
);
69 hash_table
*consumer_inputs
;
70 hash_table
*consumer_interface_inputs
;
72 const glsl_type
*simple_interface
;
73 ir_variable
*junk
[VARYING_SLOT_TESS_MAX
];
76 link_varyings::link_varyings()
78 static const glsl_struct_field f
[] = {
79 glsl_struct_field(glsl_type::vec(4), "v")
82 this->simple_interface
=
83 glsl_type::get_interface_instance(f
,
85 GLSL_INTERFACE_PACKING_STD140
,
90 link_varyings::SetUp()
92 this->mem_ctx
= ralloc_context(NULL
);
93 this->ir
.make_empty();
96 = hash_table_ctor(0, hash_table_string_hash
, hash_table_string_compare
);
98 this->consumer_interface_inputs
99 = hash_table_ctor(0, hash_table_string_hash
, hash_table_string_compare
);
103 link_varyings::TearDown()
105 ralloc_free(this->mem_ctx
);
106 this->mem_ctx
= NULL
;
108 hash_table_dtor(this->consumer_inputs
);
109 this->consumer_inputs
= NULL
;
110 hash_table_dtor(this->consumer_interface_inputs
);
111 this->consumer_interface_inputs
= NULL
;
115 * Hash table callback function that counts the elements in the table
120 ht_count_callback(const void *, void *, void *closure
)
122 unsigned int *counter
= (unsigned int *) closure
;
128 * Helper function to count the number of elements in a hash table.
131 num_elements(hash_table
*ht
)
133 unsigned int counter
= 0;
135 hash_table_call_foreach(ht
, ht_count_callback
, (void *) &counter
);
141 * Helper function to determine whether a hash table is empty.
144 is_empty(hash_table
*ht
)
146 return num_elements(ht
) == 0;
149 TEST_F(link_varyings
, single_simple_input
)
151 ir_variable
*const v
=
152 new(mem_ctx
) ir_variable(glsl_type::vec(4),
159 linker::populate_consumer_input_sets(mem_ctx
,
162 consumer_interface_inputs
,
165 EXPECT_EQ((void *) v
, hash_table_find(consumer_inputs
, "a"));
166 EXPECT_EQ(1u, num_elements(consumer_inputs
));
167 EXPECT_TRUE(is_empty(consumer_interface_inputs
));
170 TEST_F(link_varyings
, gl_ClipDistance
)
172 const glsl_type
*const array_8_of_float
=
173 glsl_type::get_array_instance(glsl_type::vec(1), 8);
175 ir_variable
*const clipdistance
=
176 new(mem_ctx
) ir_variable(array_8_of_float
,
180 clipdistance
->data
.explicit_location
= true;
181 clipdistance
->data
.location
= VARYING_SLOT_CLIP_DIST0
;
182 clipdistance
->data
.explicit_index
= 0;
184 ir
.push_tail(clipdistance
);
186 linker::populate_consumer_input_sets(mem_ctx
,
189 consumer_interface_inputs
,
192 EXPECT_EQ(clipdistance
, junk
[VARYING_SLOT_CLIP_DIST0
]);
193 EXPECT_TRUE(is_empty(consumer_inputs
));
194 EXPECT_TRUE(is_empty(consumer_interface_inputs
));
197 TEST_F(link_varyings
, single_interface_input
)
199 ir_variable
*const v
=
200 new(mem_ctx
) ir_variable(simple_interface
->fields
.structure
[0].type
,
201 simple_interface
->fields
.structure
[0].name
,
204 v
->init_interface_type(simple_interface
);
208 linker::populate_consumer_input_sets(mem_ctx
,
211 consumer_interface_inputs
,
213 char *const full_name
= interface_field_name(simple_interface
);
215 EXPECT_EQ((void *) v
, hash_table_find(consumer_interface_inputs
, full_name
));
216 EXPECT_EQ(1u, num_elements(consumer_interface_inputs
));
217 EXPECT_TRUE(is_empty(consumer_inputs
));
220 TEST_F(link_varyings
, one_interface_and_one_simple_input
)
222 ir_variable
*const v
=
223 new(mem_ctx
) ir_variable(glsl_type::vec(4),
230 ir_variable
*const iface
=
231 new(mem_ctx
) ir_variable(simple_interface
->fields
.structure
[0].type
,
232 simple_interface
->fields
.structure
[0].name
,
235 iface
->init_interface_type(simple_interface
);
239 linker::populate_consumer_input_sets(mem_ctx
,
242 consumer_interface_inputs
,
245 char *const iface_field_name
= interface_field_name(simple_interface
);
247 EXPECT_EQ((void *) iface
, hash_table_find(consumer_interface_inputs
,
249 EXPECT_EQ(1u, num_elements(consumer_interface_inputs
));
251 EXPECT_EQ((void *) v
, hash_table_find(consumer_inputs
, "a"));
252 EXPECT_EQ(1u, num_elements(consumer_inputs
));
255 TEST_F(link_varyings
, interface_field_doesnt_match_noninterface
)
257 char *const iface_field_name
= interface_field_name(simple_interface
);
259 /* The input shader has a single input variable name "a.v"
261 ir_variable
*const in_v
=
262 new(mem_ctx
) ir_variable(glsl_type::vec(4),
268 linker::populate_consumer_input_sets(mem_ctx
,
271 consumer_interface_inputs
,
274 /* Create an output variable, "v", that is part of an interface block named
275 * "a". They should not match.
277 ir_variable
*const out_v
=
278 new(mem_ctx
) ir_variable(simple_interface
->fields
.structure
[0].type
,
279 simple_interface
->fields
.structure
[0].name
,
282 out_v
->init_interface_type(simple_interface
);
284 ir_variable
*const match
=
285 linker::get_matching_input(mem_ctx
,
288 consumer_interface_inputs
,
291 EXPECT_EQ(NULL
, match
);
294 TEST_F(link_varyings
, interface_field_doesnt_match_noninterface_vice_versa
)
296 char *const iface_field_name
= interface_field_name(simple_interface
);
298 /* In input shader has a single variable, "v", that is part of an interface
301 ir_variable
*const in_v
=
302 new(mem_ctx
) ir_variable(simple_interface
->fields
.structure
[0].type
,
303 simple_interface
->fields
.structure
[0].name
,
306 in_v
->init_interface_type(simple_interface
);
310 linker::populate_consumer_input_sets(mem_ctx
,
313 consumer_interface_inputs
,
316 /* Create an output variable "a.v". They should not match.
318 ir_variable
*const out_v
=
319 new(mem_ctx
) ir_variable(glsl_type::vec(4),
323 ir_variable
*const match
=
324 linker::get_matching_input(mem_ctx
,
327 consumer_interface_inputs
,
330 EXPECT_EQ(NULL
, match
);