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 DEALINGS
25 * \file 400-combinations.c
26 * Combine 20 vertex shaders and 20 fragment shaders in various ways.
28 * Verify that the right shaders are used in the right combinations several
31 * * The vertex shader has information baked-in that determines the X position
32 * of the block on the screen.
34 * * The fragment shader has information baked-in that determines how the
35 * block is colored. This is combined with data passed from the vertex
38 * Since data is passed from the vertex shader to the fragment shader, the
39 * test can use either rendezvous-by-name (default) or rendezvous-by-location
40 * (with --by-location command line parameter).
42 #include "piglit-util-gl.h"
43 #include "sso-common.h"
46 * Size of each square that will be drawn.
48 static const unsigned tile_size
= 5;
51 * Size of the gap between the squares.
53 static const unsigned border_size
= 2;
55 static GLuint vs_programs
[20];
56 static GLuint fs_programs
[20];
58 PIGLIT_GL_TEST_CONFIG_BEGIN
60 config
.supports_gl_compat_version
= 10;
61 config
.supports_gl_core_version
= 31;
63 config
.window_width
= (tile_size
+ border_size
)
64 * ARRAY_SIZE(vs_programs
);
65 config
.window_height
= (tile_size
+ border_size
)
66 * ARRAY_SIZE(fs_programs
);
67 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
| PIGLIT_GL_VISUAL_DOUBLE
;
69 PIGLIT_GL_TEST_CONFIG_END
73 static GLuint vao
= 0;
81 static struct combination combinations
[ARRAY_SIZE(vs_programs
)
82 * ARRAY_SIZE(fs_programs
)];
84 static const char *vs_code
=
86 "#extension GL_ARB_separate_shader_objects: require\n"
87 "#extension GL_ARB_explicit_attrib_location: require\n"
89 "layout(location = 0) in vec4 piglit_vertex;\n"
90 "layout(location = 1) in vec3 vertex_color;\n"
94 "const vec4 offset = vec4(%d, 0, 0, 0);\n"
96 "uniform mat4 transform;\n"
100 " gl_Position = transform * (piglit_vertex + offset);\n"
101 " %s = vertex_color;\n"
105 static const char *fs_code
=
107 "#extension GL_ARB_separate_shader_objects: require\n"
108 "#extension GL_ARB_explicit_attrib_location: enable\n"
110 "#if __VERSION__ >= 130\n"
111 "layout(location = 0) out vec4 out_color;\n"
113 "#define out_color gl_FragColor\n"
118 "const vec3 color_offset = vec3(%d, %d, %d);\n"
122 " out_color = vec4(%s + color_offset, 1.);\n"
132 static const float expected
[] = {
133 0.0f
, 1.0f
, 0.0f
, 1.0f
136 /* This is stored in row-major order. Note the GL_TRUE parameter to
137 * the glProgramUniformMatrix4fv call below.
139 const float transform
[16] = {
140 2.f
/ piglit_width
, 0.0f
, 0.0f
, -1.0f
,
141 0.0f
, 2.f
/ piglit_height
, 0.0f
, -1.0f
,
142 0.0f
, 0.0f
, 0.0f
, 0.0f
,
143 0.0f
, 0.0f
, 0.0f
, 1.0f
,
148 glClearColor(.5f
, .5f
, .5f
, 1.f
);
149 glClear(GL_COLOR_BUFFER_BIT
);
151 for (i
= 0; i
< ARRAY_SIZE(vs_programs
); i
++) {
153 glGetUniformLocation(vs_programs
[i
], "transform");
155 glProgramUniformMatrix4fv(vs_programs
[i
], loc
, 1, GL_TRUE
,
159 glBindProgramPipeline(pipe
);
161 for (i
= 0; i
< ARRAY_SIZE(combinations
); i
++) {
162 const unsigned row
= combinations
[i
].row
;
163 const unsigned col
= combinations
[i
].col
;
165 glUseProgramStages(pipe
, GL_VERTEX_SHADER_BIT
,
167 glUseProgramStages(pipe
, GL_FRAGMENT_SHADER_BIT
,
169 glDrawArrays(GL_TRIANGLE_FAN
, row
* 4, 4);
172 glBindProgramPipeline(0);
174 for (i
= 0; i
< ARRAY_SIZE(vs_programs
); i
++) {
175 for (j
= 0; j
< ARRAY_SIZE(fs_programs
); j
++) {
176 const unsigned x
= (i
* tile_size
)
177 + ((i
+ 1) * border_size
);
178 const unsigned y
= (j
* tile_size
)
179 + ((j
+ 1) * border_size
);
181 pass
= piglit_probe_rect_rgba(x
, y
,
182 tile_size
, tile_size
,
188 piglit_present_results();
189 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
192 #define RED(x) ((int) (x / 2))
193 #define GREEN(x) (-(int) x)
194 #define BLUE(x) ((int) (x * 7))
197 piglit_init(int argc
, char **argv
)
199 unsigned glsl_version
;
203 const char *location
;
204 const char *vertex_name
;
205 const char *fragment_name
;
215 piglit_require_extension("GL_ARB_separate_shader_objects");
216 piglit_require_extension("GL_ARB_explicit_attrib_location");
218 if (argc
> 1 && strcmp(argv
[1], "--by-location") == 0) {
219 location
= "layout(location = 3)";
224 vertex_name
= "in_color";
225 fragment_name
= "in_color";
228 glsl_version
= pick_a_glsl_version();
230 /* Generate the vertex shader programs. Each vertex shader is
231 * hardcoded to select a specific column on the display.
233 printf("Generating vertex shaders...\n");
234 for (i
= 0; i
< ARRAY_SIZE(vs_programs
); i
++) {
235 const unsigned base_x
= (i
* tile_size
)
236 + ((i
+ 1) * border_size
);
240 (void)!asprintf(&source
, vs_code
,
248 glCreateShaderProgramv(GL_VERTEX_SHADER
, 1,
249 (const GLchar
*const *) &source
);
250 piglit_link_check_status(vs_programs
[i
]);
258 printf("Generating fragment shaders...\n");
259 for (i
= 0; i
< ARRAY_SIZE(fs_programs
); i
++) {
262 (void)!asprintf(&source
, fs_code
,
266 RED(i
), GREEN(i
), BLUE(i
),
270 glCreateShaderProgramv(GL_FRAGMENT_SHADER
, 1,
271 (const GLchar
*const *) &source
);
272 piglit_link_check_status(fs_programs
[i
]);
280 glGenProgramPipelines(1, &pipe
);
282 /* Generate vertex data for the tests. The row of each block is
283 * determined by the vertex data. The color data for the block comes
284 * from the vertex data and the data baked into the fragment shader.
286 if (piglit_get_gl_version() >= 30
287 || piglit_is_extension_supported("GL_ARB_vertex_array_object")) {
288 glGenVertexArrays(1, &vao
);
289 glBindVertexArray(vao
);
292 glGenBuffers(1, &bo
);
293 glBindBuffer(GL_ARRAY_BUFFER
, bo
);
294 glBufferData(GL_ARRAY_BUFFER
,
295 sizeof(vert
[0]) * 4 * ARRAY_SIZE(fs_programs
),
296 NULL
, GL_STATIC_DRAW
);
298 vert
= glMapBuffer(GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
300 for (i
= 0; i
< ARRAY_SIZE(fs_programs
); i
++) {
301 const unsigned base_y
= (i
* tile_size
)
302 + ((i
+ 1) * border_size
);
304 vert
[(i
* 4) + 0].x
= 0.f
;
305 vert
[(i
* 4) + 0].y
= (float) base_y
;
306 vert
[(i
* 4) + 0].r
= (float) -RED(i
);
307 vert
[(i
* 4) + 0].g
= (float) 1 - GREEN(i
);
308 vert
[(i
* 4) + 0].b
= (float) -BLUE(i
);
310 vert
[(i
* 4) + 1].x
= (float) tile_size
;
311 vert
[(i
* 4) + 1].y
= (float) base_y
;
312 vert
[(i
* 4) + 1].r
= (float) -RED(i
);
313 vert
[(i
* 4) + 1].g
= (float) 1 - GREEN(i
);
314 vert
[(i
* 4) + 1].b
= (float) -BLUE(i
);
316 vert
[(i
* 4) + 2].x
= (float) tile_size
;
317 vert
[(i
* 4) + 2].y
= (float) (base_y
+ tile_size
);
318 vert
[(i
* 4) + 2].r
= (float) -RED(i
);
319 vert
[(i
* 4) + 2].g
= (float) 1 - GREEN(i
);
320 vert
[(i
* 4) + 2].b
= (float) -BLUE(i
);
322 vert
[(i
* 4) + 3].x
= 0.f
;
323 vert
[(i
* 4) + 3].y
= (float) (base_y
+ tile_size
);
324 vert
[(i
* 4) + 3].r
= (float) -RED(i
);
325 vert
[(i
* 4) + 3].g
= (float) 1 - GREEN(i
);
326 vert
[(i
* 4) + 3].b
= (float) -BLUE(i
);
329 glUnmapBuffer(GL_ARRAY_BUFFER
);
331 glVertexAttribPointer(0, 2, GL_FLOAT
, GL_FALSE
, sizeof(vert
[0]),
332 (void *)(intptr_t) offsetof(struct vertex
, x
));
333 glVertexAttribPointer(1, 3, GL_FLOAT
, GL_FALSE
, sizeof(vert
[0]),
334 (void *)(intptr_t) offsetof(struct vertex
, r
));
335 glEnableVertexAttribArray(0);
336 glEnableVertexAttribArray(1);
338 /* Generate the set of combinations of vertex shader programs and
339 * fragment shader programs that will be used together. This is all
340 * the possible combinations. The next step is to shuffle list so
341 * that there's (hopefully) no pattern to the access combination... to
342 * uncover driver bugs.
345 for (i
= 0; i
< ARRAY_SIZE(vs_programs
); i
++) {
346 for (j
= 0; j
< ARRAY_SIZE(fs_programs
); j
++) {
347 combinations
[idx
].row
= j
;
348 combinations
[idx
].col
= i
;
353 for (i
= ARRAY_SIZE(combinations
); i
> 1; i
--) {
354 const unsigned j
= rand() % i
;
357 const struct combination temp
= combinations
[j
];
358 combinations
[j
] = combinations
[i
- 1];
359 combinations
[i
- 1] = temp
;