glsl-1.10/built-in-uniform-state: don't test Infs due to undefined behavior
[piglit.git] / tests / spec / glsl-1.10 / execution / built-in-uniform-state.c
blob7eb4f9911ebc6fcd59627693db9fff4867662981
1 /*
2 * Copyright © 2017 Fabian Bieler
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 built-in-uniform-state.c: Access uniform state in GLSL
27 * Set uniform state with the OpenGL API and access it in GLSL shaders.
30 #include "piglit-util-gl.h"
32 PIGLIT_GL_TEST_CONFIG_BEGIN
34 config.supports_gl_compat_version = 20;
35 config.window_visual = PIGLIT_GL_VISUAL_RGB;
36 config.khr_no_error_support = PIGLIT_NO_ERRORS;
38 PIGLIT_GL_TEST_CONFIG_END
40 #ifdef _WIN32
41 #define SRAND(x) srand(x)
42 #define DRAND() ((float)rand() / RAND_MAX)
43 #else
44 #define SRAND(x) srand48(x)
45 #define DRAND() drand48()
46 #endif
48 static const char *vs_text =
49 "void main() {\n"
50 " gl_Position = gl_Vertex;\n"
51 "}\n";
52 static const char *fs_float =
53 "void main() {\n"
54 " float epsilon = 1.0 / 256.0;\n"
55 " vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
56 " vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
57 " float a = %s;\n"
58 " float b = %f;\n"
59 " gl_FragColor = abs(a - b) < epsilon ? green : red;\n"
60 "}\n";
61 static const char *fs_vec3 =
62 "void main() {\n"
63 " vec3 epsilon = vec3(1.0 / 256.0);\n"
64 " vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
65 " vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
66 " vec3 a = %s;\n"
67 " vec3 b = vec3(%f, %f, %f);\n"
68 " gl_FragColor = all(lessThan(abs(a - b), epsilon)) ? green : red;\n"
69 "}\n";
70 static const char *fs_vec4 =
71 "void main() {\n"
72 " vec4 epsilon = vec4(1.0 / 256.0);\n"
73 " vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
74 " vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
75 " vec4 a = %s;\n"
76 " vec4 b = vec4(%f, %f, %f, %f);\n"
77 " gl_FragColor = all(lessThan(abs(a - b), epsilon)) ? green : red;\n"
78 "}\n";
80 /**
81 * Check that the built-in shader uniform \name of type \type is equal to \val
83 * Since we also test for derived state involving floating point computation
84 * don't test for strict equality but rather only check if the uniform's
85 * components are within and espilon of their expected values.
87 static bool
88 check_shader_builtin_(const GLenum type, const float *val, const char *name)
90 char *fs_text;
91 const float green[3] = {0.0, 1.0, 0.0};
93 switch (type) {
94 case GL_FLOAT:
95 asprintf(&fs_text, fs_float, name, *val);
96 break;
97 case GL_FLOAT_VEC3:
98 asprintf(&fs_text, fs_vec3, name, val[0], val[1], val[2]);
99 break;
100 case GL_FLOAT_VEC4:
101 asprintf(&fs_text, fs_vec4, name, val[0], val[1], val[2],
102 val[3]);
103 break;
104 default:
105 assert(0);
108 const GLuint program = piglit_build_simple_program(vs_text, fs_text);
109 free(fs_text);
110 glUseProgram(program);
111 glDeleteProgram(program);
112 glClear(GL_COLOR_BUFFER_BIT);
113 piglit_draw_rect(-1, -1, 2, 2);
115 if (piglit_probe_pixel_rgb_silent(piglit_width / 2, piglit_height / 2,
116 green, NULL))
117 return true;
118 printf("Failed uniform: '%s'.\n", name);
119 return false;
123 * printf-like version of function above.
125 static bool
126 check_shader_builtin(const GLenum type, const float *val, const char *format,
127 ...) PRINTFLIKE(3, 4);
128 static bool
129 check_shader_builtin(const GLenum type, const float *val, const char *format,
130 ...)
132 char *name;
133 va_list ap;
135 va_start(ap, format);
136 vasprintf(&name, format, ap);
137 va_end(ap);
139 const bool r = check_shader_builtin_(type, val, name);
140 free(name);
141 return r;
144 static void
145 normalize(float *v)
147 const float norm = sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
148 for (int i = 0; i < 3; ++i)
149 v[i] /= norm;
152 static void
153 random_vec4(float *v)
155 for (int i = 0; i < 4; ++i)
156 v[i] = DRAND();
160 * Get name fragment used in GLSL for GLenum \pname.
162 static const char *
163 enum2glsl(const GLenum pname)
165 switch (pname) {
166 case GL_EMISSION:
167 return "emission";
168 case GL_AMBIENT:
169 return "ambient";
170 case GL_DIFFUSE:
171 return "diffuse";
172 case GL_SPECULAR:
173 return "specular";
174 case GL_POSITION:
175 return "position";
176 case GL_SPOT_EXPONENT:
177 return "spotExponent";
178 case GL_SPOT_CUTOFF:
179 return "spotCutoff";
180 case GL_CONSTANT_ATTENUATION:
181 return "constantAttenuation";
182 case GL_LINEAR_ATTENUATION:
183 return "linearAttenuation";
184 case GL_QUADRATIC_ATTENUATION:
185 return "quadraticAttenuation";
186 case GL_S:
187 return "S";
188 case GL_T:
189 return "T";
190 case GL_R:
191 return "R";
192 case GL_Q:
193 return "Q";
194 default:
195 assert(!"unexpected pname");
196 return "";
200 enum piglit_result
201 piglit_display(void)
203 bool pass = true;
204 float val[4];
206 /* Depth range */
207 val[0] = DRAND();
208 val[1] = DRAND();
209 const float diff = val[1] - val[0];
210 glDepthRangef(val[0], val[1]);
211 pass = check_shader_builtin(GL_FLOAT, val, "gl_DepthRange.near") &&
212 pass;
213 pass = check_shader_builtin(GL_FLOAT, &val[1], "gl_DepthRange.far") &&
214 pass;
215 pass = check_shader_builtin(GL_FLOAT, &diff, "gl_DepthRange.diff") &&
216 pass;
218 /* Clip planes */
219 int max_clip_planes;
220 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
221 for (int cp = 0; cp < max_clip_planes; ++cp) {
222 double vald[4];
223 for (int c = 0; c < 4; ++c)
224 vald[c] = val[c] = DRAND();
225 glClipPlane(GL_CLIP_PLANE0 + cp, vald);
226 pass = check_shader_builtin(GL_FLOAT_VEC4, val,
227 "gl_ClipPlane[%d]", cp) &&
228 pass;
231 /* Point Size */
232 val[0] = DRAND();
233 glPointSize(val[0]);
234 pass = check_shader_builtin(GL_FLOAT, val, "gl_Point.size") && pass;
236 val[0] = DRAND();
237 glPointParameterf(GL_POINT_SIZE_MIN, val[0]);
238 pass = check_shader_builtin(GL_FLOAT, val, "gl_Point.sizeMin") &&
239 pass;
241 val[0] = DRAND();
242 glPointParameterf(GL_POINT_SIZE_MAX, val[0]);
243 pass = check_shader_builtin(GL_FLOAT, val, "gl_Point.sizeMax") &&
244 pass;
246 val[0] = DRAND();
247 glPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE, val[0]);
248 pass = check_shader_builtin(GL_FLOAT, val,
249 "gl_Point.fadeThresholdSize") &&
250 pass;
252 val[0] = DRAND();
253 val[1] = DRAND();
254 val[2] = DRAND();
255 glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, val);
256 pass = check_shader_builtin(GL_FLOAT, &val[0],
257 "gl_Point.distanceConstantAttenuation") &&
258 pass;
259 pass = check_shader_builtin(GL_FLOAT, &val[1],
260 "gl_Point.distanceLinearAttenuation") &&
261 pass;
262 pass = check_shader_builtin(
263 GL_FLOAT, &val[2],
264 "gl_Point.distanceQuadraticAttenuation") &&
265 pass;
267 /* Material State */
268 for (int s = 0; s < 2; ++s) {
269 for (int p = 0; p < 4; ++p) {
270 const GLenum pname[] = {GL_EMISSION, GL_AMBIENT,
271 GL_DIFFUSE, GL_SPECULAR};
273 random_vec4(val);
274 glMaterialfv(GL_FRONT + s, pname[p], val);
275 pass = check_shader_builtin(GL_FLOAT_VEC4, val,
276 "gl_%sMaterial.%s",
277 s ? "Back" : "Front",
278 enum2glsl(pname[p])) &&
279 pass;
282 val[0] = DRAND();
283 glMaterialf(GL_FRONT + s, GL_SHININESS, val[0]);
284 pass = check_shader_builtin(GL_FLOAT, val,
285 "gl_%sMaterial.shininess",
286 s ? "Back" : "Front") &&
287 pass;
290 /* Light State */
291 int max_lights;
292 glGetIntegerv(GL_MAX_LIGHTS, &max_lights);
293 for (int l = 0; l < max_lights; ++l) {
294 for (int p = 0; p < 4; ++p) {
295 const GLenum pname[] = {GL_AMBIENT, GL_DIFFUSE,
296 GL_SPECULAR, GL_POSITION};
297 random_vec4(val);
298 glLightfv(GL_LIGHT0 + l, pname[p], val);
299 pass = check_shader_builtin(GL_FLOAT_VEC4, val,
300 "gl_LightSource[%d].%s",
301 l, enum2glsl(pname[p])) &&
302 pass;
305 random_vec4(val);
306 glLightfv(GL_LIGHT0 + l, GL_SPOT_DIRECTION, val);
307 pass = check_shader_builtin(
308 GL_FLOAT_VEC3, val,
309 "gl_LightSource[%d].spotDirection", l) &&
310 pass;
312 for (int p = 0; p < 5; ++p) {
313 const GLenum pname[] = {GL_SPOT_EXPONENT,
314 GL_SPOT_CUTOFF,
315 GL_CONSTANT_ATTENUATION,
316 GL_LINEAR_ATTENUATION,
317 GL_QUADRATIC_ATTENUATION};
318 val[0] = DRAND();
319 glLightf(GL_LIGHT0 + l, pname[p], val[0]);
320 pass = check_shader_builtin(GL_FLOAT, val,
321 "gl_LightSource[%d].%s",
322 l, enum2glsl(pname[p])) &&
323 pass;
326 val[0] = DRAND() * 90;
327 glLightf(GL_LIGHT0 + l, GL_SPOT_CUTOFF, val[0]);
328 const float cos_cutoff = cosf(val[0] / 180 * M_PI);
329 pass = check_shader_builtin(
330 GL_FLOAT, &cos_cutoff,
331 "gl_LightSource[%d].spotCosCutoff", l) &&
332 pass;
334 for (int c = 0; c < 3; ++c)
335 val[c] = DRAND();
336 val[3] = 1;
337 glLightfv(GL_LIGHT0 + l, GL_POSITION, val);
338 normalize(val);
339 val[2] += 1;
340 normalize(val);
341 pass = check_shader_builtin(GL_FLOAT_VEC4, val,
342 "gl_LightSource[%d].halfVector",
343 l) &&
344 pass;
347 random_vec4(val);
348 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, val);
349 pass = check_shader_builtin(GL_FLOAT_VEC4, val,
350 "gl_LightModel.ambient") &&
351 pass;
353 /* Derived state from products of light and material. */
354 for (int s = 0; s < 2; ++s) {
355 float scene_color[4];
357 for (int c = 0; c < 4; ++c)
358 scene_color[c] = val[c] = DRAND();
359 glMaterialfv(GL_FRONT + s, GL_AMBIENT, val);
360 for (int c = 0; c < 4; ++c)
361 scene_color[c] *= val[c] = DRAND();
362 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, val);
363 for (int c = 0; c < 4; ++c)
364 scene_color[c] += val[c] = DRAND();
365 glMaterialfv(GL_FRONT + s, GL_EMISSION, val);
367 /* Page 63 (77 of the PDF) of the OpenGL 2.0 spec says:
369 * "The value of A produced by lighting is the alpha
370 * value associated with d_{cm}."
372 * I'm not sure if this applies to the scene color, but both
373 * Mesa and the NVIDIA driver do this.
375 random_vec4(val);
376 glMaterialfv(GL_FRONT + s, GL_DIFFUSE, val);
377 scene_color[3] = val[3];
379 pass = check_shader_builtin(
380 GL_FLOAT_VEC4, scene_color,
381 s ? "gl_BackLightModelProduct.sceneColor"
382 : "gl_FrontLightModelProduct.sceneColor") &&
383 pass;
386 for (int s = 0; s < 2; ++s) {
387 for (int l = 0; l < max_lights; ++l) {
388 const GLenum pname[] = {GL_AMBIENT, GL_DIFFUSE,
389 GL_SPECULAR};
390 for (int p = 0; p < 3; ++p) {
391 float light_product[4];
392 for (int c = 0; c < 4; ++c)
393 light_product[c] = val[c] = DRAND();
394 glLightfv(GL_LIGHT0 + l, pname[p], val);
395 for (int c = 0; c < 4; ++c)
396 light_product[c] *= val[c] = DRAND();
397 glMaterialfv(GL_FRONT + s, pname[p], val);
398 /* XXX: I have no Idea where the spec says the
399 * alpha value of the light product is the
400 * material's alpha value, but both Mesa and
401 * the NVIDIA driver do this.
403 light_product[3] = val[3];
405 pass = check_shader_builtin(
406 GL_FLOAT_VEC4, light_product,
407 "gl_%sLightProduct[%d].%s",
408 s ? "Back" : "Front", l,
409 enum2glsl(pname[p])) &&
410 pass;
415 /* Texture Environment and Generation */
416 int max_tu;
417 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_tu);
418 int max_tiu;
419 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_tiu);
420 const int max_textures = MIN2(max_tu, max_tiu);
421 for (int t = 0; t < max_textures; ++t) {
422 glActiveTexture(GL_TEXTURE0 + t);
424 random_vec4(val);
425 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, val);
426 pass = check_shader_builtin(GL_FLOAT_VEC4, val,
427 "gl_TextureEnvColor[%d]", t) &&
428 pass;
431 int max_texture_coords;
432 glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);
433 for (int t = 0; t < max_texture_coords; ++t) {
434 const GLenum coord[] = {GL_S, GL_T, GL_R, GL_Q};
435 glActiveTexture(GL_TEXTURE0 + t);
437 for (int co = 0; co < 4; ++co) {
438 const GLenum plane[] = {GL_EYE_PLANE,
439 GL_OBJECT_PLANE};
440 const char *plane_name[] = {"Eye", "Object"};
441 for (int pl = 0; pl < 2; ++pl) {
442 random_vec4(val);
443 glTexGenfv(coord[co], plane[pl], val);
444 pass = check_shader_builtin(
445 GL_FLOAT_VEC4, val,
446 "gl_%sPlane%s[%d]",
447 plane_name[pl],
448 enum2glsl(coord[co]), t) &&
449 pass;
454 /* Fog */
455 random_vec4(val);
456 glFogfv(GL_FOG_COLOR, val);
457 pass = check_shader_builtin(GL_FLOAT_VEC4, val, "gl_Fog.color") &&
458 pass;
460 val[0] = DRAND();
462 /* Don't test infinity because shader comparisons with infinity are
463 * undefined.
465 float fog_scale;
466 do {
467 val[1] = DRAND();
468 val[2] = DRAND();
469 fog_scale = 1 / (val[2] - val[1]);
470 } while (isinf(fog_scale));
472 glFogf(GL_FOG_DENSITY, val[0]);
473 pass = check_shader_builtin(GL_FLOAT, val, "gl_Fog.density") && pass;
475 glFogf(GL_FOG_START, val[1]);
476 pass = check_shader_builtin(GL_FLOAT, &val[1], "gl_Fog.start") &&
477 pass;
479 glFogf(GL_FOG_END, val[2]);
480 pass = check_shader_builtin(GL_FLOAT, &val[2], "gl_Fog.end") && pass;
482 pass = check_shader_builtin(GL_FLOAT, &fog_scale, "gl_Fog.scale") &&
483 pass;
485 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
488 void
489 piglit_init(int argc, char **argv)
491 SRAND(17);