1 /* Tests to validate fixes to various bugs in src/mesa/shader/shader_api.c
3 * Written by Bruce Merry
8 #define GL_GLEXT_PROTOTYPES
11 static void assert_test(const char *file
, int line
, int cond
, const char *msg
)
14 fprintf(stderr
, "%s:%d assertion \"%s\" failed\n", file
, line
, msg
);
18 #define assert(x) assert_test(__FILE__, __LINE__, (x), #x)
20 static void assert_no_error_test(const char *file
, int line
)
25 if (err
!= GL_NO_ERROR
)
26 fprintf(stderr
, "%s:%d received error %s\n",
27 file
, line
, gluErrorString(err
));
30 #define assert_no_error() assert_no_error_test(__FILE__, __LINE__)
32 static void assert_error_test(const char *file
, int line
, GLenum expect
)
38 fprintf(stderr
, "%s:%d expected %s but received %s\n",
39 file
, line
, gluErrorString(expect
), gluErrorString(err
));
40 while (glGetError()); /* consume any following errors */
43 #define assert_error(err) assert_error_test(__FILE__, __LINE__, (err))
45 static void check_status(GLuint id
, GLenum pname
, void (*query
)(GLuint
, GLenum
, GLint
*))
49 query(id
, pname
, &status
);
54 fprintf(stderr
, "Compilation/link failure:\n");
55 glGetInfoLogARB(id
, sizeof(info
), NULL
, info
);
56 fprintf(stderr
, "%s\n", info
);
61 static void check_compile_status(GLuint id
)
63 check_status(id
, GL_COMPILE_STATUS
, glGetShaderiv
);
66 static void check_link_status(GLuint id
)
68 check_status(id
, GL_LINK_STATUS
, glGetProgramiv
);
71 static GLuint
make_shader(GLenum type
, const char *src
)
76 id
= glCreateShader(type
);
77 glShaderSource(id
, 1, &src
, NULL
);
79 check_compile_status(id
);
84 static GLuint
make_program(const char *vs_src
, const char *fs_src
)
89 id
= glCreateProgram();
91 vs
= make_shader(GL_VERTEX_SHADER
, vs_src
);
92 glAttachShader(id
, vs
);
96 fs
= make_shader(GL_FRAGMENT_SHADER
, fs_src
);
97 glAttachShader(id
, fs
);
101 check_link_status(id
);
108 static void test_uniform_size_type1(const char *glslType
, GLenum glType
, const char *el
)
116 printf(" Running subtest %s\n", glslType
); fflush(stdout
);
117 sprintf(buffer
, "#version 120\nuniform %s m[60];\nvoid main() { gl_Position[0] = m[59]%s; }\n",
120 program
= make_program(buffer
, NULL
);
121 glGetProgramiv(program
, GL_ACTIVE_UNIFORMS
, &active
);
123 for (i
= 0; i
< active
; i
++) {
126 glGetActiveUniform(program
, i
, sizeof(buffer
), NULL
, &size
, &type
, buffer
);
128 if (strncmp(buffer
, "m", 1) == 0)
131 assert(i
< active
); /* Otherwise the compiler optimised it out */
132 assert(type
== glType
);
136 static void test_uniform_size_type(void)
138 test_uniform_size_type1("float", GL_FLOAT
, "");
139 test_uniform_size_type1("vec2", GL_FLOAT_VEC2
, "[0]");
140 test_uniform_size_type1("vec3", GL_FLOAT_VEC3
, "[0]");
141 test_uniform_size_type1("vec4", GL_FLOAT_VEC4
, "[0]");
143 test_uniform_size_type1("bool", GL_BOOL
, " ? 1.0 : 0.0");
144 test_uniform_size_type1("bvec2", GL_BOOL_VEC2
, "[0] ? 1.0 : 0.0");
145 test_uniform_size_type1("bvec3", GL_BOOL_VEC3
, "[0] ? 1.0 : 0.0");
146 test_uniform_size_type1("bvec4", GL_BOOL_VEC4
, "[0] ? 1.0 : 0.0");
148 test_uniform_size_type1("int", GL_INT
, "");
149 test_uniform_size_type1("ivec2", GL_INT_VEC2
, "[0]");
150 test_uniform_size_type1("ivec3", GL_INT_VEC3
, "[0]");
151 test_uniform_size_type1("ivec4", GL_INT_VEC4
, "[0]");
153 test_uniform_size_type1("mat2", GL_FLOAT_MAT2
, "[0][0]");
154 test_uniform_size_type1("mat3", GL_FLOAT_MAT3
, "[0][0]");
155 test_uniform_size_type1("mat4", GL_FLOAT_MAT4
, "[0][0]");
156 test_uniform_size_type1("mat2x3", GL_FLOAT_MAT2x3
, "[0][0]");
157 test_uniform_size_type1("mat2x4", GL_FLOAT_MAT2x4
, "[0][0]");
158 test_uniform_size_type1("mat3x2", GL_FLOAT_MAT3x2
, "[0][0]");
159 test_uniform_size_type1("mat3x4", GL_FLOAT_MAT3x4
, "[0][0]");
160 test_uniform_size_type1("mat4x2", GL_FLOAT_MAT4x2
, "[0][0]");
161 test_uniform_size_type1("mat4x3", GL_FLOAT_MAT4x3
, "[0][0]");
164 static void test_attrib_size_type1(const char *glslType
, GLenum glType
, const char *el
)
172 printf(" Running subtest %s\n", glslType
); fflush(stdout
);
173 sprintf(buffer
, "#version 120\nattribute %s m;\nvoid main() { gl_Position[0] = m%s; }\n",
176 program
= make_program(buffer
, NULL
);
177 glGetProgramiv(program
, GL_ACTIVE_ATTRIBUTES
, &active
);
179 for (i
= 0; i
< active
; i
++) {
182 glGetActiveAttrib(program
, i
, sizeof(buffer
), NULL
, &size
, &type
, buffer
);
184 if (strncmp(buffer
, "m", 1) == 0)
187 assert(i
< active
); /* Otherwise the compiler optimised it out */
188 assert(type
== glType
);
192 static void test_attrib_size_type(void)
194 test_attrib_size_type1("float", GL_FLOAT
, "");
195 test_attrib_size_type1("vec2", GL_FLOAT_VEC2
, "[0]");
196 test_attrib_size_type1("vec3", GL_FLOAT_VEC3
, "[0]");
197 test_attrib_size_type1("vec4", GL_FLOAT_VEC4
, "[0]");
199 test_attrib_size_type1("mat2", GL_FLOAT_MAT2
, "[0][0]");
200 test_attrib_size_type1("mat3", GL_FLOAT_MAT3
, "[0][0]");
201 test_attrib_size_type1("mat4", GL_FLOAT_MAT4
, "[0][0]");
202 test_attrib_size_type1("mat2x3", GL_FLOAT_MAT2x3
, "[0][0]");
203 test_attrib_size_type1("mat2x4", GL_FLOAT_MAT2x4
, "[0][0]");
204 test_attrib_size_type1("mat3x2", GL_FLOAT_MAT3x2
, "[0][0]");
205 test_attrib_size_type1("mat3x4", GL_FLOAT_MAT3x4
, "[0][0]");
206 test_attrib_size_type1("mat4x2", GL_FLOAT_MAT4x2
, "[0][0]");
207 test_attrib_size_type1("mat4x3", GL_FLOAT_MAT4x3
, "[0][0]");
210 static void test_uniform_array_overflow(void)
216 program
= make_program("#version 120\nuniform vec2 x[10];\nvoid main() { gl_Position.xy = x[9]; }\n", NULL
);
217 location
= glGetUniformLocation(program
, "x");
219 glUniform2fv(location
, 64, data
);
223 static void test_uniform_scalar_count(void)
229 program
= make_program("#version 110\nuniform vec2 x;\nvoid main() { gl_Position.xy = x; }\n", NULL
);
230 location
= glGetUniformLocation(program
, "x");
232 glUniform2fv(location
, 64, data
);
233 assert_error(GL_INVALID_OPERATION
);
236 static void test_uniform_query_matrix(void)
243 program
= make_program("#version 110\nuniform mat3 m[2];\nvoid main() { gl_Position.xyz = m[1][2]; }\n", NULL
);
244 location
= glGetUniformLocation(program
, "m");
245 for (i
= 0; i
< 9; i
++)
247 for (i
= 9; i
< 18; i
++)
249 glUniformMatrix3fv(location
, 1, GL_TRUE
, data
);
251 for (i
= 0; i
< 18; i
++)
253 glGetUniformfv(program
, location
, data
);
254 for (c
= 0; c
< 3; c
++)
255 for (r
= 0; r
< 3; r
++)
256 assert(data
[c
* 3 + r
] == r
* 3 + c
);
257 for (i
= 9; i
< 18; i
++)
258 assert(data
[i
] == 123.0);
261 static void test_uniform_neg_location(void)
266 program
= make_program("#version 110\nvoid main() { gl_Position = vec4(1.0, 1.0, 1.0, 1.0); }\n", NULL
);
270 glUniform1i(-200, 1);
271 assert_error(GL_INVALID_OPERATION
);
272 glUniformMatrix2fv(-1, 1, GL_FALSE
, data
);
274 glUniformMatrix2fv(-200, 1, GL_FALSE
, data
);
275 assert_error(GL_INVALID_OPERATION
);
278 static void test_uniform_bool_conversion(void)
282 GLint value
[16]; /* in case glGetUniformiv goes nuts on the stack */
285 program
= make_program("uniform bool b;\nvoid main() { gl_Position.x = b ? 1.5 : 0.5; }\n", NULL
);
286 location
= glGetUniformLocation(program
, "b");
287 assert(location
!= -1);
289 glUniform1i(location
, 5);
291 glGetUniformiv(program
, location
, &value
[0]);
293 assert(value
[0] == 1);
296 static void test_uniform_multiple_samplers(void)
300 GLint values
[2] = {0, 1};
303 program
= make_program(NULL
, "uniform sampler2D s[2];\nvoid main() { gl_FragColor = texture2D(s[1], vec2(0.0, 0.0)); }\n");
304 location
= glGetUniformLocation(program
, "s[0]");
305 if (location
== -1) /* Mesa doesn't currently support indexing */
306 location
= glGetUniformLocation(program
, "s");
307 assert(location
!= -1);
309 glUniform1iv(location
, 2, values
);
313 static void run_test(const char *name
, void (*callback
)(void))
315 printf("Running %s\n", name
);
320 #define RUN_TEST(name) run_test(#name, (name))
322 int main(int argc
, char **argv
)
324 glutInit(&argc
, argv
);
325 glutCreateWindow("Mesa bug demo");
327 RUN_TEST(test_uniform_size_type
);
328 RUN_TEST(test_attrib_size_type
);
329 RUN_TEST(test_uniform_array_overflow
);
330 RUN_TEST(test_uniform_scalar_count
);
331 RUN_TEST(test_uniform_query_matrix
);
332 RUN_TEST(test_uniform_neg_location
);
333 RUN_TEST(test_uniform_bool_conversion
);
334 /* Leave this one at the end, since it crashes Mesa's shader compiler */
335 RUN_TEST(test_uniform_multiple_samplers
);