ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_separate_shader_objects / 400-combinations.c
blob5f84cb149f119ed9b0b6dc89d35cf805eceecf4f
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 DEALINGS
21 * IN THE SOFTWARE.
24 /**
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
29 * ways.
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
36 * shader.
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"
45 /**
46 * Size of each square that will be drawn.
48 static const unsigned tile_size = 5;
50 /**
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
71 static GLuint pipe;
73 static GLuint vao = 0;
74 static GLuint bo = 0;
76 struct combination {
77 unsigned char row;
78 unsigned char col;
81 static struct combination combinations[ARRAY_SIZE(vs_programs)
82 * ARRAY_SIZE(fs_programs)];
84 static const char *vs_code =
85 "#version %d\n"
86 "#extension GL_ARB_separate_shader_objects: require\n"
87 "#extension GL_ARB_explicit_attrib_location: require\n"
88 "\n"
89 "layout(location = 0) in vec4 piglit_vertex;\n"
90 "layout(location = 1) in vec3 vertex_color;\n"
91 "\n"
92 "%s out vec3 %s;\n"
93 "\n"
94 "const vec4 offset = vec4(%d, 0, 0, 0);\n"
95 "\n"
96 "uniform mat4 transform;\n"
97 "\n"
98 "void main()\n"
99 "{\n"
100 " gl_Position = transform * (piglit_vertex + offset);\n"
101 " %s = vertex_color;\n"
102 "}\n"
105 static const char *fs_code =
106 "#version %d\n"
107 "#extension GL_ARB_separate_shader_objects: require\n"
108 "#extension GL_ARB_explicit_attrib_location: enable\n"
109 "\n"
110 "#if __VERSION__ >= 130\n"
111 "layout(location = 0) out vec4 out_color;\n"
112 "#else\n"
113 "#define out_color gl_FragColor\n"
114 "#endif\n"
115 "\n"
116 "%s in vec3 %s;\n"
117 "\n"
118 "const vec3 color_offset = vec3(%d, %d, %d);\n"
119 "\n"
120 "void main()\n"
121 "{\n"
122 " out_color = vec4(%s + color_offset, 1.);\n"
123 "}\n"
126 enum piglit_result
127 piglit_display(void)
129 unsigned i;
130 unsigned j;
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,
146 bool pass = true;
148 glClearColor(.5f, .5f, .5f, 1.f);
149 glClear(GL_COLOR_BUFFER_BIT);
151 for (i = 0; i < ARRAY_SIZE(vs_programs); i++) {
152 const GLint loc =
153 glGetUniformLocation(vs_programs[i], "transform");
155 glProgramUniformMatrix4fv(vs_programs[i], loc, 1, GL_TRUE,
156 transform);
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,
166 vs_programs[col]);
167 glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT,
168 fs_programs[row]);
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,
183 expected)
184 && pass;
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))
196 void
197 piglit_init(int argc, char **argv)
199 unsigned glsl_version;
200 unsigned i;
201 unsigned j;
202 unsigned idx;
203 const char *location;
204 const char *vertex_name;
205 const char *fragment_name;
207 struct vertex {
208 float x;
209 float y;
210 float r;
211 float g;
212 float b;
213 } *vert;
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)";
220 vertex_name = "a";
221 fragment_name = "b";
222 } else {
223 location = "";
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);
238 char *source = NULL;
240 (void)!asprintf(&source, vs_code,
241 glsl_version,
242 location,
243 vertex_name,
244 base_x,
245 vertex_name);
247 vs_programs[i] =
248 glCreateShaderProgramv(GL_VERTEX_SHADER, 1,
249 (const GLchar *const *) &source);
250 piglit_link_check_status(vs_programs[i]);
252 if (i == 0)
253 puts(source);
255 free(source);
258 printf("Generating fragment shaders...\n");
259 for (i = 0; i < ARRAY_SIZE(fs_programs); i++) {
260 char *source = NULL;
262 (void)!asprintf(&source, fs_code,
263 glsl_version,
264 location,
265 fragment_name,
266 RED(i), GREEN(i), BLUE(i),
267 fragment_name);
269 fs_programs[i] =
270 glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1,
271 (const GLchar *const *) &source);
272 piglit_link_check_status(fs_programs[i]);
274 if (i == 3)
275 puts(source);
277 free(source);
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.
344 idx = 0;
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;
349 idx++;
353 for (i = ARRAY_SIZE(combinations); i > 1; i--) {
354 const unsigned j = rand() % i;
356 if (j != i - 1) {
357 const struct combination temp = combinations[j];
358 combinations[j] = combinations[i - 1];
359 combinations[i - 1] = temp;