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

Brian Paul brianp at vmware.com
Mon Jul 25 23:39:01 UTC 2016


On 07/20/2016 02:45 AM, Alejandro PiƱeiro wrote:
> 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?

Not especially.  I wanted to sample from the center slice of the texture 
to make sure it was filled in correctly.  But r=1 should accomplish that 
too.

R-b?

-Brian

>
>>   	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]);
>> +}
>
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/piglit
>



More information about the Piglit mailing list