Add more structure constructor tests.
[piglit/hramrach.git] / tests / shaders / glsl-uniform-out-of-bounds.c
blobb4e861c505daaa732789008cdf347a58a0297ecd
1 /*
2 * Copyright (c) 2009 Nicolai Hähnle
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 * Nicolai Hähnle <nhaehnle@gmail.com>
28 /**
29 * \file
30 * Test that out-of-bound writes to uniform locations are caught properly.
33 #include <limits.h>
34 #include <stdarg.h>
35 #include <stdio.h>
37 #include "piglit-util.h"
38 #include "piglit-framework.h"
40 #ifndef APIENTRY
41 #define APIENTRY
42 #endif
44 int piglit_width = 100, piglit_height = 100;
45 int piglit_window_mode = GLUT_RGB;
48 static void expect_error(GLenum expect, const char * where, ...)
50 GLenum error = glGetError();
51 if (error != expect) {
52 va_list va;
54 fprintf(stderr, "Expected OpenGL error 0x%04x, got 0x%04x\nat: ", expect, error);
56 va_start(va, where);
57 vfprintf(stderr, where, va);
58 va_end(va);
59 fprintf(stderr, "\n");
61 piglit_report_result(PIGLIT_FAILURE);
65 static GLuint compile_shader(GLenum shaderType, const char * text)
67 GLuint shader;
68 GLint status;
70 shader = glCreateShaderObjectARB(shaderType);
71 glShaderSourceARB(shader, 1, (const GLchar **)&text, NULL);
72 glCompileShaderARB(shader);
74 glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
75 if (!status) {
76 GLchar log[1000];
77 GLsizei len;
78 glGetInfoLogARB(shader, 1000, &len, log);
79 fprintf(stderr, "Error: problem compiling shader: %s\n", log);
80 piglit_report_result(PIGLIT_FAILURE);
82 return shader;
85 static GLuint link_program(GLuint vs, GLuint fs)
87 GLuint program;
88 GLint status;
90 program = glCreateProgramObjectARB();
91 if (vs)
92 glAttachObjectARB(program, vs);
93 if (fs)
94 glAttachObjectARB(program, fs);
96 glLinkProgramARB(program);
97 glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &status);
98 if (!status) {
99 GLchar log[1000];
100 GLsizei len;
101 glGetInfoLogARB(program, 1000, &len, log);
102 fprintf(stderr, "Error: problem linking program: %s\n", log);
103 piglit_report_result(PIGLIT_FAILURE);
106 return program;
109 static const GLfloat lots_of_zeros[16*1024] = { 0.0f, };
111 static const char vs_vector_template[] =
112 "uniform %s a;\n"
113 "uniform %s b[4];\n"
114 "uniform %s c[4];\n"
115 "varying %s v;\n"
116 "void main() {\n"
117 " v = a + b[3] + c[0] + c[1] + c[2] + c[3];\n"
118 " gl_Position = vec4(0,0,0,1);\n"
119 "}\n";
121 static const char fs_vector_template[] =
122 "varying %s v;\n"
123 "void main() {\n"
124 " gl_FragColor = vec4(v%s);\n"
125 "}\n";
128 static void test_vector(const char *glsl_type, const char * suffix,
129 void (APIENTRY *uniform)(GLint, GLsizei, const GLfloat*))
131 char buffer[2*sizeof(vs_vector_template)];
132 GLuint vs, fs;
133 GLuint program;
134 GLint loc_a, loc_b, loc_c;
135 GLint loc_b2;
137 snprintf(buffer, sizeof(buffer), vs_vector_template,
138 glsl_type, glsl_type, glsl_type, glsl_type);
139 vs = compile_shader(GL_VERTEX_SHADER_ARB, buffer);
141 snprintf(buffer, sizeof(buffer), fs_vector_template,
142 glsl_type, suffix);
143 fs = compile_shader(GL_FRAGMENT_SHADER_ARB, buffer);
145 program = link_program(vs, fs);
147 glUseProgramObjectARB(program);
148 loc_a = glGetUniformLocationARB(program, "a");
149 loc_b = glGetUniformLocationARB(program, "b");
150 loc_c = glGetUniformLocationARB(program, "c");
151 loc_b2 = glGetUniformLocationARB(program, "b[2]");
152 printf("locations: a: %i b: %i c: %i b[2]: %i\n", loc_a, loc_b, loc_c, loc_b);
154 expect_error(GL_NO_ERROR, "Type %s: Sanity check", glsl_type);
155 uniform(loc_a, 0, lots_of_zeros);
156 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to a", glsl_type);
157 uniform(loc_a, 1, lots_of_zeros);
158 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to a", glsl_type);
159 uniform(loc_a, 2, lots_of_zeros);
160 expect_error(GL_INVALID_OPERATION, "Type %s: Write count = 2 to a", glsl_type);
161 uniform(loc_a, 1024, lots_of_zeros);
162 expect_error(GL_INVALID_OPERATION, "Type %s: Write count = 1024 to a", glsl_type);
164 uniform(loc_b, 0, lots_of_zeros);
165 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to b", glsl_type);
166 uniform(loc_b, 1, lots_of_zeros);
167 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to b", glsl_type);
168 uniform(loc_b, 4, lots_of_zeros);
169 expect_error(GL_NO_ERROR, "Type %s: Write count = 4 to b", glsl_type);
171 /* Note: The following are out of bound for the array,
172 * but the spec situation is a bit unclear as to whether errors
173 * should be generated.
175 * Issue #32 of the ARB_shader_objects spec suggests errors
176 * should be generated when writing out-of-bounds on arrays,
177 * but this is not reflected in the OpenGL spec.
179 * The main point of these tests is to make sure the driver
180 * does not introduce memory errors by accessing internal arrays
181 * out of bounds.
183 uniform(loc_b, 5, lots_of_zeros);
184 (void) glGetError(); /* Eat generated error, if any */
186 uniform(loc_c, 0, lots_of_zeros);
187 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to c", glsl_type);
188 uniform(loc_c, 1, lots_of_zeros);
189 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to c", glsl_type);
190 uniform(loc_c, 4, lots_of_zeros);
191 expect_error(GL_NO_ERROR, "Type %s: Write count = 4 to c", glsl_type);
193 /* Out of bounds; see comment above */
194 uniform(loc_c, 5, lots_of_zeros);
195 (void) glGetError(); /* Eat generated error, if any */
197 uniform(loc_b2, 0, lots_of_zeros);
198 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to b[2]", glsl_type);
199 uniform(loc_b2, 2, lots_of_zeros);
200 expect_error(GL_NO_ERROR, "Type %s: Write count = 2 to b[2]", glsl_type);
202 /* Out of bounds; see comment above */
203 uniform(loc_b2, 1024, lots_of_zeros);
204 (void) glGetError(); /* Eat generated error, if any */
206 glDeleteObjectARB(fs);
207 glDeleteObjectARB(vs);
208 glDeleteObjectARB(program);
211 static const char vs_matrix_template[] =
212 "uniform mat4 a;\n"
213 "uniform mat4 b[4];\n"
214 "uniform mat4 c[4];\n"
215 "varying vec4 v;\n"
216 "void main() {\n"
217 " mat4 m = a + b[3] + c[0] + c[1] + c[2] + c[3];\n"
218 " v = m * vec4(1.0, 1.0, 1.0, 1.0);\n"
219 " gl_Position = vec4(0,0,0,1);\n"
220 "}\n";
222 static const char fs_matrix_template[] =
223 "varying vec4 v;\n"
224 "void main() {\n"
225 " gl_FragColor = v;\n"
226 "}\n";
229 static void test_matrix(void)
231 GLuint vs, fs;
232 GLuint program;
233 GLint loc_a, loc_b, loc_c;
234 GLint loc_b2;
235 const char * glsl_type = "mat4";
237 vs = compile_shader(GL_VERTEX_SHADER_ARB, vs_matrix_template);
238 fs = compile_shader(GL_FRAGMENT_SHADER_ARB, fs_matrix_template);
239 program = link_program(vs, fs);
241 glUseProgramObjectARB(program);
242 loc_a = glGetUniformLocationARB(program, "a");
243 loc_b = glGetUniformLocationARB(program, "b");
244 loc_c = glGetUniformLocationARB(program, "c");
245 loc_b2 = glGetUniformLocationARB(program, "b[2]");
246 printf("locations: a: %i b: %i c: %i b[2]: %i\n", loc_a, loc_b, loc_c, loc_b);
248 expect_error(GL_NO_ERROR, "Type %s: Sanity check", glsl_type);
250 glUniformMatrix4fvARB(loc_b, 0, GL_FALSE, lots_of_zeros);
251 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to b", glsl_type);
252 glUniformMatrix4fvARB(loc_b, 1, GL_FALSE, lots_of_zeros);
253 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to b", glsl_type);
254 glUniformMatrix4fvARB(loc_b, 4, GL_FALSE, lots_of_zeros);
255 expect_error(GL_NO_ERROR, "Type %s: Write count = 4 to b", glsl_type);
257 /* Out of bounds; see comment above */
258 glUniformMatrix4fvARB(loc_b, 5, GL_FALSE, lots_of_zeros);
259 (void) glGetError(); /* Eat generated error, if any */
261 glUniformMatrix4fvARB(loc_c, 0, GL_FALSE, lots_of_zeros);
262 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to c", glsl_type);
263 glUniformMatrix4fvARB(loc_c, 1, GL_FALSE, lots_of_zeros);
264 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to c", glsl_type);
265 glUniformMatrix4fvARB(loc_c, 4, GL_FALSE, lots_of_zeros);
266 expect_error(GL_NO_ERROR, "Type %s: Write count = 4 to c", glsl_type);
268 /* Out of bounds; see comment above */
269 glUniformMatrix4fvARB(loc_c, 5, GL_FALSE, lots_of_zeros);
270 (void) glGetError(); /* Eat generated error, if any */
272 glUniformMatrix4fvARB(loc_b2, 0, GL_FALSE, lots_of_zeros);
273 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to b[2]", glsl_type);
274 glUniformMatrix4fvARB(loc_b2, 2, GL_FALSE, lots_of_zeros);
275 expect_error(GL_NO_ERROR, "Type %s: Write count = 2 to b[2]", glsl_type);
277 /* Out of bounds; see comment above */
278 glUniformMatrix4fvARB(loc_b2, INT_MAX, GL_FALSE, lots_of_zeros);
279 (void) glGetError(); /* Eat generated error, if any */
281 glUniformMatrix4fvARB(loc_a, 0, GL_FALSE, lots_of_zeros);
282 expect_error(GL_NO_ERROR, "Type %s: Write count = 0 to a", glsl_type);
283 glUniformMatrix4fvARB(loc_a, 1, GL_FALSE, lots_of_zeros);
284 expect_error(GL_NO_ERROR, "Type %s: Write count = 1 to a", glsl_type);
285 glUniformMatrix4fvARB(loc_a, 2, GL_FALSE, lots_of_zeros);
286 expect_error(GL_INVALID_OPERATION, "Type %s: Write count = 2 to a", glsl_type);
287 glUniformMatrix4fvARB(loc_a, INT_MAX, GL_FALSE, lots_of_zeros);
288 expect_error(GL_INVALID_OPERATION, "Type %s: Write count = INT_MAX to a", glsl_type);
290 glDeleteObjectARB(fs);
291 glDeleteObjectARB(vs);
292 glDeleteObjectARB(program);
295 enum piglit_result
296 piglit_display(void)
298 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
300 test_matrix();
302 test_vector("float", ", 0, 0, 0", glUniform1fvARB);
303 test_vector("vec2", ", 0, 0", glUniform2fvARB);
304 test_vector("vec3", ", 0", glUniform3fvARB);
305 test_vector("vec4", "", glUniform4fvARB);
307 return PIGLIT_SUCCESS;
310 void
311 piglit_init(int argc, char **argv)
313 if (!GLEW_ARB_shader_objects || !GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) {
314 printf("Requires ARB_shader_objects and ARB_{vertex,fragment}_shader\n");
315 piglit_report_result(PIGLIT_SKIP);