shader_api.c revision 7ec3b29a
132001f49Smrg/* Tests to validate fixes to various bugs in src/mesa/shader/shader_api.c
232001f49Smrg *
332001f49Smrg * Written by Bruce Merry
432001f49Smrg */
532001f49Smrg#include <string.h>
632001f49Smrg#include <stdio.h>
732001f49Smrg#include <stdlib.h>
832001f49Smrg#include <GL/glew.h>
932001f49Smrg#include "glut_wrap.h"
1032001f49Smrg
1132001f49Smrgstatic void assert_test(const char *file, int line, int cond, const char *msg)
1232001f49Smrg{
1332001f49Smrg   if (!cond)
1432001f49Smrg      fprintf(stderr, "%s:%d assertion \"%s\" failed\n", file, line, msg);
1532001f49Smrg}
1632001f49Smrg
1732001f49Smrg#undef assert
1832001f49Smrg#define assert(x) assert_test(__FILE__, __LINE__, (x), #x)
1932001f49Smrg
2032001f49Smrgstatic void assert_no_error_test(const char *file, int line)
2132001f49Smrg{
2232001f49Smrg   GLenum err;
2332001f49Smrg
2432001f49Smrg   err = glGetError();
2532001f49Smrg   if (err != GL_NO_ERROR)
2632001f49Smrg      fprintf(stderr, "%s:%d received error %s\n",
2732001f49Smrg              file, line, gluErrorString(err));
2832001f49Smrg}
2932001f49Smrg
3032001f49Smrg#define assert_no_error() assert_no_error_test(__FILE__, __LINE__)
3132001f49Smrg
3232001f49Smrgstatic void assert_error_test(const char *file, int line, GLenum expect)
3332001f49Smrg{
3432001f49Smrg   GLenum err;
3532001f49Smrg
3632001f49Smrg   err = glGetError();
3732001f49Smrg   if (err != expect)
3832001f49Smrg      fprintf(stderr, "%s:%d expected %s but received %s\n",
3932001f49Smrg              file, line, gluErrorString(expect), gluErrorString(err));
4032001f49Smrg   while (glGetError()); /* consume any following errors */
4132001f49Smrg}
4232001f49Smrg
4332001f49Smrg#define assert_error(err) assert_error_test(__FILE__, __LINE__, (err))
4432001f49Smrg
4532001f49Smrgstatic void check_status(GLuint id, GLenum pname, void (GLAPIENTRY *query)(GLuint, GLenum, GLint *))
4632001f49Smrg{
4732001f49Smrg    GLint status;
4832001f49Smrg
4932001f49Smrg    query(id, pname, &status);
5032001f49Smrg    if (!status)
5132001f49Smrg    {
5232001f49Smrg        char info[65536];
5332001f49Smrg
5432001f49Smrg        fprintf(stderr, "Compilation/link failure:\n");
5532001f49Smrg        glGetInfoLogARB(id, sizeof(info), NULL, info);
5632001f49Smrg        fprintf(stderr, "%s\n", info);
5732001f49Smrg        exit(1);
5832001f49Smrg    }
5932001f49Smrg}
6032001f49Smrg
6132001f49Smrgstatic void check_compile_status(GLuint id)
6232001f49Smrg{
6332001f49Smrg   check_status(id, GL_COMPILE_STATUS, glGetShaderiv);
6432001f49Smrg}
6532001f49Smrg
6632001f49Smrgstatic void check_link_status(GLuint id)
6732001f49Smrg{
6832001f49Smrg   check_status(id, GL_LINK_STATUS, glGetProgramiv);
6932001f49Smrg}
7032001f49Smrg
7132001f49Smrgstatic GLuint make_shader(GLenum type, const char *src)
7232001f49Smrg{
7332001f49Smrg   GLuint id;
7432001f49Smrg
7532001f49Smrg   assert_no_error();
7632001f49Smrg   id = glCreateShader(type);
7732001f49Smrg   glShaderSource(id, 1, &src, NULL);
7832001f49Smrg   glCompileShader(id);
7932001f49Smrg   check_compile_status(id);
8032001f49Smrg   assert_no_error();
8132001f49Smrg   return id;
8232001f49Smrg}
8332001f49Smrg
8432001f49Smrgstatic GLuint make_program(const char *vs_src, const char *fs_src)
8532001f49Smrg{
8632001f49Smrg   GLuint id, vs, fs;
8732001f49Smrg
8832001f49Smrg   assert_no_error();
8932001f49Smrg   id = glCreateProgram();
9032001f49Smrg   if (vs_src) {
9132001f49Smrg      vs = make_shader(GL_VERTEX_SHADER, vs_src);
9232001f49Smrg      glAttachShader(id, vs);
9332001f49Smrg      glDeleteShader(vs);
9432001f49Smrg   }
9532001f49Smrg   if (fs_src) {
9632001f49Smrg      fs = make_shader(GL_FRAGMENT_SHADER, fs_src);
9732001f49Smrg      glAttachShader(id, fs);
9832001f49Smrg      glDeleteShader(fs);
9932001f49Smrg   }
10032001f49Smrg   glLinkProgram(id);
10132001f49Smrg   check_link_status(id);
10232001f49Smrg   glUseProgram(id);
10332001f49Smrg   glDeleteProgram(id);
10432001f49Smrg   assert_no_error();
10532001f49Smrg   return id;
10632001f49Smrg}
10732001f49Smrg
10832001f49Smrgstatic void test_uniform_size_type1(const char *glslType, GLenum glType, const char *el)
10932001f49Smrg{
11032001f49Smrg   char buffer[1024];
11132001f49Smrg   GLuint program;
11232001f49Smrg   GLint active, i;
11332001f49Smrg   GLenum type;
11432001f49Smrg   GLint size;
11532001f49Smrg
11632001f49Smrg   printf("  Running subtest %s\n", glslType);
11732001f49Smrg   fflush(stdout);
11832001f49Smrg   sprintf(buffer, "#version 120\nuniform %s m[60];\nvoid main() { gl_Position[0] = m[59]%s; }\n",
11932001f49Smrg           glslType, el);
12032001f49Smrg
12132001f49Smrg   program = make_program(buffer, NULL);
12232001f49Smrg   glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active);
12332001f49Smrg   assert_no_error();
12432001f49Smrg   for (i = 0; i < active; i++) {
12532001f49Smrg      size = -1;
12632001f49Smrg      type = 0;
12732001f49Smrg      glGetActiveUniform(program, i, sizeof(buffer), NULL, &size, &type, buffer);
12832001f49Smrg      assert_no_error();
12932001f49Smrg      if (strncmp(buffer, "m", 1) == 0)
13032001f49Smrg         break;
13132001f49Smrg   }
13232001f49Smrg   assert(i < active); /* Otherwise the compiler optimised it out */
13332001f49Smrg   assert(type == glType);
13432001f49Smrg   assert(size == 60);
13532001f49Smrg}
13632001f49Smrg
13732001f49Smrgstatic void test_uniform_size_type(void)
13832001f49Smrg{
13932001f49Smrg   test_uniform_size_type1("float", GL_FLOAT, "");
14032001f49Smrg   test_uniform_size_type1("vec2", GL_FLOAT_VEC2, "[0]");
14132001f49Smrg   test_uniform_size_type1("vec3", GL_FLOAT_VEC3, "[0]");
14232001f49Smrg   test_uniform_size_type1("vec4", GL_FLOAT_VEC4, "[0]");
14332001f49Smrg
14432001f49Smrg   test_uniform_size_type1("bool", GL_BOOL, " ? 1.0 : 0.0");
14532001f49Smrg   test_uniform_size_type1("bvec2", GL_BOOL_VEC2, "[0] ? 1.0 : 0.0");
14632001f49Smrg   test_uniform_size_type1("bvec3", GL_BOOL_VEC3, "[0] ? 1.0 : 0.0");
14732001f49Smrg   test_uniform_size_type1("bvec4", GL_BOOL_VEC4, "[0] ? 1.0 : 0.0");
14832001f49Smrg
14932001f49Smrg   test_uniform_size_type1("int", GL_INT, "");
15032001f49Smrg   test_uniform_size_type1("ivec2", GL_INT_VEC2, "[0]");
15132001f49Smrg   test_uniform_size_type1("ivec3", GL_INT_VEC3, "[0]");
15232001f49Smrg   test_uniform_size_type1("ivec4", GL_INT_VEC4, "[0]");
15332001f49Smrg
15432001f49Smrg   test_uniform_size_type1("mat2", GL_FLOAT_MAT2, "[0][0]");
15532001f49Smrg   test_uniform_size_type1("mat3", GL_FLOAT_MAT3, "[0][0]");
15632001f49Smrg   test_uniform_size_type1("mat4", GL_FLOAT_MAT4, "[0][0]");
15732001f49Smrg   test_uniform_size_type1("mat2x3", GL_FLOAT_MAT2x3, "[0][0]");
15832001f49Smrg   test_uniform_size_type1("mat2x4", GL_FLOAT_MAT2x4, "[0][0]");
15932001f49Smrg   test_uniform_size_type1("mat3x2", GL_FLOAT_MAT3x2, "[0][0]");
16032001f49Smrg   test_uniform_size_type1("mat3x4", GL_FLOAT_MAT3x4, "[0][0]");
16132001f49Smrg   test_uniform_size_type1("mat4x2", GL_FLOAT_MAT4x2, "[0][0]");
16232001f49Smrg   test_uniform_size_type1("mat4x3", GL_FLOAT_MAT4x3, "[0][0]");
16332001f49Smrg}
16432001f49Smrg
16532001f49Smrgstatic void test_attrib_size_type1(const char *glslType, GLenum glType, const char *el)
16632001f49Smrg{
16732001f49Smrg   char buffer[1024];
16832001f49Smrg   GLuint program;
16932001f49Smrg   GLint active, i;
17032001f49Smrg   GLenum type;
17132001f49Smrg   GLint size;
17232001f49Smrg
17332001f49Smrg   printf("  Running subtest %s\n", glslType);
17432001f49Smrg   fflush(stdout);
17532001f49Smrg   sprintf(buffer, "#version 120\nattribute %s m;\nvoid main() { gl_Position[0] = m%s; }\n",
17632001f49Smrg           glslType, el);
17732001f49Smrg
17832001f49Smrg   program = make_program(buffer, NULL);
17932001f49Smrg   glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active);
18032001f49Smrg   assert_no_error();
18132001f49Smrg   for (i = 0; i < active; i++) {
18232001f49Smrg      size = -1;
18332001f49Smrg      type = -1;
18432001f49Smrg      glGetActiveAttrib(program, i, sizeof(buffer), NULL, &size, &type, buffer);
18532001f49Smrg      assert_no_error();
18632001f49Smrg      if (strncmp(buffer, "m", 1) == 0)
18732001f49Smrg         break;
18832001f49Smrg   }
18932001f49Smrg   assert(i < active); /* Otherwise the compiler optimised it out */
19032001f49Smrg   assert(type == glType);
19132001f49Smrg   assert(size == 1);
19232001f49Smrg}
19332001f49Smrg
19432001f49Smrgstatic void test_attrib_size_type(void)
19532001f49Smrg{
19632001f49Smrg   test_attrib_size_type1("float", GL_FLOAT, "");
19732001f49Smrg   test_attrib_size_type1("vec2", GL_FLOAT_VEC2, "[0]");
19832001f49Smrg   test_attrib_size_type1("vec3", GL_FLOAT_VEC3, "[0]");
19932001f49Smrg   test_attrib_size_type1("vec4", GL_FLOAT_VEC4, "[0]");
20032001f49Smrg
20132001f49Smrg   test_attrib_size_type1("mat2", GL_FLOAT_MAT2, "[0][0]");
20232001f49Smrg   test_attrib_size_type1("mat3", GL_FLOAT_MAT3, "[0][0]");
20332001f49Smrg   test_attrib_size_type1("mat4", GL_FLOAT_MAT4, "[0][0]");
20432001f49Smrg   test_attrib_size_type1("mat2x3", GL_FLOAT_MAT2x3, "[0][0]");
20532001f49Smrg   test_attrib_size_type1("mat2x4", GL_FLOAT_MAT2x4, "[0][0]");
20632001f49Smrg   test_attrib_size_type1("mat3x2", GL_FLOAT_MAT3x2, "[0][0]");
20732001f49Smrg   test_attrib_size_type1("mat3x4", GL_FLOAT_MAT3x4, "[0][0]");
20832001f49Smrg   test_attrib_size_type1("mat4x2", GL_FLOAT_MAT4x2, "[0][0]");
20932001f49Smrg   test_attrib_size_type1("mat4x3", GL_FLOAT_MAT4x3, "[0][0]");
21032001f49Smrg}
21132001f49Smrg
21232001f49Smrgstatic void test_uniform_array_overflow(void)
21332001f49Smrg{
21432001f49Smrg   GLuint program;
21532001f49Smrg   GLint location;
21632001f49Smrg   GLfloat data[128];
21732001f49Smrg
21832001f49Smrg   program = make_program("#version 120\nuniform vec2 x[10];\nvoid main() { gl_Position.xy = x[9]; }\n", NULL);
21932001f49Smrg   location = glGetUniformLocation(program, "x");
22032001f49Smrg   assert_no_error();
22132001f49Smrg   glUniform2fv(location, 64, data);
22232001f49Smrg   assert_no_error();
22332001f49Smrg}
22432001f49Smrg
22532001f49Smrgstatic void test_uniform_scalar_count(void)
22632001f49Smrg{
22732001f49Smrg   GLuint program;
22832001f49Smrg   GLint location;
22932001f49Smrg   GLfloat data[128];
23032001f49Smrg
23132001f49Smrg   program = make_program("#version 110\nuniform vec2 x;\nvoid main() { gl_Position.xy = x; }\n", NULL);
23232001f49Smrg   location = glGetUniformLocation(program, "x");
23332001f49Smrg   assert_no_error();
23432001f49Smrg   glUniform2fv(location, 64, data);
23532001f49Smrg   assert_error(GL_INVALID_OPERATION);
23632001f49Smrg}
23732001f49Smrg
23832001f49Smrgstatic void test_uniform_query_matrix(void)
23932001f49Smrg{
24032001f49Smrg   GLuint program;
24132001f49Smrg   GLfloat data[18];
24232001f49Smrg   GLint i, r, c;
24332001f49Smrg   GLint location;
24432001f49Smrg
24532001f49Smrg   program = make_program("#version 110\nuniform mat3 m[2];\nvoid main() { gl_Position.xyz = m[1][2]; }\n", NULL);
24632001f49Smrg   location = glGetUniformLocation(program, "m");
24732001f49Smrg   for (i = 0; i < 9; i++)
24832001f49Smrg      data[i] = i;
24932001f49Smrg   for (i = 9; i < 18; i++)
25032001f49Smrg      data[i] = 321.0;
25132001f49Smrg   glUniformMatrix3fv(location, 1, GL_TRUE, data);
25232001f49Smrg
25332001f49Smrg   for (i = 0; i < 18; i++)
25432001f49Smrg      data[i] = 123.0;
25532001f49Smrg   glGetUniformfv(program, location, data);
25632001f49Smrg   for (c = 0; c < 3; c++)
25732001f49Smrg      for (r = 0; r < 3; r++)
25832001f49Smrg         assert(data[c * 3 + r] == r * 3 + c);
25932001f49Smrg   for (i = 9; i < 18; i++)
26032001f49Smrg      assert(data[i] == 123.0);
26132001f49Smrg}
26232001f49Smrg
26332001f49Smrgstatic void test_uniform_neg_location(void)
26432001f49Smrg{
26532001f49Smrg   GLuint program;
26632001f49Smrg   GLfloat data[4];
26732001f49Smrg
26832001f49Smrg   program = make_program("#version 110\nvoid main() { gl_Position = vec4(1.0, 1.0, 1.0, 1.0); }\n", NULL);
26932001f49Smrg   assert_no_error();
2707ec3b29aSmrg   (void)program;
27132001f49Smrg   glUniform1i(-1, 1);
27232001f49Smrg   assert_no_error();
27332001f49Smrg   glUniform1i(-200, 1);
27432001f49Smrg   assert_error(GL_INVALID_OPERATION);
27532001f49Smrg   glUniformMatrix2fv(-1, 1, GL_FALSE, data);
27632001f49Smrg   assert_no_error();
27732001f49Smrg   glUniformMatrix2fv(-200, 1, GL_FALSE, data);
27832001f49Smrg   assert_error(GL_INVALID_OPERATION);
27932001f49Smrg}
28032001f49Smrg
28132001f49Smrgstatic void test_uniform_bool_conversion(void)
28232001f49Smrg{
28332001f49Smrg    GLuint program;
28432001f49Smrg    GLint location;
28532001f49Smrg    GLint value[16];  /* in case glGetUniformiv goes nuts on the stack */
28632001f49Smrg
28732001f49Smrg    assert_no_error();
28832001f49Smrg    program = make_program("uniform bool b;\nvoid main() { gl_Position.x = b ? 1.5 : 0.5; }\n", NULL);
28932001f49Smrg    location = glGetUniformLocation(program, "b");
29032001f49Smrg    assert(location != -1);
29132001f49Smrg    assert_no_error();
29232001f49Smrg    glUniform1i(location, 5);
29332001f49Smrg    assert_no_error();
29432001f49Smrg    glGetUniformiv(program, location, &value[0]);
29532001f49Smrg    assert_no_error();
29632001f49Smrg    assert(value[0] == 1);
29732001f49Smrg}
29832001f49Smrg
29932001f49Smrgstatic void test_uniform_multiple_samplers(void)
30032001f49Smrg{
30132001f49Smrg   GLuint program;
30232001f49Smrg   GLint location;
30332001f49Smrg   GLint values[2] = {0, 1};
30432001f49Smrg
30532001f49Smrg   assert_no_error();
30632001f49Smrg   program = make_program(NULL, "uniform sampler2D s[2];\nvoid main() { gl_FragColor = texture2D(s[1], vec2(0.0, 0.0)); }\n");
30732001f49Smrg   location = glGetUniformLocation(program, "s[0]");
30832001f49Smrg   assert(location != -1);
30932001f49Smrg   assert_no_error();
31032001f49Smrg   glUniform1iv(location, 2, values);
31132001f49Smrg   assert_no_error();
31232001f49Smrg}
31332001f49Smrg
31432001f49Smrgstatic void run_test(const char *name, void (*callback)(void))
31532001f49Smrg{
31632001f49Smrg   printf("Running %s\n", name);
31732001f49Smrg   fflush(stdout);
31832001f49Smrg   callback();
31932001f49Smrg}
32032001f49Smrg
32132001f49Smrg#define RUN_TEST(name) run_test(#name, (name))
32232001f49Smrg
32332001f49Smrgint main(int argc, char **argv)
32432001f49Smrg{
32532001f49Smrg   glutInit(&argc, argv);
32632001f49Smrg   glutCreateWindow("Mesa bug demo");
32732001f49Smrg   glewInit();
32832001f49Smrg
32932001f49Smrg   if (!GLEW_VERSION_2_0) {
33032001f49Smrg      printf("Sorry, this test requires OpenGL 2.x GLSL support\n");
33132001f49Smrg      exit(0);
33232001f49Smrg   }
33332001f49Smrg
33432001f49Smrg   RUN_TEST(test_uniform_size_type);
33532001f49Smrg   RUN_TEST(test_attrib_size_type);
33632001f49Smrg   RUN_TEST(test_uniform_array_overflow);
33732001f49Smrg   RUN_TEST(test_uniform_scalar_count);
33832001f49Smrg   RUN_TEST(test_uniform_query_matrix);
33932001f49Smrg   RUN_TEST(test_uniform_neg_location);
34032001f49Smrg   RUN_TEST(test_uniform_bool_conversion);
34132001f49Smrg   /* Leave this one at the end, since it crashes Mesa's shader compiler */
34232001f49Smrg   RUN_TEST(test_uniform_multiple_samplers);
34332001f49Smrg   return 0;
34432001f49Smrg}
345