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-gl.h"
39 PIGLIT_GL_TEST_CONFIG_BEGIN
41 config
.supports_gl_compat_version
= 10;
43 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
;
45 PIGLIT_GL_TEST_CONFIG_END
47 static void expect_error(GLenum expect
, const char * where
, ...)
49 GLenum error
= glGetError();
50 if (error
!= expect
) {
53 fprintf(stderr
, "Expected OpenGL error 0x%04x, got 0x%04x\nat: ", expect
, error
);
56 vfprintf(stderr
, where
, va
);
58 fprintf(stderr
, "\n");
60 piglit_report_result(PIGLIT_FAIL
);
64 static GLuint
compile_shader(GLenum shaderType
, const char * text
)
69 shader
= glCreateShaderObjectARB(shaderType
);
70 glShaderSourceARB(shader
, 1, (const GLchar
**)&text
, NULL
);
71 glCompileShaderARB(shader
);
73 glGetObjectParameterivARB(shader
, GL_OBJECT_COMPILE_STATUS_ARB
, &status
);
77 glGetInfoLogARB(shader
, 1000, &len
, log
);
78 fprintf(stderr
, "Error: problem compiling shader: %s\n", log
);
79 piglit_report_result(PIGLIT_FAIL
);
84 static GLuint
link_program(GLuint vs
, GLuint fs
)
89 program
= glCreateProgramObjectARB();
91 glAttachObjectARB(program
, vs
);
93 glAttachObjectARB(program
, fs
);
95 glLinkProgramARB(program
);
96 glGetObjectParameterivARB(program
, GL_OBJECT_LINK_STATUS_ARB
, &status
);
100 glGetInfoLogARB(program
, 1000, &len
, log
);
101 fprintf(stderr
, "Error: problem linking program: %s\n", log
);
102 piglit_report_result(PIGLIT_FAIL
);
108 static const GLfloat lots_of_zeros
[16*1024] = { 0.0f
, };
110 static const char vs_vector_template
[] =
116 " v = a + b[3] + c[0] + c[1] + c[2] + c[3];\n"
117 " gl_Position = vec4(0,0,0,1);\n"
120 static const char fs_vector_template
[] =
123 " gl_FragColor = vec4(v%s);\n"
127 static void test_vector(const char *glsl_type
, const char * suffix
,
128 void (GLAPIENTRY
*uniform
)(GLint
, GLsizei
, const GLfloat
*))
130 char buffer
[2*sizeof(vs_vector_template
)];
133 GLint loc_a
, loc_b
, loc_c
;
136 snprintf(buffer
, sizeof(buffer
), vs_vector_template
,
137 glsl_type
, glsl_type
, glsl_type
, glsl_type
);
138 vs
= compile_shader(GL_VERTEX_SHADER_ARB
, buffer
);
140 snprintf(buffer
, sizeof(buffer
), fs_vector_template
,
142 fs
= compile_shader(GL_FRAGMENT_SHADER_ARB
, buffer
);
144 program
= link_program(vs
, fs
);
146 glUseProgramObjectARB(program
);
147 loc_a
= glGetUniformLocationARB(program
, "a");
148 loc_b
= glGetUniformLocationARB(program
, "b");
149 loc_c
= glGetUniformLocationARB(program
, "c");
150 loc_b2
= glGetUniformLocationARB(program
, "b[2]");
151 printf("locations: a: %i b: %i c: %i b[2]: %i\n", loc_a
, loc_b
, loc_c
, loc_b
);
153 expect_error(GL_NO_ERROR
, "Type %s: Sanity check", glsl_type
);
154 uniform(loc_a
, 0, lots_of_zeros
);
155 expect_error(GL_NO_ERROR
, "Type %s: Write count = 0 to a", glsl_type
);
156 uniform(loc_a
, 1, lots_of_zeros
);
157 expect_error(GL_NO_ERROR
, "Type %s: Write count = 1 to a", glsl_type
);
158 uniform(loc_a
, 2, lots_of_zeros
);
159 expect_error(GL_INVALID_OPERATION
, "Type %s: Write count = 2 to a", glsl_type
);
160 uniform(loc_a
, 1024, lots_of_zeros
);
161 expect_error(GL_INVALID_OPERATION
, "Type %s: Write count = 1024 to a", glsl_type
);
163 uniform(loc_b
, 0, lots_of_zeros
);
164 expect_error(GL_NO_ERROR
, "Type %s: Write count = 0 to b", glsl_type
);
165 uniform(loc_b
, 1, lots_of_zeros
);
166 expect_error(GL_NO_ERROR
, "Type %s: Write count = 1 to b", glsl_type
);
167 uniform(loc_b
, 4, lots_of_zeros
);
168 expect_error(GL_NO_ERROR
, "Type %s: Write count = 4 to b", glsl_type
);
170 /* Note: The following are out of bound for the array,
171 * but the spec situation is a bit unclear as to whether errors
172 * should be generated.
174 * Issue #32 of the ARB_shader_objects spec suggests errors
175 * should be generated when writing out-of-bounds on arrays,
176 * but this is not reflected in the OpenGL spec.
178 * The main point of these tests is to make sure the driver
179 * does not introduce memory errors by accessing internal arrays
182 uniform(loc_b
, 5, lots_of_zeros
);
183 (void) glGetError(); /* Eat generated error, if any */
185 uniform(loc_c
, 0, lots_of_zeros
);
186 expect_error(GL_NO_ERROR
, "Type %s: Write count = 0 to c", glsl_type
);
187 uniform(loc_c
, 1, lots_of_zeros
);
188 expect_error(GL_NO_ERROR
, "Type %s: Write count = 1 to c", glsl_type
);
189 uniform(loc_c
, 4, lots_of_zeros
);
190 expect_error(GL_NO_ERROR
, "Type %s: Write count = 4 to c", glsl_type
);
192 /* Out of bounds; see comment above */
193 uniform(loc_c
, 5, lots_of_zeros
);
194 (void) glGetError(); /* Eat generated error, if any */
196 uniform(loc_b2
, 0, lots_of_zeros
);
197 expect_error(GL_NO_ERROR
, "Type %s: Write count = 0 to b[2]", glsl_type
);
198 uniform(loc_b2
, 2, lots_of_zeros
);
199 expect_error(GL_NO_ERROR
, "Type %s: Write count = 2 to b[2]", glsl_type
);
201 /* Out of bounds; see comment above */
202 uniform(loc_b2
, 1024, lots_of_zeros
);
203 (void) glGetError(); /* Eat generated error, if any */
205 glDeleteObjectARB(fs
);
206 glDeleteObjectARB(vs
);
207 glDeleteObjectARB(program
);
210 static const char vs_matrix_template
[] =
212 "uniform mat4 b[4];\n"
213 "uniform mat4 c[4];\n"
216 " mat4 m = a + b[3] + c[0] + c[1] + c[2] + c[3];\n"
217 " v = m * vec4(1.0, 1.0, 1.0, 1.0);\n"
218 " gl_Position = vec4(0,0,0,1);\n"
221 static const char fs_matrix_template
[] =
224 " gl_FragColor = v;\n"
228 static void test_matrix(void)
232 GLint loc_a
, loc_b
, loc_c
;
234 const char * glsl_type
= "mat4";
236 vs
= compile_shader(GL_VERTEX_SHADER_ARB
, vs_matrix_template
);
237 fs
= compile_shader(GL_FRAGMENT_SHADER_ARB
, fs_matrix_template
);
238 program
= link_program(vs
, fs
);
240 glUseProgramObjectARB(program
);
241 loc_a
= glGetUniformLocationARB(program
, "a");
242 loc_b
= glGetUniformLocationARB(program
, "b");
243 loc_c
= glGetUniformLocationARB(program
, "c");
244 loc_b2
= glGetUniformLocationARB(program
, "b[2]");
245 printf("locations: a: %i b: %i c: %i b[2]: %i\n", loc_a
, loc_b
, loc_c
, loc_b
);
247 expect_error(GL_NO_ERROR
, "Type %s: Sanity check", glsl_type
);
249 glUniformMatrix4fvARB(loc_b
, 0, GL_FALSE
, lots_of_zeros
);
250 expect_error(GL_NO_ERROR
, "Type %s: Write count = 0 to b", glsl_type
);
251 glUniformMatrix4fvARB(loc_b
, 1, GL_FALSE
, lots_of_zeros
);
252 expect_error(GL_NO_ERROR
, "Type %s: Write count = 1 to b", glsl_type
);
253 glUniformMatrix4fvARB(loc_b
, 4, GL_FALSE
, lots_of_zeros
);
254 expect_error(GL_NO_ERROR
, "Type %s: Write count = 4 to b", glsl_type
);
256 /* Out of bounds; see comment above */
257 glUniformMatrix4fvARB(loc_b
, 5, GL_FALSE
, lots_of_zeros
);
258 (void) glGetError(); /* Eat generated error, if any */
260 glUniformMatrix4fvARB(loc_c
, 0, GL_FALSE
, lots_of_zeros
);
261 expect_error(GL_NO_ERROR
, "Type %s: Write count = 0 to c", glsl_type
);
262 glUniformMatrix4fvARB(loc_c
, 1, GL_FALSE
, lots_of_zeros
);
263 expect_error(GL_NO_ERROR
, "Type %s: Write count = 1 to c", glsl_type
);
264 glUniformMatrix4fvARB(loc_c
, 4, GL_FALSE
, lots_of_zeros
);
265 expect_error(GL_NO_ERROR
, "Type %s: Write count = 4 to c", glsl_type
);
267 /* Out of bounds; see comment above */
268 glUniformMatrix4fvARB(loc_c
, 5, GL_FALSE
, lots_of_zeros
);
269 (void) glGetError(); /* Eat generated error, if any */
271 glUniformMatrix4fvARB(loc_b2
, 0, GL_FALSE
, lots_of_zeros
);
272 expect_error(GL_NO_ERROR
, "Type %s: Write count = 0 to b[2]", glsl_type
);
273 glUniformMatrix4fvARB(loc_b2
, 2, GL_FALSE
, lots_of_zeros
);
274 expect_error(GL_NO_ERROR
, "Type %s: Write count = 2 to b[2]", glsl_type
);
276 /* Out of bounds; see comment above */
277 glUniformMatrix4fvARB(loc_b2
, INT_MAX
, GL_FALSE
, lots_of_zeros
);
278 (void) glGetError(); /* Eat generated error, if any */
280 glUniformMatrix4fvARB(loc_a
, 0, GL_FALSE
, lots_of_zeros
);
281 expect_error(GL_NO_ERROR
, "Type %s: Write count = 0 to a", glsl_type
);
282 glUniformMatrix4fvARB(loc_a
, 1, GL_FALSE
, lots_of_zeros
);
283 expect_error(GL_NO_ERROR
, "Type %s: Write count = 1 to a", glsl_type
);
284 glUniformMatrix4fvARB(loc_a
, 2, GL_FALSE
, lots_of_zeros
);
285 expect_error(GL_INVALID_OPERATION
, "Type %s: Write count = 2 to a", glsl_type
);
286 glUniformMatrix4fvARB(loc_a
, INT_MAX
, GL_FALSE
, lots_of_zeros
);
287 expect_error(GL_INVALID_OPERATION
, "Type %s: Write count = INT_MAX to a", glsl_type
);
289 glDeleteObjectARB(fs
);
290 glDeleteObjectARB(vs
);
291 glDeleteObjectARB(program
);
297 piglit_ortho_projection(piglit_width
, piglit_height
, GL_FALSE
);
301 test_vector("float", ", 0, 0, 0", glUniform1fvARB
);
302 test_vector("vec2", ", 0, 0", glUniform2fvARB
);
303 test_vector("vec3", ", 0", glUniform3fvARB
);
304 test_vector("vec4", "", glUniform4fvARB
);
310 piglit_init(int argc
, char **argv
)
312 if (!piglit_is_extension_supported("GL_ARB_shader_objects") || !piglit_is_extension_supported("GL_ARB_vertex_shader") || !piglit_is_extension_supported("GL_ARB_fragment_shader")) {
313 printf("Requires ARB_shader_objects and ARB_{vertex,fragment}_shader\n");
314 piglit_report_result(PIGLIT_SKIP
);