ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / ext_transform_feedback / max-varyings.c
blobbbce09cce0763904dcaaf6e37086d1ed2ecb953a
1 /*
2 * Copyright © 2012 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 /** @file glsl-max-varyings.c
26 * Test that all varyings can be captured using transform feedback, up
27 * to the maximum allowed by
28 * GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. Also verify that
29 * the varyings are passed correctly to the fragment shader. This
30 * test uses vec4 varyings, so it does not rely on the implementation
31 * packing varyings correctly.
33 * The test uses a vertex shader that generates an array of
34 * (GL_MAX_VARYING_FLOATS / 4) vec4's, and a fragment shader that
35 * checks the values of all of those vec4's. It uses transform
36 * feedback to capture contiguous subsets of that array, with all
37 * possible lengths and offsets.
40 #include "piglit-util-gl.h"
42 #define MAX_VARYING 32
43 #define AOA_OUTER_DIM 2
45 static const struct piglit_gl_test_config * piglit_config;
46 static const char *xfb_varying_array[MAX_VARYING];
47 static const char *xfb_varying_aoa[MAX_VARYING];
48 static GLuint xfb_buf;
50 /* Generate a VS that writes to a varying vec4[num_varyings] called
51 * "v". The values written are v[0] = (0.0, 1.0, 2.0, 3.0), v[1] =
52 * (4.0, 5.0, 6.0, 7.0), and so on.
54 static GLint
55 get_vs(int num_varyings)
57 GLuint shader;
58 char vstext[2048];
60 sprintf(vstext,
61 "#version 120\n"
62 "varying vec4[%d] v;\n"
63 "\n"
64 "void main()\n"
65 "{\n"
66 " int i;\n"
67 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
68 " for (i = 0; i < v.length(); ++i) {\n"
69 " v[i] = 4.0*i + vec4(0.0, 1.0, 2.0, 3.0);\n"
70 " }\n"
71 "}\n", num_varyings);
73 shader = piglit_compile_shader_text(GL_VERTEX_SHADER, vstext);
75 return shader;
78 static GLint
79 get_vs_aoa(int num_varyings)
81 GLuint shader;
82 char vstext[2048];
83 int inner_dim = num_varyings / AOA_OUTER_DIM;
85 /* If there is an odd number of varyings add one more */
86 char *extra_varying;
87 char *extra_statement;
88 if (num_varyings % 2 != 0) {
89 extra_varying = "varying vec4 y;";
90 extra_statement = "y = 4.0*(offset+j) + vec4(0.0, 1.0, 2.0, 3.0);";
91 } else {
92 extra_varying = "";
93 extra_statement = "";
96 sprintf(vstext,
97 "#version 120\n"
98 "#extension GL_ARB_arrays_of_arrays : enable\n"
99 "varying vec4[%d][%d] v;\n"
100 "%s\n"
101 "\n"
102 "void main()\n"
103 "{\n"
104 " int offset;\n"
105 " int j;\n"
106 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
107 " for (int i = 0; i < v.length(); ++i) {\n"
108 " offset = i * v[i].length();\n"
109 " for (j = 0; j < v[i].length(); ++j) {\n"
110 " v[i][j] = 4.0*(offset+j) + vec4(0.0, 1.0, 2.0, 3.0);\n"
111 " }\n"
112 " }\n"
113 " %s\n"
114 "}\n", AOA_OUTER_DIM, inner_dim, extra_varying, extra_statement);
116 shader = piglit_compile_shader_text(GL_VERTEX_SHADER, vstext);
118 return shader;
121 /* Generate a FS that checks all the varyings written by the VS, and
122 * outputs green if they are all correct.
124 static GLint
125 get_fs(int num_varyings)
127 GLuint shader;
128 char fstext[2048];
130 sprintf(fstext,
131 "#version 120\n"
132 "varying vec4[%d] v;\n"
133 "\n"
134 "void main()\n"
135 "{\n"
136 " bool failed = false;\n"
137 " for(int i = 0; i < v.length(); ++i) {\n"
138 " failed = failed || (v[i] != 4.0*i + vec4(0.0, 1.0, 2.0, 3.0));\n"
139 " }\n"
140 " gl_FragColor = vec4(float(failed), 1.0 - float(failed), 0.0, 1.0);\n"
141 "}\n", num_varyings);
143 shader = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fstext);
145 return shader;
148 static GLint
149 get_fs_aoa(int num_varyings)
151 GLuint shader;
152 char fstext[2048];
153 int inner_dim = num_varyings / AOA_OUTER_DIM;
155 /* If there is an odd number of varyings add one more */
156 char *extra_varying;
157 char *extra_statement;
158 if (num_varyings % 2 != 0) {
159 extra_varying = "varying vec4 y;";
160 extra_statement = "failed = failed || (y != 4.0*(offset+j) + vec4(0.0, 1.0, 2.0, 3.0));";
162 } else {
163 extra_varying = "";
164 extra_statement = "";
167 sprintf(fstext,
168 "#version 120\n"
169 "#extension GL_ARB_arrays_of_arrays : enable\n"
170 "varying vec4[%d][%d] v;\n"
171 "%s\n"
172 "\n"
173 "void main()\n"
174 "{\n"
175 " bool failed = false;\n"
176 " int offset;\n"
177 " int j;\n"
178 " for(int i = 0; i < v.length(); ++i) {\n"
179 " offset = i * v[i].length();\n"
180 " for (j = 0; j < v[i].length(); ++j) {\n"
181 " failed = failed || (v[i][j] != 4.0*(offset+j) + vec4(0.0, 1.0, 2.0, 3.0));\n"
182 " }\n"
183 " }\n"
184 " %s\n"
185 " gl_FragColor = vec4(float(failed), 1.0 - float(failed), 0.0, 1.0);\n"
186 "}\n", AOA_OUTER_DIM, inner_dim, extra_varying, extra_statement);
188 shader = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fstext);
190 return shader;
194 * Initialize xfb_varying_array to contain the names of the varyings
195 * used by get_vs and get_fs.
197 static void
198 init_xfb_varyings(int max_varyings)
200 int i, j;
201 int inner_dim = max_varyings / AOA_OUTER_DIM;
202 int count = 0;
204 /* Initialise arrays of arrays */
205 for (i = 0; i < AOA_OUTER_DIM; ++i) {
206 for (j = 0; j < inner_dim; ++j) {
207 char *buf = malloc(16);
208 sprintf(buf, "v[%d][%d]", i, j);
209 xfb_varying_aoa[count++] = buf;
212 if (max_varyings % 2 != 0) {
213 char *buf = malloc(8);
214 sprintf(buf, "y");
215 xfb_varying_aoa[count++] = buf;
218 /* Initialise singlie dimension array */
219 for (i = 0; i < MAX_VARYING; ++i) {
220 char *buf = malloc(6);
221 sprintf(buf, "v[%d]", i);
222 xfb_varying_array[i] = buf;
226 static int
227 coord_from_index(int index)
229 return 2 + 12 * index;
232 static GLboolean
233 check_xfb_output(int max_varyings, int num_xfb_varyings,
234 int offset, const char **xfb_varyings)
236 GLboolean pass = GL_TRUE;
237 int vertex, varying, i;
238 float (*buffer)[4] = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER,
239 GL_READ_ONLY);
240 int numFail = 0;
242 for (vertex = 0; vertex < 6; ++vertex) {
243 for (varying = 0; varying < num_xfb_varyings; ++varying) {
244 float expected[4];
245 float *actual;
246 for (i = 0; i < 4; ++i) {
247 expected[i] = (varying + offset) * 4.0 + i;
249 actual = buffer[vertex * num_xfb_varyings + varying];
250 if (memcmp(expected, actual, 4 * sizeof(float)) != 0) {
251 printf("When recording %i varyings\n",
252 num_xfb_varyings);
253 printf("Out of a total of %i\n", max_varyings);
254 printf("With an offset of %i\n", offset);
255 printf("Got incorrect transform feedback data "
256 "for vertex %i, varying %s\n",
257 vertex, *(xfb_varyings + offset));
258 printf("Expected (%f, %f, %f, %f)\n",
259 expected[0], expected[1], expected[2],
260 expected[3]);
261 printf("Actual (%f, %f, %f, %f)\n",
262 actual[0], actual[1], actual[2],
263 actual[3]);
264 pass = GL_FALSE;
265 if (++numFail >= 10) {
266 goto end;
272 end:
273 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
275 return pass;
278 static GLboolean
279 draw(GLuint vs, GLuint fs, int num_xfb_varyings,
280 int max_varyings, const char **xfb_varyings)
282 GLboolean pass = GL_TRUE;
283 int offset;
285 for (offset = 0; offset + num_xfb_varyings <= max_varyings; ++offset) {
286 GLuint prog;
287 float initial_buffer[MAX_VARYING * 6][4];
289 prog = glCreateProgram();
290 glAttachShader(prog, vs);
291 glAttachShader(prog, fs);
293 glTransformFeedbackVaryings(prog, num_xfb_varyings,
294 xfb_varyings + offset,
295 GL_INTERLEAVED_ATTRIBS);
297 glLinkProgram(prog);
298 if (!piglit_link_check_status(prog))
299 piglit_report_result(PIGLIT_FAIL);
301 glUseProgram(prog);
303 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf);
304 memset(initial_buffer, 0, sizeof(initial_buffer));
305 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
306 sizeof(initial_buffer), initial_buffer,
307 GL_STREAM_READ);
308 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buf);
309 glBeginTransformFeedback(GL_TRIANGLES);
311 piglit_draw_rect(coord_from_index(offset),
312 coord_from_index(num_xfb_varyings - 1),
314 10);
316 glEndTransformFeedback();
317 pass = check_xfb_output(max_varyings, num_xfb_varyings,
318 offset, xfb_varyings);
320 glDeleteProgram(prog);
321 if (!pass) {
322 break;
326 return pass;
329 static GLboolean
330 run_subtest(GLuint vs, GLuint fs, int max_xfb_varyings,
331 int max_varyings, const char **xfb_varyings)
333 GLboolean pass = GL_TRUE;
334 int row, col;
336 glClearColor(0.5, 0.5, 0.5, 0.5);
337 glClear(GL_COLOR_BUFFER_BIT);
339 for (row = 0; row < max_xfb_varyings; row++) {
340 pass = draw(vs, fs, row + 1, max_varyings, xfb_varyings);
341 if (!pass) {
342 goto end;
346 for (row = 0; row < max_xfb_varyings; row++) {
347 for (col = 0; col < max_varyings - row; col++) {
348 GLboolean ok;
349 float green[3] = {0.0, 1.0, 0.0};
351 ok = piglit_probe_rect_rgb(coord_from_index(col),
352 coord_from_index(row),
353 10, 10,
354 green);
355 if (!ok) {
356 printf(" Failure with %d vec4 varyings"
357 " captured and offset %d\n",
358 row + 1, col);
359 pass = GL_FALSE;
360 goto end;
364 end:
365 return pass;
368 struct common_data {
369 int max_varyings;
370 GLint max_components;
371 int max_xfb_varyings;
372 GLint max_xfb_components;
375 static enum piglit_result
376 test_1d_array(void * data) {
377 struct common_data * test_data = (struct common_data *)data;
379 GLuint vs = get_vs(test_data->max_varyings);
380 GLuint fs = get_fs(test_data->max_varyings);
381 bool pass = run_subtest(
382 vs, fs,
383 test_data->max_xfb_varyings,
384 test_data->max_varyings,
385 xfb_varying_array);
387 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
390 static enum piglit_result
391 test_aoa(void * data) {
392 if (!piglit_is_extension_supported("GL_ARB_arrays_of_arrays")) {
393 return PIGLIT_SKIP;
396 struct common_data * test_data = (struct common_data *)data;
398 GLuint vs = get_vs_aoa(test_data->max_varyings);
399 GLuint fs = get_fs_aoa(test_data->max_varyings);
400 bool pass = run_subtest(
403 test_data->max_xfb_varyings,
404 test_data->max_varyings, xfb_varying_aoa);
406 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
409 static struct piglit_subtest tests[] = {
411 "max-varying-single-dimension-array",
412 "1d-array",
413 test_1d_array,
414 NULL,
417 "max-varying-arrays-of-arrays",
418 "aoa",
419 test_aoa,
420 NULL,
422 { NULL }
425 /* 10x10 rectangles with 2 pixels of pad. Deal with up to 32 varyings. */
427 PIGLIT_GL_TEST_CONFIG_BEGIN
429 piglit_config = &config;
430 config.subtests = tests;
431 config.supports_gl_compat_version = 20;
433 config.window_width = (2+MAX_VARYING*12);
434 config.window_height = (2+MAX_VARYING*12);
435 config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
436 config.khr_no_error_support = PIGLIT_NO_ERRORS;
438 PIGLIT_GL_TEST_CONFIG_END
440 enum piglit_result
441 piglit_display(void)
443 struct common_data data = { 0, 0, 0, 0 };
444 enum piglit_result status = PIGLIT_PASS;
446 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
448 glGetIntegerv(GL_MAX_VARYING_FLOATS, &data.max_components);
449 data.max_varyings = data.max_components / 4;
450 init_xfb_varyings(data.max_varyings);
452 printf("GL_MAX_VARYING_FLOATS = %i\n", data.max_components);
454 if (data.max_varyings > MAX_VARYING) {
455 printf("test not designed to handle >%d varying vec4s.\n"
456 "(implementation reports %d components)\n",
457 data.max_components, MAX_VARYING);
458 data.max_varyings = MAX_VARYING;
459 status = PIGLIT_WARN;
462 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
463 &data.max_xfb_components);
464 data.max_xfb_varyings = MIN2(data.max_xfb_components / 4, data.max_varyings);
466 printf("GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = %i\n",
467 data.max_xfb_components);
469 for (unsigned i = 0; i < ARRAY_SIZE(tests); ++i) {
470 tests[i].data = (void *)&data;
473 status = piglit_run_selected_subtests(
474 tests,
475 piglit_config->selected_subtests,
476 piglit_config->num_selected_subtests,
477 status);
479 return status;
482 void piglit_init(int argc, char **argv)
484 piglit_require_GLSL_version(120);
485 piglit_require_transform_feedback();
486 glGenBuffers(1, &xfb_buf);
488 printf("Vertical axis: Increasing numbers of varyings captured by "
489 "transform feedback.\n");
490 printf("Horizontal axis: Offset of first varying captured.\n");