perf/pixel-rate: new pixel throughput microbenchmark
[piglit.git] / tests / shaders / version-mixing.c
blob88ef1042bd341334a26da3e117f3faceaa190d47
1 /*
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
13 * Software.
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.
24 /** \file
26 * Test that any desktop GLSL version may be linked with any other
27 * desktop GLSL version.
29 * From the GLSL 4.30 spec, section 3.3 (Preprocessor):
31 * "Shaders for the core or compatibility profiles that declare
32 * different versions can be linked together."
34 * This is a deliberate relaxation of the cross-version linking rules
35 * from previous versions of the GLSL spec (which prohibited some
36 * combinations of GLSL versions from being linked together). It was
37 * made because existing implementations didn't follow the old
38 * cross-version linking rules (see Khronos bug 8463). So it seems
39 * reasonable to expect all implementations to follow the new relaxed
40 * rules.
42 * This test can be run in the following ways:
44 * - "interstage" checks that a vertex shader of one version can be
45 * linked with a fragment shader of another version.
47 * - "intrastage" checks that two vertex shaders of different versions
48 * can be linked together.
50 * - "vs-gs" checks that a vertex shader of one version can be linked
51 * with a geometry shader of another version.
54 #include "piglit-util-gl.h"
56 static enum test_type {
57 test_type_interstage,
58 test_type_intrastage,
59 test_type_vs_gs,
60 } test_type;
62 static void parse_params(int argc, char **argv);
64 PIGLIT_GL_TEST_CONFIG_BEGIN
66 piglit_gl_process_args(&argc, argv, &config);
67 parse_params(argc, argv);
68 if (test_type == test_type_vs_gs) {
69 config.supports_gl_compat_version = 32;
70 config.supports_gl_core_version = 32;
71 } else {
72 config.supports_gl_compat_version = 10;
73 config.supports_gl_core_version = 31;
76 PIGLIT_GL_TEST_CONFIG_END
78 static const char *interstage_vs =
79 "#version %d\n"
80 "\n"
81 "void main()\n"
82 "{\n"
83 " gl_Position = vec4(0.0);\n"
84 "}\n";
86 static const char *interstage_gs =
87 "#version %d\n"
88 "\n"
89 "layout(triangles) in;\n"
90 "layout(triangle_strip, max_vertices = 3) out;\n"
91 "void main()\n"
92 "{\n"
93 " for (int i = 0; i < 3; i++) {\n"
94 " gl_Position = gl_in[i].gl_Position;\n"
95 " EmitVertex();\n"
96 " }\n"
97 "}\n";
99 static const char *interstage_fs =
100 "#version %d\n"
101 "\n"
102 "void main()\n"
103 "{\n"
104 " gl_FragColor = vec4(0.0);\n"
105 "}\n";
107 /* Section 1.2.1 (Summary of Changes from Version 4.10) of the OpenGL
108 * Shading Language 4.20 spec says:
110 * Move these previously deprecated features to be only in the
111 * compatibility profile:
112 * ...
113 * * The built-in variables gl_FragColor and gl_FragData.
115 static const char *interstage_fs_420 =
116 "#version %d\n"
117 "\n"
118 "out vec4 color;\n"
119 "\n"
120 "void main()\n"
121 "{\n"
122 " color = vec4(0.0);\n"
123 "}\n";
125 static const char *intrastage_vs1 =
126 "#version %d\n"
127 "\n"
128 "void f();\n"
129 "void main()\n"
130 "{\n"
131 " f();\n"
132 "}\n";
134 static const char *intrastage_vs2 =
135 "#version %d\n"
136 "\n"
137 "void f()\n"
138 "{\n"
139 " gl_Position = vec4(0.0);\n"
140 "}\n";
142 static int all_glsl_versions[] = {
143 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440
147 static void
148 print_usage_and_exit(const char *prog_name)
150 printf("Usage: %s <subtest>\n"
151 " where <subtest> is one of:\n"
152 " interstage: test interstage linking (vs-to-fs)\n"
153 " intrastage: test intrastage linking (vs-to-vs)\n"
154 " vs-gs: test interstage linking (vs-to-gs)\n",
155 prog_name);
156 piglit_report_result(PIGLIT_FAIL);
160 static int
161 get_max_glsl_version()
163 bool es;
164 int major, minor;
165 piglit_get_glsl_version(&es, &major, &minor);
166 if (es) {
167 printf("This test should only be run on desktop GL.\n");
168 piglit_report_result(PIGLIT_FAIL);
170 return 100 * major + minor;
175 * Try compiling a shader of type \c target, whose string is formed by
176 * applying \c version to \c shader_template, and attach it to \c
177 * prog. On success, return true. If there is a problem, print an
178 * error message using \c shader_desc to describe the shader, and
179 * return false.
181 static bool
182 try_attach_shader(GLuint prog, const char *shader_desc, GLenum target,
183 const char *shader_template, int version)
185 char *shader_text = NULL;
186 GLuint shader = glCreateShader(target);
187 GLint ok;
189 (void)!asprintf(&shader_text, shader_template, version);
190 glShaderSource(shader, 1, (const GLchar **) &shader_text, NULL);
191 free(shader_text);
192 glCompileShader(shader);
193 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
194 if (!ok) {
195 printf("%s failed to compile.\n", shader_desc);
196 glDeleteShader(shader);
197 return false;
199 glAttachShader(prog, shader);
200 glDeleteShader(shader);
201 return true;
206 * Test interstage linking between VS and FS, and print a message
207 * describing the result, and return true if compilation and linking
208 * succeeded.
210 static bool
211 test_interstage(int version_vs, int version_other, bool use_gs)
213 GLuint prog = glCreateProgram();
214 GLint ok;
216 if (!try_attach_shader(prog, "vertex shader", GL_VERTEX_SHADER,
217 interstage_vs, version_vs)) {
218 glDeleteProgram(prog);
219 return false;
221 if (use_gs) {
222 if (version_other < 150) {
223 printf("Not tested (GS requires GLSL 1.50).\n");
224 glDeleteProgram(prog);
225 return true;
227 if (!try_attach_shader(prog, "geometry shader",
228 GL_GEOMETRY_SHADER, interstage_gs,
229 version_other)) {
230 glDeleteProgram(prog);
231 return false;
233 } else {
234 const char *fs = interstage_fs;
236 if (version_other >= 420)
237 fs = interstage_fs_420;
239 if (!try_attach_shader(prog, "fragment shader",
240 GL_FRAGMENT_SHADER, fs,
241 version_other)) {
242 glDeleteProgram(prog);
243 return false;
246 glLinkProgram(prog);
247 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
248 if (ok)
249 printf("Success.\n");
250 else
251 printf("Link failed.\n");
252 return ok;
257 * Test intrastage linking between two VS shaders, and print a message
258 * describing the result, and return true if compilation and linking
259 * succeeded.
261 static bool
262 test_intrastage(int version_vs1, int version_vs2)
264 GLuint prog = glCreateProgram();
265 GLint ok;
267 if (!try_attach_shader(prog, "vertex shader 1", GL_VERTEX_SHADER,
268 intrastage_vs1, version_vs1)) {
269 glDeleteProgram(prog);
270 return false;
272 if (!try_attach_shader(prog, "vertex shader 2", GL_VERTEX_SHADER,
273 intrastage_vs2, version_vs2)) {
274 glDeleteProgram(prog);
275 return false;
277 glLinkProgram(prog);
278 glGetProgramiv(prog, GL_LINK_STATUS, &ok);
279 if (ok)
280 printf("Success.\n");
281 else
282 printf("Link failed.\n");
283 return ok;
287 void
288 parse_params(int argc, char **argv)
290 if (argc != 2)
291 print_usage_and_exit(argv[0]);
292 if (strcmp(argv[1], "interstage") == 0)
293 test_type = test_type_interstage;
294 else if (strcmp(argv[1], "intrastage") == 0)
295 test_type = test_type_intrastage;
296 else if (strcmp(argv[1], "vs-gs") == 0)
297 test_type = test_type_vs_gs;
298 else
299 print_usage_and_exit(argv[0]);
303 void
304 piglit_init(int argc, char **argv)
306 int i, j;
307 bool pass = true;
308 int max_glsl_version;
310 piglit_require_vertex_shader();
311 if (test_type != test_type_intrastage)
312 piglit_require_fragment_shader();
314 max_glsl_version = get_max_glsl_version();
316 for (i = 0; i < ARRAY_SIZE(all_glsl_versions); i++) {
317 if (all_glsl_versions[i] > max_glsl_version)
318 continue;
319 for (j = 0; j < ARRAY_SIZE(all_glsl_versions); j++) {
320 if (all_glsl_versions[j] > max_glsl_version)
321 continue;
322 printf("Testing versions %d and %d: ",
323 all_glsl_versions[i], all_glsl_versions[j]);
324 switch (test_type) {
325 case test_type_interstage:
326 pass = test_interstage(all_glsl_versions[i],
327 all_glsl_versions[j],
328 false /* use_gs */)
329 && pass;
330 break;
331 case test_type_vs_gs:
332 pass = test_interstage(all_glsl_versions[i],
333 all_glsl_versions[j],
334 true /* use_gs */)
335 && pass;
336 break;
337 case test_type_intrastage:
338 pass = test_intrastage(all_glsl_versions[i],
339 all_glsl_versions[j])
340 && pass;
341 break;
342 default:
343 /* Should never occur */
344 piglit_report_result(PIGLIT_FAIL);
345 break;
350 piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
354 enum piglit_result
355 piglit_display(void)
357 /* Should never be reached */
358 return PIGLIT_FAIL;