[Piglit] [PATCH] tex3d-maxsize: rewrite to be more robust and do more testing

Alejandro PiƱeiro apinheiro at igalia.com
Wed Jul 20 08:45:55 UTC 2016


On 13/07/16 23:47, Brian Paul wrote:
> 1. It seems with NVIDIA's driver that using a proxy texture isn't a
> sure fire way to know that a given texture format/size can actually be
> created.  Update the find_max_tex3d_size() function to actually try
> creating a texture with glTexImage3D/glTexStorage3D and see if it
> works.
>
> 2. Improve the speed of texture initialization by copying the first
> 3D slice to the other slices with glCopyImageSubData().
>
> 3. Use glTexStorage3D when GL_ARB_texture_storage is supported.
>
> 4. In addition to GL_RGBA8, test GL_INTENSITY8 and GL_RGBA32F formats.
>
> 5. Before testing the largest possible texture, try a couple smaller
> sizes as a sanity check.
>
> 6. Loosen the piglit probe tolerance by one bit to account for inaccuracy
> caused by GL_NEAREST filtering.
>
> Tested with NVIDIA driver, VMware driver and llvmpipe.

I just tested with intel i965 Haswell, and it also works fine. Looks
good to me, but I have a small question below.

> ---
>  tests/texturing/tex3d-maxsize.c | 285 +++++++++++++++++++++++++++++-----------
>  1 file changed, 211 insertions(+), 74 deletions(-)
>
> diff --git a/tests/texturing/tex3d-maxsize.c b/tests/texturing/tex3d-maxsize.c
> index e168d14..60c9c63 100644
> --- a/tests/texturing/tex3d-maxsize.c
> +++ b/tests/texturing/tex3d-maxsize.c
> @@ -30,31 +30,88 @@
>  
>  PIGLIT_GL_TEST_CONFIG_BEGIN
>  
> -	config.supports_gl_compat_version = 10;
> +	config.supports_gl_compat_version = 12;
>  
>  	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
>  
>  PIGLIT_GL_TEST_CONFIG_END
>  
> -static const char *TestName = "tex3d-maxsize";
> +
> +static GLint MaxSize;
> +
> +
> +
> +/**
> + * Compute size (in megabytes) of a texture of the given dimensions and
> + * internal format.
> + */
> +static unsigned
> +tex_size(GLenum internalFormat, int width, int height, int depth)
> +{
> +	uint64_t sz;
> +
> +	sz = (uint64_t) width * (uint64_t) height * (uint64_t) depth;
> +
> +	switch (internalFormat) {
> +	case GL_INTENSITY8:
> +		sz *= 1;
> +		break;
> +	case GL_RGBA8:
> +		sz *= 4;
> +		break;
> +	case GL_RGBA32F:
> +		sz *= 16;
> +		break;
> +	default:
> +		assert(!"Unexpected internalFormat");
> +	}
> +
> +	return (unsigned) (sz / (uint64_t) (1024 * 1024));
> +}
> +
> +
> +/**
> + * Allocate a 1-level 3D texture.
> + */
> +static void
> +alloc_tex3d(GLenum target, GLenum internalFormat,
> +	    GLsizei width, GLsizei height, GLsizei depth)
> +{
> +	if (target == GL_TEXTURE_3D) {
> +		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
> +		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
> +	}
> +
> +	if (piglit_is_extension_supported("GL_ARB_texture_storage")) {
> +		glTexStorage3D(target, 1, internalFormat,
> +			       width, height, depth);
> +	}
> +	else {
> +		glTexImage3D(target, 0, internalFormat,
> +			     width, height, depth, 0,
> +			     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
> +	}
> +}
>  
>  
>  /*
>   * Use proxy texture to find largest possible 3D texture size.
>   */
>  static void
> -find_max_tex3d_size(GLint initSize, GLint *width, GLint *height, GLint *depth)
> +find_max_tex3d_size(GLenum internalFormat,
> +		    GLint initSize, GLint *width, GLint *height, GLint *depth)
>  {
>  	GLint dim = 0, w, h, d, pw, ph, pd;
>  
> +	piglit_check_gl_error(GL_NO_ERROR);
> +
>  	w = h = d = initSize;
>  
>  	while (w >= 1 && h >= 1 && d >= 1) {
>  		/* try proxy image */
>  		const int level = 0;
>  
> -		glTexImage3D(GL_PROXY_TEXTURE_3D, level, GL_RGBA8,
> -			     w, h, d, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
> +		alloc_tex3d(GL_PROXY_TEXTURE_3D, internalFormat, w, h, d);
>  
>  		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, level,
>  					 GL_TEXTURE_WIDTH, &pw);
> @@ -63,12 +120,40 @@ find_max_tex3d_size(GLint initSize, GLint *width, GLint *height, GLint *depth)
>  		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, level,
>  					 GL_TEXTURE_DEPTH, &pd);
>  
> +		if (!piglit_check_gl_error(GL_NO_ERROR)) {
> +			printf("Unexpected error during texture proxy test.\n");
> +			piglit_report_result(PIGLIT_FAIL);
> +		}
> +
>  		if (pw == w && ph == h && pd == d) {
> -			/* success! */
> -			*width = w;
> -			*height = h;
> -			*depth = d;
> -			return;
> +			/* this size should be supported, but test it to
> +			 * be sure.
> +			 */
> +			GLuint tex;
> +			GLenum err;
> +
> +			/* Create a texture object for the non-proxy texture below */
> +			glGenTextures(1, &tex);
> +			glBindTexture(GL_TEXTURE_3D, tex);
> +			alloc_tex3d(GL_TEXTURE_3D, internalFormat, w, h, d);
> +
> +			err = glGetError();
> +
> +			glDeleteTextures(1, &tex);
> +
> +			if (err == GL_NO_ERROR) {
> +				/* success! */
> +				*width = w;
> +				*height = h;
> +				*depth = d;
> +				return;
> +			}
> +			else {
> +				printf("Note: proxy texture of size "
> +				       "%d x %d x %d worked, but actual "
> +				       "glTexImage3D call failed!\n",
> +				       w, h, d);
> +			}
>  		}
>  
>  		/* halve one of the dimensions and try again */
> @@ -84,70 +169,39 @@ find_max_tex3d_size(GLint initSize, GLint *width, GLint *height, GLint *depth)
>  }
>  
>  
> -enum piglit_result
> -piglit_display(void)
> +/**
> + * Create a 3D texture of the given format and size, draw a textured quad
> + * with that texture, and check results.
> + */
> +static bool
> +test_render(GLenum internalFormat, int width, int height, int depth)
>  {
> -	GLuint tex;
> -	GLint maxsize, width, height, depth;
> -	GLenum err;
> +	static const float c1[4] = {0.25, 0.25, 0.25, 1.0};
> +	static const float c2[4] = {0.75, 0.75, 0.75, 1.0};
> +	bool pass = true;
>  	char *data;
>  	int i, j;
> -	GLboolean pass = GL_TRUE;
> -	float c1[4] = {0.25, 0.25, 0.25, 1.0};
> -	float c2[4] = {0.75, 0.75, 0.75, 1.0};
> -
> -	piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
> +	GLuint tex;
> +	unsigned mbytes = tex_size(internalFormat, width, height, depth);
>  
> -	glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxsize);
> +	printf("Testing %d x %d x %d %s (%u MB) texture\n",
> +	       width, height, depth,
> +	       piglit_get_gl_enum_name(internalFormat), mbytes);
> +	fflush(stdout);
>  
> -	/* Create the texture. */
>  	glGenTextures(1, &tex);
>  	glBindTexture(GL_TEXTURE_3D, tex);
> -	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
> -	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
> -	if (glGetError())
> -		return PIGLIT_FAIL;
> -
> -	glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, maxsize, maxsize, maxsize, 0,
> -		     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
> -
> -	err = glGetError();
> -
> -	if (err == GL_OUT_OF_MEMORY) {
> +	alloc_tex3d(GL_TEXTURE_3D, internalFormat, width, height, depth);
>  
> -		/* use proxy texture to find working max texture size */
> -		width = height = depth = 0;
> -		find_max_tex3d_size(maxsize, &width, &height, &depth);
> -
> -		printf("Max 3D texture size: %d x %d x %d\n",
> -		       width, height, depth);
> -		fflush(stdout);
> -
> -		glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, width, height, depth, 0,
> -			     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
> -		err = glGetError();
> -
> -		if (err == GL_OUT_OF_MEMORY)
> -			return PIGLIT_PASS;
> -	}
> -	else {
> -		/* the max 3D texture size actually worked */
> -		width = height = depth = maxsize;
> -	}
> -
> -	if (err != GL_NO_ERROR) {
> -		printf("%s: unexpected glTexImage3D error: 0x%x\n",
> -		       TestName, err);
> -		return PIGLIT_FAIL;
> +	if (!piglit_check_gl_error(GL_NO_ERROR)) {
> +		printf("Creating texture failed in test_render().\n");
> +		pass = false;
> +		goto end;
>  	}
>  
> -	if (0)
> -		printf("max 3D texture size = %d x %d x %d\n",
> -		       width, height, depth);
> -
>  	/* Set its pixels, slice by slice. */
>  	data = malloc(width * height * 4);
> -	for (j = 0; j < height; j++)
> +	for (j = 0; j < height; j++) {
>  		for (i = 0; i < width; i++) {
>  			int a = (j * width + i) * 4;
>  			data[a+0] =
> @@ -155,26 +209,45 @@ piglit_display(void)
>  			data[a+2] =
>  			data[a+3] = (i * 255) / (width - 1);
>  		}
> +	}
>  
> -	for (i = 0; i < depth; i++) {
> -		glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, width, height, 1,
> +	if (piglit_is_extension_supported("GL_ARB_copy_image")) {
> +		/* load 0th slice */
> +		glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
> +				width, height, 1,
>  				GL_RGBA, GL_UNSIGNED_BYTE, data);
> +
> +		/* copy 0th slice to other slices (should be faster) */
> +		for (i = 1; i < depth; i++) {
> +			glCopyImageSubData(tex, GL_TEXTURE_3D, 0, 0, 0, 0,
> +					   tex, GL_TEXTURE_3D, 0, 0, 0, i,
> +					   width, height, 1);
> +		}
> +	}
> +	else {
> +		/* load each slice with glTexSubImage3D */
> +		for (i = 0; i < depth; i++) {
> +			glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i,
> +					width, height, 1,
> +					GL_RGBA, GL_UNSIGNED_BYTE, data);
> +		}
>  	}
>  	free(data);
>  
> +	glClear(GL_COLOR_BUFFER_BIT);
> +
>  	/* Now try basic rendering. */
>  	glEnable(GL_TEXTURE_3D);
>  	glBegin(GL_QUADS);
> -	glTexCoord3f(0, 0, 1);
> +	glTexCoord3f(0, 0, 0.5);
>  	glVertex2f(0, 0);
> -	glTexCoord3f(0, 1, 1);
> +	glTexCoord3f(0, 1, 0.5);
>  	glVertex2f(0, piglit_height);
> -	glTexCoord3f(1, 1, 1);
> +	glTexCoord3f(1, 1, 0.5);
>  	glVertex2f(piglit_width, piglit_height);
> -	glTexCoord3f(1, 0, 1);
> +	glTexCoord3f(1, 0, 0.5);

Any reason to change the texcoords?

>  	glVertex2f(piglit_width, 0);
>  	glEnd();
> -	glDeleteTextures(1, &tex);
>  
>  	pass = piglit_probe_pixel_rgb(piglit_width * 1 / 4,
>  				      piglit_height * 1 / 4, c1) && pass;
> @@ -187,17 +260,81 @@ piglit_display(void)
>  	piglit_present_results();
>  
>  	if (!pass) {
> -		printf("%s: failed at size %d x %d x %d\n", TestName,
> -		       width, height, depth);
> +		printf("rendering failed with %d x %d x %d %s texture\n",
> +		       width, height, depth,
> +		       piglit_get_gl_enum_name(internalFormat));
> +	}
> +
> +end:
> +	glDeleteTextures(1, &tex);
> +
> +	return pass;
> +}
> +
> +
> +static bool
> +test_3d_tex_format(GLenum internalFormat)
> +{
> +	GLint width, height, depth;
> +	bool pass = true;
> +	unsigned mbytes;
> +
> +	piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
> +
> +	/* use proxy texture to find actual max texture size */
> +	width = height = depth = 0;
> +	find_max_tex3d_size(internalFormat, MaxSize,
> +			    &width, &height, &depth);
> +
> +	mbytes = tex_size(internalFormat, width, height, depth);
> +	printf("Actual max 3D texture size for %s: %d x %d x %d (%u MB)\n",
> +	       piglit_get_gl_enum_name(internalFormat),
> +	       width, height, depth, mbytes);
> +
> +	/* first, try some smaller res 3D texture rendering */
> +	pass = test_render(internalFormat, width, height, depth/4);
> +	pass = test_render(internalFormat, width, height, depth/2) && pass;
> +
> +	/* test largest 3D texture size */
> +	pass = test_render(internalFormat, width, height, depth) && pass;
> +
> +	return pass;
> +}
> +
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +	bool pass;
> +
> +	glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &MaxSize);
> +	printf("GL_MAX_3D_TEXTURE_SIZE = %d\n", MaxSize);
> +
> +	pass = test_3d_tex_format(GL_INTENSITY8);
> +
> +	pass = test_3d_tex_format(GL_RGBA8) && pass;
> +
> +	if (piglit_is_extension_supported("GL_ARB_texture_float")) {
> +		pass = test_3d_tex_format(GL_RGBA32F) && pass;
>  	}
>  
>  	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
>  }
>  
> +
>  void piglit_init(int argc, char **argv)
>  {
> -	piglit_require_gl_version(12);
> -
>  	glDisable(GL_DITHER);
> -}
>  
> +	/* Set the tolerance a little looser since we're using GL_NEAREST
> +	 * texture sampling.  GL_NEAREST is fastest for software rendering.
> +	 * We probably wouldn't have to loosen the tolerance if we used
> +	 * GL_LINEAR filtering.
> +	 */
> +	piglit_set_tolerance_for_bits(7, 7, 7, 7);
> +	printf("Probe tolerance: %f, %f, %f, %f\n",
> +	       piglit_tolerance[0],
> +	       piglit_tolerance[1],
> +	       piglit_tolerance[2],
> +	       piglit_tolerance[3]);
> +}




More information about the Piglit mailing list