1 /*
2  * Copyright © 2016 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 DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 /**
25  * \file getactiveattrib.c
26  * Verify that glGetActiveAttrib and GL_ACTIVE_ATTRIBUTES return the expected
27  * values for the new tokens defined at ARB_vertex_attrib_64bit specification.
28  *
29  * This is based on tests/general/getactiveattrib.c
30  */
31 
32 #include "piglit-util-gl.h"
33 
34 PIGLIT_GL_TEST_CONFIG_BEGIN
35 	config.supports_gl_compat_version = 32;
36 	config.supports_gl_core_version = 32;
37 
38 	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
39 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
40 PIGLIT_GL_TEST_CONFIG_END
41 
42 struct attribute {
43 	/** Name of the attribute. */
44 	const char *name;
45 
46 	/** Expected GLSL type of the attribute. */
47 	GLenum type;
48 };
49 
50 struct test {
51 	const char *code;
52 
53 	/**
54 	 * List of attributes to be checked
55 	 *
56 	 * \note
57 	 * The list is terminated by an attribute with a \c NULL \c name
58 	 * pointer.
59 	 */
60 	struct attribute attributes[16];
61 };
62 
63 static const struct test vertex_attrib_64bit_tests[] = {
64 	/* Try all the possible types for vertex shader inputs added
65 	 * at the spec. They could be added as 13 attributes on the
66 	 * same vertex shader, but we would need to get them all
67 	 * active. It is easier to read this way.
68 	 */
69 	{
70 		"#version 150\n"
71 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
72 		"#extension GL_ARB_gpu_shader_fp64: require\n"
73 		"in double _double;\n"
74 		"void main() { gl_Position = vec4(float(_double)); }\n",
75 		{
76 			{ "_double",	GL_DOUBLE },
77 			{ NULL, }
78 		}
79 	},
80 	{
81 		"#version 150\n"
82 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
83 		"#extension GL_ARB_gpu_shader_fp64: require\n"
84 		"in dvec2 _dvec2;\n"
85 		"void main() { gl_Position = vec4(float(_dvec2.x)); }\n",
86 		{
87 			{ "_dvec2",	GL_DOUBLE_VEC2 },
88 			{ NULL, }
89 		}
90 	},
91 	{
92 		"#version 150\n"
93 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
94 		"#extension GL_ARB_gpu_shader_fp64: require\n"
95 		"in dvec3 _dvec3;\n"
96 		"void main() { gl_Position = vec4(float(_dvec3.x)); }\n",
97 		{
98 			{ "_dvec3",	GL_DOUBLE_VEC3 },
99 			{ NULL, }
100 		}
101 	},
102 	{
103 		"#version 150\n"
104 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
105 		"#extension GL_ARB_gpu_shader_fp64: require\n"
106 		"in dvec4 _dvec4;\n"
107 		"void main() { gl_Position = vec4(float(_dvec4.x)); }\n",
108 		{
109 			{ "_dvec4",	GL_DOUBLE_VEC4 },
110 			{ NULL, }
111 		}
112 	},
113 	{
114 		"#version 150\n"
115 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
116 		"#extension GL_ARB_gpu_shader_fp64: require\n"
117 		"in dmat2 _dmat2;\n"
118 		"void main() { gl_Position = vec4(float(_dmat2[0][0])); }\n",
119 		{
120 			{ "_dmat2",	GL_DOUBLE_MAT2 },
121 			{ NULL, }
122 		}
123 	},
124 	{
125 		"#version 150\n"
126 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
127 		"#extension GL_ARB_gpu_shader_fp64: require\n"
128 		"in dmat3 _dmat3;\n"
129 		"void main() { gl_Position = vec4(float(_dmat3[0][0])); }\n",
130 		{
131 			{ "_dmat3",	GL_DOUBLE_MAT3 },
132 			{ NULL, }
133 		}
134 	},
135 	{
136 		"#version 150\n"
137 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
138 		"#extension GL_ARB_gpu_shader_fp64: require\n"
139 		"in dmat4 _dmat4;\n"
140 		"void main() { gl_Position = vec4(float(_dmat4[0][0])); }\n",
141 		{
142 			{ "_dmat4",	GL_DOUBLE_MAT4 },
143 			{ NULL, }
144 		}
145 	},
146 	{
147 		"#version 150\n"
148 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
149 		"#extension GL_ARB_gpu_shader_fp64: require\n"
150 		"in dmat2x3 _dmat2x3;\n"
151 		"void main() { gl_Position = vec4(float(_dmat2x3[0][0])); }\n",
152 		{
153 			{ "_dmat2x3",	GL_DOUBLE_MAT2x3 },
154 			{ NULL, }
155 		}
156 	},
157 	{
158 		"#version 150\n"
159 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
160 		"#extension GL_ARB_gpu_shader_fp64: require\n"
161 		"in dmat2x4 _dmat2x4;\n"
162 		"void main() { gl_Position = vec4(float(_dmat2x4[0][0])); }\n",
163 		{
164 			{ "_dmat2x4",	GL_DOUBLE_MAT2x4 },
165 			{ NULL, }
166 		}
167 	},
168 	{
169 		"#version 150\n"
170 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
171 		"#extension GL_ARB_gpu_shader_fp64: require\n"
172 		"in dmat3x2 _dmat3x2;\n"
173 		"void main() { gl_Position = vec4(float(_dmat3x2[0][0])); }\n",
174 		{
175 			{ "_dmat3x2",	GL_DOUBLE_MAT3x2 },
176 			{ NULL, }
177 		}
178 	},
179 	{
180 		"#version 150\n"
181 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
182 		"#extension GL_ARB_gpu_shader_fp64: require\n"
183 		"in dmat3x4 _dmat3x4;\n"
184 		"void main() { gl_Position = vec4(float(_dmat3x4[0][0])); }\n",
185 		{
186 			{ "_dmat3x4",	GL_DOUBLE_MAT3x4 },
187 			{ NULL, }
188 		}
189 	},
190 	{
191 		"#version 150\n"
192 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
193 		"#extension GL_ARB_gpu_shader_fp64: require\n"
194 		"in dmat4x2 _dmat4x2;\n"
195 		"void main() { gl_Position = vec4(float(_dmat4x2[0][0])); }\n",
196 		{
197 			{ "_dmat4x2",	GL_DOUBLE_MAT4x2 },
198 			{ NULL, }
199 		}
200 	},
201 	{
202 		"#version 150\n"
203 		"#extension GL_ARB_vertex_attrib_64bit: require\n"
204 		"#extension GL_ARB_gpu_shader_fp64: require\n"
205 		"in dmat4x3 _dmat4x3;\n"
206 		"void main() { gl_Position = vec4(float(_dmat4x3[0][0])); }\n",
207 		{
208 			{ "_dmat4x3",	GL_DOUBLE_MAT4x3 },
209 			{ NULL, }
210 		}
211 	},
212 };
213 
214 enum piglit_result
piglit_display(void)215 piglit_display(void)
216 {
217 	return PIGLIT_FAIL;
218 }
219 
220 int
find_attrib(const struct attribute * attribs,const char * name)221 find_attrib(const struct attribute *attribs, const char *name)
222 {
223 	unsigned i;
224 
225 	for (i = 0; attribs[i].name != NULL; i++) {
226 		if (strcmp(attribs[i].name, name) == 0)
227 			return (int) i;
228 	}
229 
230 	return -1;
231 }
232 
233 #define DUMP_SHADER(code)						\
234 	do {								\
235 		if (!shader_dumped) {					\
236 			fprintf(stderr, "\nFailing shader:\n%s\n\n",	\
237 				code);					\
238 			shader_dumped = true;				\
239 		}							\
240 	} while (false)
241 
242 bool
do_test(const struct test * tests,unsigned num_tests)243 do_test(const struct test *tests, unsigned num_tests)
244 {
245 	bool pass = true;
246 	unsigned i;
247 
248 	for (i = 0; i < num_tests; i++) {
249 		GLint prog = piglit_build_simple_program(tests[i].code, 0);
250 		GLint num_attr;
251 		unsigned visited_count[64];
252 		unsigned j;
253 		bool shader_dumped = false;
254 
255 		memset(visited_count, 0, sizeof(visited_count));
256 
257 		/* From page 93 (page 109 of the PDF) says:
258 		 *
259 		 *     "An attribute variable (either conventional or generic)
260 		 *      is considered active if it is determined by the
261 		 *      compiler and linker that the attribute may be accessed
262 		 *      when the shader is executed. Attribute variables that
263 		 *      are declared in a vertex shader but never used will not
264 		 *      count against the limit. In cases where the compiler
265 		 *      and linker cannot make a conclusive determination, an
266 		 *      attribute will be considered active."
267 		 *
268 		 * Compare the set of active attributes against the list of
269 		 * expected active attributes.
270 		 */
271 		glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &num_attr);
272 
273 		for (j = 0; j < num_attr; j++) {
274 			const struct attribute *attr;
275 			char name_buf[256];
276 			int attr_idx;
277 			GLsizei name_len;
278 			GLint size;
279 			GLenum type;
280 
281 			glGetActiveAttrib(prog, j,
282 					  sizeof(name_buf),
283 					  &name_len,
284 					  &size,
285 					  &type,
286 					  name_buf);
287 			attr_idx = find_attrib(tests[i].attributes, name_buf);
288 
289 			/* If the named attribute is not in the list for the
290 			 * test, then it must not be active.
291 			 */
292 			if (attr_idx < 0) {
293 				DUMP_SHADER(tests[i].code);
294 				fprintf(stderr,
295 					"Attribute `%s' should not be active"
296 					" but is.\n", name_buf);
297 				pass = false;
298 				continue;
299 			}
300 
301 			attr = &tests[i].attributes[attr_idx];
302 			if (visited_count[attr_idx] != 0) {
303 				DUMP_SHADER(tests[i].code);
304 				fprintf(stderr,
305 					"Attribute `%s' listed multiple times"
306 					" in active list.\n", name_buf);
307 				pass = false;
308 			} else if (attr->type != type) {
309 				DUMP_SHADER(tests[i].code);
310 				fprintf(stderr,
311 					"Attribute `%s' should have type"
312 					" %s, but had type %s.\n",
313 					name_buf, piglit_get_gl_enum_name(attr->type),
314 					piglit_get_gl_enum_name(type));
315 				pass = false;
316 			}
317 
318 			visited_count[attr_idx]++;
319 		}
320 
321 		for (j = 0; tests[i].attributes[j].name != NULL; j++) {
322 			if (visited_count[j] == 0) {
323 				DUMP_SHADER(tests[i].code);
324 				fprintf(stderr,
325 					"Attribute `%s' should have been"
326 					" active but wasn't.\n",
327 					tests[i].attributes[j].name);
328 				pass = false;
329 			}
330 		}
331 	}
332 
333 	return pass;
334 }
335 
piglit_init(int argc,char ** argv)336 void piglit_init(int argc, char **argv)
337 {
338 	bool pass = true;
339 
340 	piglit_require_extension("GL_ARB_vertex_attrib_64bit");
341 
342 	pass = do_test(vertex_attrib_64bit_tests,
343 		       ARRAY_SIZE(vertex_attrib_64bit_tests));
344 
345 	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
346 }
347