1 /*
2 * Copyright © 2013 Gregory Hainaut <gregory.hainaut@gmail.com>
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 #include "piglit-util-gl.h"
25
26 PIGLIT_GL_TEST_CONFIG_BEGIN
27
28 config.supports_gl_compat_version = 21;
29 config.supports_gl_core_version = 31;
30
31 PIGLIT_GL_TEST_CONFIG_END
32
33 static const char vs_source_template[] =
34 "#version %d\n"
35 "\n"
36 "#if __VERSION__ > 140\n"
37 "out gl_PerVertex {\n"
38 " vec4 gl_Position;\n"
39 "};\n"
40 "\n"
41 "in vec4 position;\n"
42 "#else\n"
43 "attribute vec4 position;\n"
44 "#endif\n"
45 "\n"
46 "void main()\n"
47 "{\n"
48 " gl_Position = position;\n"
49 "}\n"
50 ;
51 static const char fs_source_template[] =
52 "#version %d\n"
53 "\n"
54 "#if __VERSION__ > 140\n"
55 "out vec4 color;\n"
56 "#else\n"
57 "#define color gl_FragColor\n"
58 "#endif\n"
59 "\n"
60 "void main()\n"
61 "{\n"
62 " color = vec4(0.0, 1.0, 0.0, 0.0);\n"
63 "}\n"
64 ;
65 static const char gs_source_template[] =
66 "#version %d\n"
67 "\n"
68 "in gl_PerVertex {\n"
69 " vec4 gl_Position;\n"
70 "} gl_in[];\n"
71 "\n"
72 "out gl_PerVertex {\n"
73 " vec4 gl_Position;\n"
74 "};\n"
75 "\n"
76 "layout(triangles) in;\n"
77 "layout(triangle_strip, max_vertices = 3) out;\n"
78 "void main()\n"
79 "{\n"
80 " for(int i = 0; i < gl_in.length(); i++) {\n"
81 " gl_Position = gl_in[i].gl_Position;\n"
82 " EmitVertex();\n"
83 " }\n"
84 " EndPrimitive();\n"
85 "}\n"
86 ;
87 static const char tc_source_template[] =
88 "#version %d\n"
89 "#extension GL_ARB_tessellation_shader: enable\n"
90 "\n"
91 "in gl_PerVertex {\n"
92 " vec4 gl_Position;\n"
93 "} gl_in[];\n"
94 "\n"
95 "out gl_PerVertex {\n"
96 " vec4 gl_Position;\n"
97 "} gl_out[];\n"
98 "\n"
99 "layout(vertices = 3) out;\n"
100 "void main()\n"
101 "{\n"
102 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
103 " gl_TessLevelOuter[0] = 1.0;\n"
104 " gl_TessLevelOuter[1] = 1.0;\n"
105 " gl_TessLevelOuter[2] = 1.0;\n"
106 " gl_TessLevelInner[0] = 1.0;\n"
107 " gl_TessLevelInner[1] = 1.0;\n"
108 "}\n"
109 ;
110 static const char te_source_template[] =
111 "#version %d\n"
112 "#extension GL_ARB_tessellation_shader: enable\n"
113 "\n"
114 "in gl_PerVertex {\n"
115 " vec4 gl_Position;\n"
116 "} gl_in[];\n"
117 "\n"
118 "out gl_PerVertex {\n"
119 " vec4 gl_Position;\n"
120 "};\n"
121 "\n"
122 "layout(triangles, equal_spacing) in;\n"
123 "\n"
124 "void main()\n"
125 "{\n"
126 " vec4 p0 = gl_in[0].gl_Position;\n"
127 " vec4 p1 = gl_in[1].gl_Position;\n"
128 " vec4 p2 = gl_in[2].gl_Position;\n"
129 "\n"
130 " vec3 p = gl_TessCoord.xyz;\n"
131 "\n"
132 " gl_Position = p0*p.x + p1*p.y + p2*p.z;\n"
133 "}\n"
134 ;
135
136 static bool pass;
137
138 enum piglit_result
piglit_display(void)139 piglit_display(void)
140 {
141 /* UNREACHED */
142 return PIGLIT_FAIL;
143 }
144
145 static void
validate_pipe(GLuint pipe,bool expected,const char * test_name)146 validate_pipe(GLuint pipe, bool expected, const char *test_name)
147 {
148 GLint status;
149
150 pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
151
152 status = piglit_program_pipeline_check_status_quiet(pipe);
153
154 if (status != expected) {
155 fprintf(stderr,
156 "Wrong pipeline validation status. Got %d, but "
157 "expected %d\n",
158 status, expected);
159 piglit_report_subtest_result(PIGLIT_FAIL, "%s", test_name);
160 pass = false;
161 } else {
162 piglit_report_subtest_result(PIGLIT_PASS, "%s", test_name);
163 }
164 }
165
166 static void
build_and_validate_pipe(GLuint pipe,bool expected,const char * test_name,GLbitfield bit_a,GLuint prog_a,GLbitfield bit_b,GLuint prog_b,GLbitfield bit_c,GLuint prog_c,GLbitfield bit_d,GLuint prog_d,GLbitfield bit_e,GLuint prog_e)167 build_and_validate_pipe(GLuint pipe, bool expected, const char *test_name,
168 GLbitfield bit_a, GLuint prog_a,
169 GLbitfield bit_b, GLuint prog_b,
170 GLbitfield bit_c, GLuint prog_c,
171 GLbitfield bit_d, GLuint prog_d,
172 GLbitfield bit_e, GLuint prog_e)
173 {
174 if (!piglit_automatic)
175 printf("%s\n", test_name);
176
177 if (bit_a != GL_ALL_SHADER_BITS)
178 glUseProgramStages(pipe, GL_ALL_SHADER_BITS, 0);
179
180 if (bit_a != 0)
181 glUseProgramStages(pipe, bit_a, prog_a);
182
183 if (bit_b != 0)
184 glUseProgramStages(pipe, bit_b, prog_b);
185
186 if (bit_c != 0)
187 glUseProgramStages(pipe, bit_c, prog_c);
188
189 if (bit_d != 0)
190 glUseProgramStages(pipe, bit_d, prog_d);
191
192 if (bit_e != 0)
193 glUseProgramStages(pipe, bit_e, prog_e);
194
195 validate_pipe(pipe, expected, test_name);
196
197 if (!piglit_automatic)
198 printf("\n");
199 }
200
201 static GLuint
create_prog(GLint sh1,GLint sh2)202 create_prog(GLint sh1, GLint sh2)
203 {
204 GLint p = 0;
205
206 p = glCreateProgram();
207 glProgramParameteri(p, GL_PROGRAM_SEPARABLE, GL_TRUE);
208 if (sh1)
209 glAttachShader(p, sh1);
210 if (sh2)
211 glAttachShader(p, sh2);
212 glLinkProgram(p);
213
214 pass = piglit_link_check_status(p) && pass;
215
216 return p;
217 }
218
219 void
piglit_init(int argc,char ** argv)220 piglit_init(int argc, char **argv)
221 {
222 GLint vs, fs, gs, tes, tcs;
223 GLuint pipe;
224 GLint prog_vs, prog_fs, prog_gs = 0, prog_tcs = 0, prog_tes = 0, prog_tess;
225 GLint prog_vs_fs, prog_vs_gs = 0;
226 GLint separable;
227 int version;
228
229 char *vs_source, *fs_source, *gs_source, *te_source, *tc_source;
230
231 const bool has_tess = piglit_get_gl_version() >= 40
232 || piglit_is_extension_supported("GL_ARB_tessellation_shader");
233 const bool has_geo =
234 piglit_get_gl_version() >= 32;
235
236 piglit_require_extension("GL_ARB_separate_shader_objects");
237
238 if (piglit_get_gl_version() >= 40)
239 version = 400;
240 else if (piglit_get_gl_version() >= 32)
241 version = 150;
242 else
243 version = 120;
244
245 pass = true;
246
247 /* create the shader program */
248 (void)!asprintf(&vs_source, vs_source_template, version);
249 (void)!asprintf(&fs_source, fs_source_template, version);
250 (void)!asprintf(&gs_source, gs_source_template, version);
251 (void)!asprintf(&te_source, te_source_template, version);
252 (void)!asprintf(&tc_source, tc_source_template, version);
253
254 vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_source);
255 fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_source);
256 pass = (fs != 0) && (vs != 0) && pass;
257 if (has_geo) {
258 gs = piglit_compile_shader_text(GL_GEOMETRY_SHADER, gs_source);
259 pass = (gs != 0) && pass;
260 }
261 if (has_tess) {
262 tes = piglit_compile_shader_text(GL_TESS_EVALUATION_SHADER,
263 te_source);
264 tcs = piglit_compile_shader_text(GL_TESS_CONTROL_SHADER,
265 tc_source);
266 pass = (tes != 0) && (tcs != 0) && pass;
267 }
268
269 free(vs_source);
270 free(fs_source);
271 free(gs_source);
272 free(te_source);
273 free(tc_source);
274
275 prog_vs = create_prog(vs, 0);
276 prog_fs = create_prog(fs, 0);
277 prog_vs_fs = create_prog(vs, fs);
278 if (has_geo) {
279 prog_gs = create_prog(gs, 0);
280 prog_vs_gs = create_prog(vs, gs);
281 }
282 if (has_tess) {
283 prog_tcs = create_prog(tcs, 0);
284 prog_tes = create_prog(tes, 0);
285 prog_tess = create_prog(tcs, tes);
286 }
287
288 /* Setup or compilation failure. Stop here */
289 pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
290 if (!pass) {
291 piglit_report_result(PIGLIT_FAIL);
292 return;
293 }
294
295 if (!piglit_automatic) {
296 if (has_tess && has_geo) {
297 printf("INFO: ALL stages supported: running all "
298 "test\n");
299 } else {
300 if (!has_tess)
301 printf("INFO: GL_ARB_tessellation_shader / "
302 "OpenGL 4.0 not supported: tessellation "
303 "test disabled\n");
304 if (!has_geo)
305 printf("INFO: OpenGL 3.2 not "
306 "supported: geometry test disabled\n");
307 }
308 }
309
310 /* Create the pipeline */
311 glGenProgramPipelines(1, &pipe);
312 glBindProgramPipeline(pipe);
313
314 build_and_validate_pipe(pipe, true,
315 "VS/FS program, single glUseProgramStages "
316 "call",
317 GL_ALL_SHADER_BITS, prog_vs_fs,
318 0, 0,
319 0, 0,
320 0, 0,
321 0, 0);
322
323 build_and_validate_pipe(pipe, true,
324 "VS/FS program, multiple glUseProgramStages "
325 "calls",
326 GL_FRAGMENT_SHADER_BIT, prog_vs_fs,
327 GL_VERTEX_SHADER_BIT, prog_vs_fs,
328 0, 0,
329 0, 0,
330 0, 0);
331
332 build_and_validate_pipe(pipe, true,
333 "program per pipeline stage",
334 GL_VERTEX_SHADER_BIT, prog_vs,
335 GL_FRAGMENT_SHADER_BIT, prog_fs,
336 (has_geo) ? GL_GEOMETRY_SHADER_BIT : 0,
337 prog_gs,
338 (has_tess) ? GL_TESS_CONTROL_SHADER_BIT : 0,
339 prog_tcs,
340 (has_tess) ? GL_TESS_EVALUATION_SHADER_BIT : 0,
341 prog_tes);
342
343 /* Section 2.11.11 (Shader Execution), subpart "Validation" of the
344 * OpenGL 4.1 spec says:
345 *
346 * "If the current set of active program objects cannot be
347 * executed, no primitives are processed and the error
348 * INVALID_OPERATION will be generated. This error is generated
349 * by any command that transfers vertices to the GL if:
350 *
351 * ...
352 *
353 * - One program object is active for at least two shader stages
354 * and a second program is active for a shader stage between two
355 * stages for which the first program was active."
356 */
357 if (has_geo)
358 build_and_validate_pipe(pipe, false,
359 "GS splitting a VS/FS pipeline",
360 GL_ALL_SHADER_BITS, prog_vs_fs,
361 GL_GEOMETRY_SHADER_BIT, prog_gs,
362 0, 0,
363 0, 0,
364 0, 0);
365 else
366 piglit_report_subtest_result(PIGLIT_SKIP,
367 "GS splitting a VS/FS pipeline");
368
369 if (has_tess)
370 build_and_validate_pipe(pipe, false,
371 "TCS splitting a VS/GS pipeline",
372 GL_ALL_SHADER_BITS, prog_vs_gs,
373 GL_TESS_CONTROL_SHADER_BIT, prog_tcs,
374 0, 0,
375 0, 0,
376 0, 0);
377 else
378 piglit_report_subtest_result(PIGLIT_SKIP,
379 "TCS splitting a VS/GS pipeline");
380
381 if (has_tess)
382 build_and_validate_pipe(pipe, false,
383 "TES splitting a VS/GS program",
384 GL_ALL_SHADER_BITS, prog_vs_gs,
385 GL_FRAGMENT_SHADER_BIT, prog_fs,
386 GL_TESS_EVALUATION_SHADER_BIT, prog_tes,
387 0, 0,
388 0, 0);
389 else
390 piglit_report_subtest_result(PIGLIT_SKIP,
391 "TES splitting a VS/GS program");
392
393 /* Section 2.11.11 (Shader Execution), subpart "Validation" of the
394 * OpenGL 4.1 spec says:
395 *
396 * "If the current set of active program objects cannot be
397 * executed, no primitives are processed and the error
398 * INVALID_OPERATION will be generated. This error is generated
399 * by any command that transfers vertices to the GL if:
400 *
401 * ...
402 *
403 * - There is an active program for tessellation control,
404 * tessellation evaluation, or geometry stages with
405 * corresponding executable shader, but there is no active
406 * program with executable vertex shader."
407 */
408 if (has_geo)
409 build_and_validate_pipe(pipe, false,
410 "GS without VS",
411 GL_FRAGMENT_SHADER_BIT, prog_fs,
412 GL_GEOMETRY_SHADER_BIT, prog_gs,
413 0, 0,
414 0, 0,
415 0, 0);
416 else
417 piglit_report_subtest_result(PIGLIT_SKIP, "GS without VS");
418
419 if (has_tess)
420 build_and_validate_pipe(pipe, false,
421 "TES/TCS without VS",
422 GL_ALL_SHADER_BITS, prog_tess,
423 GL_FRAGMENT_SHADER_BIT, prog_fs,
424 0, 0,
425 0, 0,
426 0, 0);
427 else
428 piglit_report_subtest_result(PIGLIT_SKIP, "TES/TCS without VS");
429
430 /* Section 2.11.11 (Shader Execution), subpart "Validation" of the
431 * OpenGL 4.1 spec says:
432 *
433 * "If the current set of active program objects cannot be
434 * executed, no primitives are processed and the error
435 * INVALID_OPERATION will be generated. This error is generated
436 * by any command that transfers vertices to the GL if:
437 *
438 * - A program object is active for at least one, but not all of
439 * the shader stages that were present when the program was
440 * linked."
441 */
442 build_and_validate_pipe(pipe, false,
443 "Only VS from a VS/FS program",
444 GL_FRAGMENT_SHADER_BIT, prog_fs,
445 GL_VERTEX_SHADER_BIT, prog_vs_fs,
446 0, 0,
447 0, 0,
448 0, 0);
449
450 if (has_geo)
451 build_and_validate_pipe(pipe, false,
452 "Only GS from a VS/GS program",
453 GL_FRAGMENT_SHADER_BIT, prog_fs,
454 GL_GEOMETRY_SHADER_BIT, prog_vs_gs,
455 GL_VERTEX_SHADER_BIT, prog_vs,
456 0, 0,
457 0, 0);
458 else
459 piglit_report_subtest_result(PIGLIT_SKIP,
460 "Only GS from a VS/GS program");
461
462 if (has_tess)
463 build_and_validate_pipe(pipe, false,
464 "Only TES from TES/TCS program",
465 GL_FRAGMENT_SHADER_BIT, prog_fs,
466 GL_TESS_EVALUATION_SHADER_BIT, prog_tess,
467 GL_VERTEX_SHADER_BIT, prog_vs,
468 0, 0,
469 0, 0);
470 else
471 piglit_report_subtest_result(PIGLIT_SKIP,
472 "Only TES from TES/TCS program");
473
474 /* Section 2.11.11 (Shader Execution), subpart "Validation" of the
475 * OpenGL 4.1 spec says:
476 *
477 * "If the current set of active program objects cannot be
478 * executed, no primitives are processed and the error
479 * INVALID_OPERATION will be generated. This error is generated
480 * by any command that transfers vertices to the GL if:
481 *
482 * ...
483 *
484 * - There is no current unified program object and the current
485 * program pipeline object includes a program object that was
486 * relinked since being applied to the pipeline object via
487 * UseProgramStages with the PROGRAM_SEPARABLE parameter set to
488 * FALSE."
489 */
490 build_and_validate_pipe(pipe, true,
491 "Relink attached VS without "
492 "GL_PROGRAM_SEPARABLE (sanity pre-test)",
493 GL_FRAGMENT_SHADER_BIT, prog_fs,
494 GL_VERTEX_SHADER_BIT, prog_vs,
495 0, 0,
496 0, 0,
497 0, 0);
498
499 glGetProgramiv(prog_vs, GL_PROGRAM_SEPARABLE, &separable);
500 if (!separable) {
501 printf("Error: %d was not a separable program\n", prog_vs);
502 pass = false;
503 }
504
505 glProgramParameteri(prog_vs, GL_PROGRAM_SEPARABLE, GL_FALSE);
506
507 glGetProgramiv(prog_vs, GL_PROGRAM_SEPARABLE, &separable);
508
509 /* NOTE: This check /may/ need to be moved after the call to
510 * glLinkProgram. There has been some discussion as to whether this
511 * is supposed to be "latched" state.
512 */
513 if (separable) {
514 printf("Error: fail to remove separable flags of program %d\n",
515 prog_vs);
516 pass = false;
517 }
518
519 glLinkProgram(prog_vs);
520 pass = piglit_link_check_status(prog_vs) && pass;
521 validate_pipe(pipe, GL_FALSE,
522 "Relink attached VS without GL_PROGRAM_SEPARABLE");
523
524 piglit_present_results();
525
526 piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
527 }
528