cmake: move defaults into the per-platform section
[piglit.git] / tests / shaders / glsl-max-varyings.c
blob75146ba530229e1c8ddc77ab12943f5d3755349f
1 /*
2 * Copyright © 2010 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.
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
28 /** @file glsl-max-varyings.c
30 * Tests whether each varying can be used at all numbers of varyings up to
31 * GL_MAX_VARYING_FLOATS / 4.
34 #include "piglit-util-gl.h"
36 #define MAX_VARYING 256
38 /* 1x1 rectangles with 1 pixels of pad. Deal with up to 256 varyings. */
40 PIGLIT_GL_TEST_CONFIG_BEGIN
42 config.supports_gl_compat_version = 10;
44 config.window_width = MAX_VARYING;
45 config.window_height = MAX_VARYING;
46 config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
48 PIGLIT_GL_TEST_CONFIG_END
50 static bool exceed_limits = false;
51 static int max_varyings;
53 /* Generate a VS that writes to num_varyings vec4s, and put
54 * interesting data in data_varying with 0.0 everywhere else.
56 static GLint get_vs(int num_varyings)
58 GLuint shader;
59 unsigned i;
60 char *code = malloc(4096);
61 char temp[2048];
63 code[0] = 0;
64 for (i = 0; i < num_varyings; i++) {
65 sprintf(temp, "varying vec4 v%d;\n", i);
66 strcat(code, temp);
69 sprintf(temp,
70 "attribute vec4 vertex;\n"
71 "attribute vec4 green;\n"
72 "attribute vec4 red;\n"
73 "uniform int data_varying;\n"
74 "void main()\n"
75 "{\n"
76 " gl_Position = (gl_ModelViewProjectionMatrix * \n"
77 " vertex);\n");
78 strcat(code, temp);
80 for (i = 0; i < num_varyings; i++) {
81 sprintf(temp, " v%d = (data_varying == %d) ? green : red;\n", i, i);
82 strcat(code, temp);
85 sprintf(temp,
86 "}\n"
88 strcat(code, temp);
90 shader = piglit_compile_shader_text(GL_VERTEX_SHADER, code);
91 /* printf("%s\n", code); */
93 free(code);
94 return shader;
97 /* Generate a FS that does operations on num_varyings, yet makes only
98 * data_varying contribute to the output.
100 * We could make a single FS per num_varyings that did this by using a
101 * uniform for data_varying and some multiplication by comparisons
102 * (see glsl-routing for an example), but since we're linking a new
103 * shader each time anyway, this produces a simpler FS to read and
104 * verify.
106 static GLint get_fs(int num_varyings)
108 GLuint shader;
109 unsigned i;
110 char *code = malloc(8192);
111 char temp[2048];
113 code[0] = 0;
114 for (i = 0; i < num_varyings; i++) {
115 sprintf(temp, "varying vec4 v%d;\n", i);
116 strcat(code, temp);
119 sprintf(temp,
120 "uniform float contribution[%d];\n"
121 "void main()\n"
122 "{\n"
123 " vec4 val = vec4(0.0);\n",
124 num_varyings);
125 strcat(code, temp);
127 for (i = 0; i < num_varyings; i++) {
128 sprintf(temp, " val += contribution[%d] * v%d;\n", i, i);
129 strcat(code, temp);
132 sprintf(temp,
133 " gl_FragColor = val;\n"
134 "}\n"
136 strcat(code, temp);
138 /* printf("%s\n", code); */
139 shader = piglit_compile_shader_text(GL_FRAGMENT_SHADER, code);
141 free(code);
142 return shader;
145 static bool
146 draw(int num_varyings)
148 int data_varying;
149 float vertex[4][4] = { {0.0, 0.0, 0.0, 1.0},
150 {0.0, 0.0, 0.0, 1.0},
151 {0.0, 0.0, 0.0, 1.0},
152 {0.0, 0.0, 0.0, 1.0} };
153 float green[4][4] = { {0.0, 1.0, 0.0, 0.0},
154 {0.0, 1.0, 0.0, 0.0},
155 {0.0, 1.0, 0.0, 0.0},
156 {0.0, 1.0, 0.0, 0.0} };
157 float red[4][4] = { {1.0, 0.0, 0.0, 0.0},
158 {1.0, 0.0, 0.0, 0.0},
159 {1.0, 0.0, 0.0, 0.0},
160 {1.0, 0.0, 0.0, 0.0} };
162 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float),
163 vertex);
164 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float),
165 green);
166 glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float),
167 red);
168 glEnableVertexAttribArray(0);
169 glEnableVertexAttribArray(1);
170 glEnableVertexAttribArray(2);
172 GLuint vs = get_vs(num_varyings);
173 GLuint fs = get_fs(num_varyings);
174 GLuint prog = glCreateProgram();
175 glAttachShader(prog, vs);
176 glAttachShader(prog, fs);
178 glBindAttribLocation(prog, 0, "vertex");
179 glBindAttribLocation(prog, 1, "green");
180 glBindAttribLocation(prog, 2, "red");
182 glLinkProgram(prog);
183 if (!piglit_link_check_status_quiet(prog)) {
184 if (num_varyings > max_varyings) {
185 printf("Failed to link with %d out of %d "
186 "varyings used\n",
187 num_varyings, max_varyings);
188 return false;
189 } else {
190 piglit_report_result(PIGLIT_FAIL);
194 int data_varying_loc = glGetUniformLocation(prog, "data_varying");
195 int contribution_loc = glGetUniformLocation(prog, "contribution");
197 glUseProgram(prog);
199 for (data_varying = 0; data_varying < num_varyings; data_varying++) {
200 float x, y;
202 glUniform1i(data_varying_loc, data_varying);
203 glUniform1f(contribution_loc + data_varying, 1.0);
204 if (data_varying > 0)
205 glUniform1f(contribution_loc + data_varying - 1, 0.0);
207 x = data_varying;
208 y = num_varyings - 1;
209 vertex[0][0] = x;
210 vertex[0][1] = y;
211 vertex[1][0] = x + 1;
212 vertex[1][1] = y;
213 vertex[2][0] = x;
214 vertex[2][1] = y + 1;
215 vertex[3][0] = x + 1;
216 vertex[3][1] = y + 1;
217 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
220 glDeleteShader(vs);
221 glDeleteShader(fs);
222 glDeleteProgram(prog);
224 return true;
227 enum piglit_result
228 piglit_display(void)
230 GLint max_components;
231 int test_varyings, row, col;
232 GLboolean pass = GL_TRUE, warned = GL_FALSE;
233 bool drew[MAX_VARYING];
234 float readback_buffer[MAX_VARYING * MAX_VARYING * 3] = {0};
236 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
238 glGetIntegerv(GL_MAX_VARYING_FLOATS, &max_components);
239 max_varyings = max_components / 4;
241 printf("GL_MAX_VARYING_FLOATS = %i\n", max_components);
243 test_varyings = max_varyings;
244 if (exceed_limits)
245 test_varyings++;
246 if (test_varyings > MAX_VARYING) {
247 printf("test not designed to handle >%d varying vec4s.\n"
248 "(implementation reports %d components)\n",
249 MAX_VARYING, max_varyings);
250 test_varyings = MAX_VARYING;
251 warned = GL_TRUE;
254 glClearColor(0.5, 0.5, 0.5, 0.5);
255 glClear(GL_COLOR_BUFFER_BIT);
257 for (row = 0; row < test_varyings; row++) {
258 drew[row] = draw(row + 1);
261 glReadPixels(0, 0, test_varyings, test_varyings, GL_RGB, GL_FLOAT, readback_buffer);
263 for (row = 0; row < test_varyings; row++) {
264 if (!drew[row])
265 continue;
267 for (col = 0; col <= row; col++) {
268 GLboolean ok;
269 float green[3] = {0.0, 1.0, 0.0};
270 int pixel_id = 3 * (row * test_varyings + col);
272 ok = readback_buffer[pixel_id + 0] == green[0] &&
273 readback_buffer[pixel_id + 1] == green[1] &&
274 readback_buffer[pixel_id + 2] == green[2];
276 if (!ok) {
277 printf(" Failure with %d vec4 varyings used "
278 "in varying index %d\n",
279 row + 1, col);
280 printf(" Expected %f %f %f\n Got %f %f %f\n\n",
281 green[0], green[1], green[2],
282 readback_buffer[pixel_id + 0],
283 readback_buffer[pixel_id + 1],
284 readback_buffer[pixel_id + 2]);
285 pass = GL_FALSE;
286 break;
291 piglit_present_results();
293 if (!pass)
294 return PIGLIT_FAIL;
295 if (warned)
296 return PIGLIT_WARN;
297 else
298 return PIGLIT_PASS;
301 void piglit_init(int argc, char **argv)
303 int i;
305 piglit_require_gl_version(20);
307 for (i = 0; i < argc; i++) {
308 if (strcmp(argv[i], "--exceed-limits") == 0)
309 exceed_limits = true;
312 printf("Vertical axis: Increasing numbers of varyings.\n");
313 printf("Horizontal axis: Which of the varyings contains the color.\n");