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
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
24 * Nicolai Hähnle <nhaehnle@gmail.com>
30 * Test that out-of-bound writes to uniform locations are caught properly.
37 #include "piglit-util.h"
38 #include "piglit-framework.h"
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
) {
54 fprintf(stderr
, "Expected OpenGL error 0x%04x, got 0x%04x\nat: ", expect
, error
);
57 vfprintf(stderr
, where
, va
);
59 fprintf(stderr
, "\n");
61 piglit_report_result(PIGLIT_FAILURE
);
65 static GLuint
compile_shader(GLenum shaderType
, const char * text
)
70 shader
= glCreateShaderObjectARB(shaderType
);
71 glShaderSourceARB(shader
, 1, (const GLchar
**)&text
, NULL
);
72 glCompileShaderARB(shader
);
74 glGetObjectParameterivARB(shader
, GL_OBJECT_COMPILE_STATUS_ARB
, &status
);
78 glGetInfoLogARB(shader
, 1000, &len
, log
);
79 fprintf(stderr
, "Error: problem compiling shader: %s\n", log
);
80 piglit_report_result(PIGLIT_FAILURE
);
85 static GLuint
link_program(GLuint vs
, GLuint fs
)
90 program
= glCreateProgramObjectARB();
92 glAttachObjectARB(program
, vs
);
94 glAttachObjectARB(program
, fs
);
96 glLinkProgramARB(program
);
97 glGetObjectParameterivARB(program
, GL_OBJECT_LINK_STATUS_ARB
, &status
);
101 glGetInfoLogARB(program
, 1000, &len
, log
);
102 fprintf(stderr
, "Error: problem linking program: %s\n", log
);
103 piglit_report_result(PIGLIT_FAILURE
);
109 static const GLfloat lots_of_zeros
[16*1024] = { 0.0f
, };
111 static const char vs_vector_template
[] =
117 " v = a + b[3] + c[0] + c[1] + c[2] + c[3];\n"
118 " gl_Position = vec4(0,0,0,1);\n"
121 static const char fs_vector_template
[] =
124 " gl_FragColor = vec4(v%s);\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
)];
134 GLint loc_a
, loc_b
, loc_c
;
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
,
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
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
[] =
213 "uniform mat4 b[4];\n"
214 "uniform mat4 c[4];\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"
222 static const char fs_matrix_template
[] =
225 " gl_FragColor = v;\n"
229 static void test_matrix(void)
233 GLint loc_a
, loc_b
, loc_c
;
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
);
298 piglit_ortho_projection(piglit_width
, piglit_height
, GL_FALSE
);
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
;
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
);