[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