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