[Piglit] [PATCH] shaders: add a test counting builtin active uniforms

Tapani Pälli tapani.palli at intel.com
Tue May 26 05:05:31 PDT 2015


Hi;

Looks good, I also uncommented printf line when testing to see the 
beautiful shader source :)

As it happens there are somewhat similar tests for builtin uniforms in 
ES31 suite and it looks like they will get fixed by your upcoming Mesa 
changes.

It's unfortunate that we cannot verify against the amount of active 
uniforms but that's just how it is. I think this is a good test for 
catching the current issue for which we have a bug for.



Reviewed-by: Tapani Pälli <tapani.palli at intel.com>



On 05/19/2015 03:29 PM, Martin Peres wrote:
> The test will almost-always pass but it is a nice way to catch bugs
> in our implementation... More information inside the test!
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=32403
> Signed-off-by: Martin Peres <martin.peres at linux.intel.com>
> ---
>   tests/all.py                    |   1 +
>   tests/shaders/CMakeLists.gl.txt |   1 +
>   tests/shaders/getuniform-03.c   | 305 ++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 307 insertions(+)
>   create mode 100755 tests/shaders/getuniform-03.c
>
> diff --git a/tests/all.py b/tests/all.py
> index 5b87410..8159b9b 100755
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -484,6 +484,7 @@ with profile.group_manager(PiglitGLTest, 'shaders') as g:
>       g(['glsl-getattriblocation'])
>       g(['getuniform-01'])
>       g(['getuniform-02'])
> +    g(['getuniform-03'])
>       g(['glsl-invalid-asm-01'])
>       g(['glsl-invalid-asm-02'])
>       g(['glsl-novertexdata'])
> diff --git a/tests/shaders/CMakeLists.gl.txt b/tests/shaders/CMakeLists.gl.txt
> index 35b4c6c..192debb 100644
> --- a/tests/shaders/CMakeLists.gl.txt
> +++ b/tests/shaders/CMakeLists.gl.txt
> @@ -59,6 +59,7 @@ piglit_add_executable (glsl-getactiveuniform-count glsl-getactiveuniform-count.c
>   piglit_add_executable (glsl-getactiveuniform-length glsl-getactiveuniform-length.c)
>   piglit_add_executable (getuniform-01 getuniform-01.c)
>   piglit_add_executable (getuniform-02 getuniform-02.c)
> +piglit_add_executable (getuniform-03 getuniform-03.c)
>   piglit_add_executable (glsl-invalid-asm-01 glsl-invalid-asm-01.c)
>   piglit_add_executable (glsl-invalid-asm-02 glsl-invalid-asm-02.c)
>   piglit_add_executable (glsl-novertexdata glsl-novertexdata.c)
> diff --git a/tests/shaders/getuniform-03.c b/tests/shaders/getuniform-03.c
> new file mode 100755
> index 0000000..927a98f
> --- /dev/null
> +++ b/tests/shaders/getuniform-03.c
> @@ -0,0 +1,305 @@
> +/*
> + * Copyright 2015 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#include "piglit-util-gl.h"
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> +	config.supports_gl_compat_version = 21;
> +
> +	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +struct builtin_uniform_t {
> +	const char *name;
> +	GLenum type;
> +	bool is_array;
> +	bool found;
> +} uniforms[] = {
> +	{ "gl_DepthRange.near", GL_FLOAT, false , false },
> +	{ "gl_DepthRange.far", GL_FLOAT, false , false },
> +	{ "gl_DepthRange.diff", GL_FLOAT, false , false },
> +	/* { "gl_NumSamples", GL_INT, false , false }, requires OGL 4.0 */
> +	{ "gl_ModelViewMatrix", GL_FLOAT_MAT4, false , false },
> +	{ "gl_ProjectionMatrix", GL_FLOAT_MAT4, false , false  },
> +	{ "gl_ModelViewProjectionMatrix", GL_FLOAT_MAT4, false , false },
> +	{ "gl_TextureMatrix", GL_FLOAT_MAT4, true , false  },
> +	{ "gl_NormalMatrix", GL_FLOAT_MAT3, false , false  },
> +	{ "gl_ModelViewMatrixInverse", GL_FLOAT_MAT4, false , false },
> +	{ "gl_ProjectionMatrixInverse", GL_FLOAT_MAT4, false , false  },
> +	{ "gl_TextureMatrixInverse", GL_FLOAT_MAT4, true , false  },
> +	{ "gl_ModelViewMatrixTranspose", GL_FLOAT_MAT4, false , false  },
> +	{ "gl_ProjectionMatrixTranspose", GL_FLOAT_MAT4, false , false },
> +	{ "gl_ModelViewProjectionMatrixTranspose", GL_FLOAT_MAT4, false , false },
> +	{ "gl_TextureMatrixTranspose", GL_FLOAT_MAT4, true , false  },
> +	{ "gl_ModelViewMatrixInverseTranspose", GL_FLOAT_MAT4, false , false  },
> +	{ "gl_ProjectionMatrixInverseTranspose", GL_FLOAT_MAT4, false , false },
> +	{ "gl_ModelViewProjectionMatrixInverseTranspose", GL_FLOAT_MAT4, false  },
> +	{ "gl_TextureMatrixInverseTranspose", GL_FLOAT_MAT4, true , false },
> +	{ "gl_NormalScale", GL_FLOAT, false , false },
> +	{ "gl_ClipPlane", GL_FLOAT_VEC4, true , false },
> +	{ "gl_Point.size", GL_FLOAT, false , false },
> +	{ "gl_Point.sizeMin", GL_FLOAT, false , false },
> +	{ "gl_Point.sizeMax", GL_FLOAT, false , false },
> +	{ "gl_Point.fadeThresholdSize", GL_FLOAT, false , false },
> +	{ "gl_Point.distanceConstantAttenuation", GL_FLOAT, false , false },
> +	{ "gl_Point.distanceLinearAttenuation", GL_FLOAT, false , false },
> +	{ "gl_Point.distanceQuadraticAttenuation", GL_FLOAT, false , false },
> +	{ "gl_FrontMaterial.emission", GL_FLOAT_VEC4, false , false },
> +	{ "gl_FrontMaterial.ambient", GL_FLOAT_VEC4, false , false },
> +	{ "gl_FrontMaterial.diffuse", GL_FLOAT_VEC4, false , false },
> +	{ "gl_FrontMaterial.specular", GL_FLOAT_VEC4, false , false },
> +	{ "gl_FrontMaterial.shininess", GL_FLOAT, false , false },
> +	{ "gl_BackMaterial.emission", GL_FLOAT_VEC4, false , false },
> +	{ "gl_BackMaterial.ambient", GL_FLOAT_VEC4, false , false },
> +	{ "gl_BackMaterial.diffuse", GL_FLOAT_VEC4, false , false },
> +	{ "gl_BackMaterial.specular", GL_FLOAT_VEC4, false , false },
> +	{ "gl_BackMaterial.shininess", GL_FLOAT, false , false },
> +	{ "gl_LightSource[0].ambient", GL_FLOAT_VEC4, false , false },
> +	{ "gl_LightSource[0].diffuse", GL_FLOAT_VEC4, false , false },
> +	{ "gl_LightSource[0].specular", GL_FLOAT_VEC4, false , false },
> +	{ "gl_LightSource[0].position", GL_FLOAT_VEC4, false , false },
> +	{ "gl_LightSource[0].halfVector", GL_FLOAT_VEC4, false , false },
> +	{ "gl_LightSource[0].spotDirection", GL_FLOAT_VEC3, false , false },
> +	{ "gl_LightSource[0].spotExponent", GL_FLOAT, false , false },
> +	{ "gl_LightSource[0].spotCutoff", GL_FLOAT, false , false },
> +	{ "gl_LightSource[0].spotCosCutoff", GL_FLOAT, false , false },
> +	{ "gl_LightSource[0].constantAttenuation", GL_FLOAT, false , false },
> +	{ "gl_LightSource[0].linearAttenuation", GL_FLOAT, false , false },
> +	{ "gl_LightSource[0].quadraticAttenuation", GL_FLOAT, false , false },
> +	{ "gl_LightModel.ambient", GL_FLOAT_VEC4, false , false },
> +	{ "gl_FrontLightModelProduct.sceneColor", GL_FLOAT_VEC4, false , false },
> +	{ "gl_BackLightModelProduct.sceneColor", GL_FLOAT_VEC4, false , false },
> +	{ "gl_FrontLightProduct[0].ambient", GL_FLOAT_VEC4, true , false },
> +	{ "gl_FrontLightProduct[0].diffuse", GL_FLOAT_VEC4, true , false },
> +	{ "gl_FrontLightProduct[0].specular", GL_FLOAT_VEC4, true , false },
> +	{ "gl_BackLightProduct[0].ambient", GL_FLOAT_VEC4, true , false },
> +	{ "gl_BackLightProduct[0].diffuse", GL_FLOAT_VEC4, true , false },
> +	{ "gl_BackLightProduct[0].specular", GL_FLOAT_VEC4, true , false },
> +	{ "gl_TextureEnvColor", GL_FLOAT_VEC4, true , false },
> +	{ "gl_EyePlaneS", GL_FLOAT_VEC4, true , false },
> +	{ "gl_EyePlaneT", GL_FLOAT_VEC4, true , false },
> +	{ "gl_EyePlaneR", GL_FLOAT_VEC4, true , false },
> +	{ "gl_EyePlaneQ", GL_FLOAT_VEC4, true , false },
> +	{ "gl_ObjectPlaneS", GL_FLOAT_VEC4, true , false },
> +	{ "gl_ObjectPlaneT", GL_FLOAT_VEC4, true , false },
> +	{ "gl_ObjectPlaneR", GL_FLOAT_VEC4, true , false },
> +	{ "gl_ObjectPlaneQ", GL_FLOAT_VEC4, true , false },
> +	{ "gl_Fog.color", GL_FLOAT_VEC4, false , false },
> +	{ "gl_Fog.density", GL_FLOAT, false , false },
> +	{ "gl_Fog.start", GL_FLOAT, false , false },
> +	{ "gl_Fog.end", GL_FLOAT, false , false },
> +	{ "gl_Fog.scale", GL_FLOAT, false , false },
> +};
> +
> +static const char vs_header[] =
> +   "void main()\n"
> +   "{\n"
> +   "  gl_Position = vec4(1);\n";
> +
> +static const char vs_footer[] =
> +   "}\n";
> +
> +char *
> +gen_vs_shader_all()
> +{
> +	/* strlen("  gl_Position += vec4(gl_ModelViewProjectionMatrixInverse
> +	 *        "Transpose[0]);\n") */
> +	size_t max_line_size = 64;
> +	size_t uniforms_count = ARRAY_SIZE(uniforms);
> +	size_t shader_len = strlen(vs_header) +
> +			    uniforms_count * max_line_size +
> +			    strlen(vs_footer) + 1;
> +	size_t i;
> +
> +	/* allocate the shader */
> +	char *vs_text = malloc(shader_len);
> +	memset(vs_text, 0, shader_len);
> +
> +	/* add the header */
> +	strcat(vs_text, vs_header);
> +
> +	/* add a reference to every uniform */
> +	for (i = 0; i < uniforms_count; i++) {
> +		strcat(vs_text, "  gl_Position += ");
> +		switch(uniforms[i].type) {
> +		case GL_FLOAT_VEC3:
> +			strcat(vs_text, "vec4(");
> +			strcat(vs_text, uniforms[i].name);
> +			strcat(vs_text, ", 1)");
> +			break;
> +		case GL_FLOAT_MAT4:
> +			strcat(vs_text, "vec4(");
> +			strcat(vs_text, uniforms[i].name);
> +			strcat(vs_text, "[0])");
> +			break;
> +		case GL_FLOAT_MAT3:
> +			strcat(vs_text, "vec4(");
> +			strcat(vs_text, uniforms[i].name);
> +			strcat(vs_text, ")");
> +			break;
> +		default:
> +			strcat(vs_text, uniforms[i].name);
> +			if (uniforms[i].is_array)
> +				strcat(vs_text, "[0]");
> +		}
> +		strcat(vs_text, ";\n");
> +	}
> +
> +	/* add the footer */
> +	strcat(vs_text, vs_footer);
> +
> +	/* Uncomment the following to view the generated shader */
> +	/*fprintf(stderr, "shader = '%s'\n", vs_text);*/
> +
> +	return vs_text;
> +}
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +	/* never called */
> +	return PIGLIT_FAIL;
> +}
> +
> +static struct builtin_uniform_t *
> +find_uniform(const char *name)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(uniforms); i++) {
> +		/* OpenGL ES 3.0 and OpenGL 4.2 require that the "[0]" be
> +		 * appended to the name.  Earlier versions of the spec are
> +		 * ambiguous.  Accept either name.
> +		*/
> +		if (strcmp(uniforms[i].name, name) == 0 ||
> +		    (strcmp(name + strlen(name) - 3, "[0]") == 0 &&
> +		     strncmp(uniforms[i].name, name, strlen(name) - 3) == 0))
> +			return &uniforms[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +	GLint numUniforms, i;
> +	bool pass = true;
> +	GLuint vs, prog;
> +	char *vs_text;
> +
> +	piglit_require_vertex_shader();
> +	piglit_require_fragment_shader();
> +
> +	vs_text = gen_vs_shader_all();
> +
> +	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text);
> +	prog = piglit_link_simple_program(vs, 0);
> +	if (!prog) {
> +		printf("Compilation error. Aborting...\n");
> +		piglit_report_result(PIGLIT_FAIL);
> +	}
> +
> +	glUseProgram(prog);
> +	free(vs_text);
> +
> +	glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &numUniforms);
> +	if (numUniforms != ARRAY_SIZE(uniforms)) {
> +		printf("Unexpected number of uniforms (found %d, expected "
> +		       "%lu)\n", numUniforms, ARRAY_SIZE(uniforms));
> +	}
> +
> +	/* check the types of the active uniforms and check which ones got
> +	 * references by glGetActiveUniform for later comparaison. */
> +	for (i = 0; i < numUniforms; i++) {
> +		struct builtin_uniform_t *uniform;
> +		GLcharARB name[100];
> +		GLsizei len;
> +		GLint size;
> +		GLenum type;
> +
> +		glGetActiveUniform(prog, i, sizeof(name), &len, &size, &type,
> +				   name);
> +
> +		uniform = find_uniform(name);
> +
> +		if (!uniform) {
> +			fprintf(stderr, "Cannot find uniform '%s'\n", name);
> +			pass = false;
> +			continue;
> +		}
> +
> +		uniform->found = true;
> +
> +		if (type != uniform->type) {
> +			printf("Wrong type for '%s' (found %s(0x%x)), "
> +			       "expected %s(0x%x))\n",
> +				name, piglit_get_gl_enum_name(type), type,
> +				piglit_get_gl_enum_name(uniform->type),
> +				uniform->type);
> +				pass = false;
> +		}
> +	}
> +
> +	/* check that no uniform got forgotten as there is the possibility that
> +	 * one got referenced twice!
> +	 */
> +	for (i = 0; i < ARRAY_SIZE(uniforms); i++) {
> +		if (uniforms[i].found == false) {
> +			fprintf(stderr, "uniform '%s' is missing from the "
> +					"active uniform list!\n",
> +				uniforms[i].name);
> +
> +			/* A missing builtin is legal, as stated by page 80
> +			 * (page 94 of the PDF) of the OpenGL 2.1 spec:
> +			 *
> +			 * "The returned uniform name can be the name of
> +			 * built-in uniform state as well."
> +			 */
> +
> +			/* FIXME: verify that the missing uniform as not been
> +			 * forgotten by the implementation. One way could have
> +			 * been to count the number of components used by the
> +			 * uniforms and add more components until reaching
> +			 * shader then adding other uniforms to reach
> +			 * GL_MAX_VERTEX_UNIFORM_COMPONENTS. If the shader still
> +			 * compiles, and assuming that
> +			 * GL_MAX_VERTEX_UNIFORM_COMPONENTS reports a good value
> +			 * then we can assume that the compiler just replaced
> +			 * the uniform with something else. If it does not
> +			 * compile, then it probably lied somewhere!
> +			 *
> +			 * The problem with this approach is that counting the
> +			 * number of components used for some types such as
> +			 * matrices is implementation-dependent...
> +			 *
> +			 * Until we have such a way to verify, let's not fail
> +			 * the test!
> +			 */
> +		}
> +	}
> +
> +	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
> +}
>


More information about the Piglit mailing list