Reviewed-by: Roland Scheidegger <srol...@vmware.com>

Am 24.12.2017 um 23:41 schrieb Brian Paul:
> Create the largest possible 2D GL_RGBA_32F multisampled texture, load it
> with known values the read it back and see if the values match up.
> 
> The --array option runs the test with a 2D texture array instead of an
> MSAA texture.  There are other options to specify texture size, number of
> samples, fp16 and a texel value scale.
> 
> Fails with NVIDIA's driver.  See code comments.
> 
> Note: The entry in all.py limits the texture size to 512x512 so it runs
> in a reasonable amount of time.  Ideally, the texture size should be set
> in quick.py instead but I've been unable to make that work.
> 
> v2:
> * Fix a few code issues raised by Fabian Bieler, fix all.py, quick.py code.
> * Update comments about NVIDIA driver, per Roland.
> v3:
> * remove config.khr_no_error_support line.
> ---
>  tests/all.py                                       |   8 +
>  tests/quick.py                                     |  17 +
>  .../spec/arb_texture_multisample/CMakeLists.gl.txt |   1 +
>  .../arb_texture_multisample/large-float-texture.c  | 727 
> +++++++++++++++++++++
>  4 files changed, 753 insertions(+)
>  create mode 100644 tests/spec/arb_texture_multisample/large-float-texture.c
> 
> diff --git a/tests/all.py b/tests/all.py
> index 5d90e8f..d55cca9 100644
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -1651,6 +1651,14 @@ with profile.test_list.group_manager(
>  # Group ARB_texture_multisample
>  with profile.test_list.group_manager(
>          PiglitGLTest, grouptools.join('spec', 'ARB_texture_multisample')) as 
> g:
> +    g(['arb_texture_multisample-large-float-texture'], 'large-float-texture',
> +      run_concurrent=False)
> +    g(['arb_texture_multisample-large-float-texture', '--array'],
> +      'large-float-texture-array', run_concurrent=False)
> +    g(['arb_texture_multisample-large-float-texture', '--fp16'],
> +      'large-float-texture-fp16', run_concurrent=False)
> +    g(['arb_texture_multisample-large-float-texture', '--array', '--fp16'],
> +      'large-float-texture-array-fp16', run_concurrent=False)
>      g(['arb_texture_multisample-minmax'])
>      g(['texelFetch', 'fs', 'sampler2DMS', '4', '1x71-501x71'])
>      g(['texelFetch', 'fs', 'sampler2DMS', '4', '1x130-501x130'])
> diff --git a/tests/quick.py b/tests/quick.py
> index 1a7d674..53774e4 100644
> --- a/tests/quick.py
> +++ b/tests/quick.py
> @@ -68,6 +68,23 @@ with profile.test_list.group_manager(
>      with profile.test_list.allow_reassignment:
>          g(['ext_texture_env_combine-combine', '--quick'], 
> 'texture-env-combine')
>  
> +# Limit texture size to 512x512 for some texture_multisample tests.
> +# The default (max supported size) can be pretty slow.
> +with profile.test_list.group_manager(
> +        PiglitGLTest,
> +        grouptools.join('spec', 'ARB_texture_multisample')) as g:
> +    with profile.test_list.allow_reassignment:
> +        size_arg = ['--texsize', '512']
> +        g(['arb_texture_multisample-large-float-texture'] + size_arg,
> +          'large-float-texture', run_concurrent=False)
> +        g(['arb_texture_multisample-large-float-texture', '--array'] +
> +          size_arg, 'large-float-texture-array', run_concurrent=False)
> +        g(['arb_texture_multisample-large-float-texture', '--fp16'] +
> +          size_arg, 'large-float-texture-fp16', run_concurrent=False)
> +        g(['arb_texture_multisample-large-float-texture', '--array',
> +           '--fp16'] + size_arg,
> +          'large-float-texture-array-fp16', run_concurrent=False)
> +
>  # These take too long
>  profile.filters.append(lambda n, _: '-explosion' not in n)
>  profile.filters.append(FilterVsIn())
> diff --git a/tests/spec/arb_texture_multisample/CMakeLists.gl.txt 
> b/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
> index a347143..31965c4 100644
> --- a/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
> +++ b/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
> @@ -9,6 +9,7 @@ link_libraries (
>       ${OPENGL_gl_LIBRARY}
>  )
>  
> +piglit_add_executable (arb_texture_multisample-large-float-texture 
> large-float-texture.c)
>  piglit_add_executable (arb_texture_multisample-minmax minmax.c)
>  piglit_add_executable (arb_texture_multisample-errors errors.c)
>  piglit_add_executable (arb_texture_multisample-fb-completeness 
> fb-completeness.c)
> diff --git a/tests/spec/arb_texture_multisample/large-float-texture.c 
> b/tests/spec/arb_texture_multisample/large-float-texture.c
> new file mode 100644
> index 0000000..2e05a6e
> --- /dev/null
> +++ b/tests/spec/arb_texture_multisample/large-float-texture.c
> @@ -0,0 +1,727 @@
> +/*
> + * Copyright (c) 2017 VMware, Inc.
> + *
> + * 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.
> + */
> +
> +/** @file large-float-texture.c
> + *
> + * Test large MSAA float textures.  In particular, create/load a multisample
> + * texture then read it back and compare returned values.
> + * Also support array textures instead of MSAA as a sanity check / debug
> + * option.
> + *
> + * Some drivers/GPUs may fail this test.  NVIDIA, for example, appears to
> + * only store the MSAA coverage info, not the sample colors, for samples
> + * beyond the 8th sample.  We may tune the way this test operates over time
> + * to be more useful.  Maybe we should test all MSAA samples/pixels (2x,
> + * 4x, 8x, etc).
> + *
> + * See code for command line arguments.
> + */
> +
> +#include "piglit-util-gl.h"
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +     config.supports_gl_compat_version = 30;
> +     config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +
> +static bool verbose = false;
> +
> +
> +/**
> + * Try to create a GL_RGBA32F/16F texture of the given size, samples.
> + * Return 0 if failure.
> + */
> +static GLuint
> +create_texture(GLenum target, GLenum intFormat,
> +            GLsizei width, GLsizei height, GLuint numSamples)
> +{
> +     GLuint tex;
> +
> +     assert(intFormat == GL_RGBA32F || intFormat == GL_RGBA16F);
> +
> +     if (verbose) {
> +             printf("Trying %d x %d  %d samples/layers\n",
> +                    width, height, numSamples);
> +     }
> +
> +     glGenTextures(1, &tex);
> +     glBindTexture(target, tex);
> +     if (target == GL_TEXTURE_2D_MULTISAMPLE) {
> +             glTexImage2DMultisample(target,
> +                                     numSamples, intFormat, width, height,
> +                                     GL_FALSE); /* fixedsamplelocations */
> +     }
> +     else {
> +             /* instead of samples per pixel, use 'samples' layers */
> +             assert(target == GL_TEXTURE_2D_ARRAY);
> +             glTexStorage3D(target, 1, intFormat, width, height,
> +                            numSamples);
> +     }
> +
> +     if (glGetError() != GL_NO_ERROR) {
> +             /* some error */
> +             glDeleteTextures(1, &tex);
> +             tex = 0;
> +     }
> +
> +     return tex;
> +}
> +
> +
> +/**
> + * Find the max working texture size.
> + */
> +static GLuint
> +create_texture_max_size(GLenum target, GLenum intFormat,
> +                     GLsizei *width, GLsizei *height,
> +                     GLuint numSamples)
> +{
> +     GLint w, h;
> +     GLuint tex = 0;
> +
> +     w = *width;
> +     h = *height;
> +     while (w >= 1 && h >= 1) {
> +             tex = create_texture(target, intFormat, w, h, numSamples);
> +             if (tex) {
> +                     /* done! */
> +                     *width = w;
> +                     *height = h;
> +                     break;
> +             }
> +             /* try smaller size */
> +             if (h >= w) {
> +                     h /= 2;
> +             }
> +             else {
> +                     w /= 2;
> +             }
> +     }
> +
> +     return tex;
> +}
> +
> +
> +/**
> + * Create an FBO which wraps the given texture.
> + */
> +static GLuint
> +create_fbo(GLuint tex, GLenum texTarget)
> +{
> +     GLuint fbo;
> +
> +     assert(texTarget == GL_TEXTURE_2D_MULTISAMPLE ||
> +            texTarget == GL_TEXTURE_2D_ARRAY ||
> +            texTarget == GL_TEXTURE_2D);
> +
> +     glGenFramebuffers(1, &fbo);
> +     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
> +     if (texTarget == GL_TEXTURE_2D_MULTISAMPLE ||
> +         texTarget == GL_TEXTURE_2D) {
> +             glFramebufferTexture2D(GL_FRAMEBUFFER,
> +                                    GL_COLOR_ATTACHMENT0,
> +                                    texTarget, tex, 0);  /* 0=level */
> +     }
> +     else {
> +             assert(texTarget == GL_TEXTURE_2D_ARRAY);
> +             glFramebufferTextureLayer(GL_FRAMEBUFFER,
> +                                       GL_COLOR_ATTACHMENT0,
> +                                       tex, 0, 0);
> +     }
> +
> +     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
> +     if (status != GL_FRAMEBUFFER_COMPLETE) {
> +             if (verbose) {
> +                     printf("Failed to create FBO! (status = %s)\n",
> +                            piglit_get_gl_enum_name(status));
> +             }
> +             glDeleteFramebuffers(1, &fbo);
> +             fbo = 0;
> +     }
> +
> +     return fbo;
> +}
> +
> +
> +/**
> + * Load the GL_RGBA32F/16F MSAA (or array) texture with known values.
> + * The color components are basically:
> + *  x = texcoord in [0, 1]  (this can get fuzzy for large texture widths)
> + *  y = fragcoord.y MOD 16 in [0, 15]
> + *  z = -curSample in [-(numSamples-1), 0]
> + *  w = curSample in [0, numSamples-1]
> + */
> +static void
> +load_texture_image(GLenum target, GLuint fbo, GLuint tex,
> +                GLsizei width, GLsizei height, GLuint numSamples,
> +                GLfloat valueScale)
> +{
> +     static const char *vs_text =
> +             "#version 130\n"
> +             "out vec4 texcoord;\n"
> +             "void main() {\n"
> +             "  texcoord = gl_MultiTexCoord0;\n"
> +             "  gl_Position = gl_Vertex;\n"
> +             "}\n";
> +     static const char *fs_text =
> +             "#version 130\n"
> +             "out vec4 color;\n"
> +             "in vec4 texcoord;\n"
> +             "uniform int curSample;\n"
> +             "uniform float valueScale;\n"
> +             "void main() {\n"
> +             "   float x = texcoord.x; \n"
> +             "   float y = float(int(gl_FragCoord.y) % 16) / 16.0; \n"
> +             "   float z = -curSample; \n"
> +             "   float w = curSample; \n"
> +             "   color = valueScale * vec4(x, y, z, w); \n"
> +             "}\n";
> +
> +     GLuint prog;
> +
> +     prog = piglit_build_simple_program(vs_text, fs_text);
> +
> +     assert(prog);
> +     assert(numSamples <= 32);
> +
> +     glUseProgram(prog);
> +
> +     GLint curSampleUniform = glGetUniformLocation(prog, "curSample");
> +     assert(curSampleUniform >= 0);
> +
> +     GLint valueScaleUniform = glGetUniformLocation(prog, "valueScale");
> +     glUniform1f(valueScaleUniform, valueScale);
> +
> +     if (target == GL_TEXTURE_2D_MULTISAMPLE) {
> +             glEnable(GL_SAMPLE_MASK);
> +             glEnable(GL_MULTISAMPLE);
> +     }
> +
> +     GLint samp;
> +     for (samp = 0; samp < numSamples; samp++) {
> +             if (verbose) {
> +                     printf("Render sample/layer %d\n", samp);
> +             }
> +
> +             glUniform1i(curSampleUniform, samp);
> +
> +             /* choose sample or layer to write to */
> +             if (target == GL_TEXTURE_2D_MULTISAMPLE) {
> +                     glSampleMaski(0, 1u << samp);
> +             }
> +             else {
> +                     assert(target == GL_TEXTURE_2D_ARRAY);
> +                     glFramebufferTextureLayer(GL_FRAMEBUFFER,
> +                                               GL_COLOR_ATTACHMENT0,
> +                                               tex, 0, samp);
> +             }
> +
> +             /* Full framebuffer rect */
> +             piglit_draw_rect_tex(-1, -1, 2, 2,
> +                                  0, 0, 1, 1);
> +     }
> +
> +     if (target == GL_TEXTURE_2D_MULTISAMPLE) {
> +             glDisable(GL_SAMPLE_MASK);
> +             glDisable(GL_MULTISAMPLE);
> +     }
> +
> +     glDeleteProgram(prog);
> +}
> +
> +
> +/**
> + * Create simple 2D, GL_RGBA32F texture of given size.
> + */
> +static GLuint
> +create_float4_tex(GLsizei width, GLsizei height)
> +{
> +     GLuint tex;
> +
> +     glGenTextures(1, &tex);
> +     glBindTexture(GL_TEXTURE_2D, tex);
> +     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, width, height);
> +
> +     if (glGetError() != GL_NO_ERROR) {
> +             glDeleteTextures(1, &tex);
> +             tex = 0;
> +     }
> +     return tex;
> +}
> +
> +
> +/**
> + * Create the shader program needed for extracting texels from an
> + * MSAA (or array) texture.
> + */
> +static GLuint
> +create_readback_program(GLenum target)
> +{
> +     static const char *fs_text_msaa =
> +             "#version 130\n"
> +             "#extension GL_ARB_texture_multisample : enable\n"
> +             "out vec4 color;\n"
> +             "uniform sampler2DMS tex;\n"
> +             "uniform int sample;\n"
> +             "void main() {\n"
> +             "  ivec2 coord = ivec2(gl_FragCoord.xy);\n"
> +             "  color = texelFetch(tex, coord, sample);\n"
> +             "}\n";
> +
> +     static const char *fs_text_array =
> +             "#version 130\n"
> +             "out vec4 color;\n"
> +             "uniform sampler2DArray tex;\n"
> +             "uniform int sample;\n"
> +             "void main() {\n"
> +             "  ivec2 coord = ivec2(gl_FragCoord.xy);\n"
> +             "  color = texelFetch(tex, ivec3(coord, sample), 0);\n"
> +             "}\n";
> +
> +     const char *fs_text = target == GL_TEXTURE_2D_MULTISAMPLE ?
> +             fs_text_msaa : fs_text_array;
> +
> +     GLuint prog = piglit_build_simple_program(NULL, fs_text);
> +
> +     assert(prog);
> +
> +     return prog;
> +}
> +
> +/**
> + * Extract a slice or per-sample image from the src_tex.
> + */
> +static void
> +extract_texture_image(GLuint readbackProg,
> +                   GLuint src_tex, GLsizei width, GLsizei height,
> +                   GLuint sample)
> +{
> +     glUseProgram(readbackProg);
> +
> +     GLint texUniform = glGetUniformLocation(readbackProg, "tex");
> +     GLint sampleUniform = glGetUniformLocation(readbackProg, "sample");
> +
> +     /* Create texture to put results into, and wrap it in an FBO.
> +      * The shader will extract the sample from the MSAA texture (or
> +      * array layer) and write the results into a destination texture/FBO.
> +      */
> +     GLuint dst_tex = create_float4_tex(width, height);
> +     GLuint dst_fbo = create_fbo(dst_tex, GL_TEXTURE_2D);
> +
> +     glUniform1i(texUniform, 0);  // unit 0
> +     glUniform1i(sampleUniform, sample);
> +
> +     glBindFramebuffer(GL_FRAMEBUFFER, dst_fbo);
> +
> +     piglit_draw_rect_tex(-1, -1, 2, 2,
> +                          0, 0, 1, 1);
> +
> +     glBindTexture(GL_TEXTURE_2D, dst_tex);
> +
> +     /* Now, the extracted image is available both as dst_tex
> +      * and as the current FBO.
> +      */
> +}
> +
> +
> +/**
> + * Test if two float[4] values are nearly equal.
> + */
> +static bool
> +nearly_equal(const GLfloat x[4], const GLfloat y[4])
> +{
> +     /* XXX this tolerance was chosen emperically */
> +     const float maxRelDiff = 0.0005;
> +     int i;
> +     for (i = 0; i < 4; i++) {
> +             float diff = x[i] - y[i];
> +             float ax = fabsf(x[i]), ay = fabsf(y[i]);
> +             if (diff > MAX2(ax, ay) * maxRelDiff) {
> +                     return false;
> +             }
> +     }
> +
> +     return true;
> +}
> +
> +
> +/**
> + * To record +/- max difference between expected and rendered results.
> + */
> +struct error_info
> +{
> +     float min_error[4], max_error[4];
> +     float avg_error[4];
> +     unsigned num_fail;
> +};
> +
> +
> +static void
> +init_error_info(struct error_info *err)
> +{
> +     int i;
> +     for (i = 0; i < 4; i++) {
> +             err->min_error[i] = 1e20;
> +             err->max_error[i] = -1e20;
> +             err->avg_error[i] = 0.0;
> +     }
> +     err->num_fail = 0;
> +}
> +
> +
> +static bool
> +nonzero(const float a[4])
> +{
> +     return a[0] != 0.0 ||a[1] != 0.0 ||a[2] != 0.0 ||a[3] != 0.0;
> +}
> +
> +
> +static void
> +finish_and_print_error_info(struct error_info *err,
> +                         GLsizei width, GLsizei height)
> +{
> +     int i;
> +     for (i = 0; i < 4; i++) {
> +             err->avg_error[i] /= width * height;
> +     }
> +     if (verbose ||
> +         nonzero(err->min_error) ||
> +         nonzero(err->max_error) ||
> +         nonzero(err->avg_error)) {
> +             printf("Min error: %g %g %g %g\n",
> +                    err->min_error[0], err->min_error[1],
> +                    err->min_error[2], err->min_error[3]);
> +             printf("Max error: %g %g %g %g\n",
> +                    err->max_error[0], err->max_error[1],
> +                    err->max_error[2], err->max_error[3]);
> +             printf("Avg error: %g %g %g %g\n",
> +                    err->avg_error[0], err->avg_error[1],
> +                    err->avg_error[2], err->avg_error[3]);
> +             printf("num_fail: %u\n", err->num_fail);
> +     }
> +}
> +
> +
> +static void
> +update_error_info(struct error_info *err,
> +               const GLfloat a[4], const GLfloat b[4])
> +{
> +     bool fail = false;
> +     int i;
> +
> +     for (i = 0; i < 4; i++) {
> +             float delta = a[i] - b[i];
> +             err->min_error[i] = MIN2(err->min_error[i], delta);
> +             err->max_error[i] = MAX2(err->max_error[i], delta);
> +
> +             err->avg_error[i] += fabsf(delta);
> +
> +             if (delta != 0.0f) {
> +                     fail = true;
> +             }
> +     }
> +
> +     err->num_fail += (unsigned) fail;
> +}
> +
> +
> +static unsigned
> +texel_size(GLenum intFormat)
> +{
> +     switch (intFormat) {
> +     case GL_RGBA16F:
> +             return 4 * sizeof(GLhalf);
> +     case GL_RGBA32F:
> +             return 4 * sizeof(GLfloat);
> +     default:
> +             assert(!"Unexpected texture format");
> +     }
> +}
> +
> +
> +/**
> + * Read back all texture samples, compare to reference.
> + */
> +static bool
> +validate_texture_image(GLenum target,
> +                    GLenum intFormat,
> +                    GLuint readbackProg,
> +                    GLuint src_tex,
> +                    GLsizei width, GLsizei height, GLuint numSamples,
> +                    GLfloat valueScale)
> +{
> +     /*
> +      * Note: this is a little more complicated than just mallocing
> +      * a buffer of size width * height * numSamples * texelSize
> +      * because we could easily exceed 4GB.  So, we read back the image
> +      * in stripes no larger than 512MB.
> +      */
> +     const size_t buffer_size = 512 * 1024 * 1024;  // 512 MB
> +     GLfloat *buffer = malloc(buffer_size);
> +     assert(buffer);
> +
> +     const int bytesPerRow = width * numSamples * texel_size(intFormat);
> +     const int stripeHeight = MIN2(buffer_size / bytesPerRow, height);
> +
> +     bool pass = true;
> +     float fwidth = (float) width;
> +     GLuint samp;
> +
> +     glBindTexture(target, src_tex);
> +
> +     for (samp = 0; samp < numSamples; samp++) {
> +             struct error_info err;
> +
> +             init_error_info(&err);
> +
> +             if (verbose) {
> +                     printf("Checking sample/layer %d\n", samp);
> +             }
> +
> +             extract_texture_image(readbackProg, src_tex,
> +                                   width, height, samp);
> +
> +             GLint i, j, numFail = 0;
> +
> +             for (j = 0; j < height; j++) {
> +
> +                     if (j % stripeHeight == 0) {
> +                             /* read a stripe */
> +                             if (height == stripeHeight) {
> +                                     /* get whole texture with GetTexImage */
> +                                     glGetTexImage(GL_TEXTURE_2D, 0,
> +                                                   GL_RGBA, GL_FLOAT,
> +                                                   buffer);
> +                             }
> +                             else {
> +                                     /* use glReadPixels to get a stripe */
> +                                     glReadPixels(0, j, width, stripeHeight,
> +                                                  GL_RGBA, GL_FLOAT, buffer);
> +                             }
> +                     }
> +
> +                     for (i = 0; i < width; i++) {
> +                             int row = j % stripeHeight;
> +                             const GLfloat *texel =
> +                                     buffer + (width * row + i) * 4;
> +                             GLfloat expected[4];
> +
> +                             /* [0] is texcoord at center of fragment */
> +                             expected[0] = i / fwidth + (0.5f / fwidth);
> +                             /* [1] is fragcoord.y MOD 16 / 16.0 */
> +                             expected[1] = (j % 16) / 16.0;
> +                             expected[2] = -1.0 * samp;
> +                             expected[3] = samp;
> +
> +                             expected[0] *= valueScale;
> +                             expected[1] *= valueScale;
> +                             expected[2] *= valueScale;
> +                             expected[3] *= valueScale;
> +
> +                             update_error_info(&err, texel, expected);
> +
> +                             if (!nearly_equal(texel, expected)) {
> +                                     printf("Fail at %d, %d:\n", i, j);
> +                                     printf("  Expected %g, %g, %g, %g\n",
> +                                            expected[0], expected[1],
> +                                            expected[2], expected[3]);
> +                                     printf("  Found %g, %g, %g, %g\n",
> +                                            texel[0], texel[1],
> +                                            texel[2], texel[3]);
> +                                     pass = false;
> +                                     numFail++;
> +                                     if (numFail >= 5) {
> +                                             goto end;
> +                                     }
> +                             }
> +                     }
> +             }
> +             finish_and_print_error_info(&err, width, height);
> +     }
> +
> +end:
> +     free(buffer);
> +
> +     return pass;
> +}
> +
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +     GLenum target = GL_TEXTURE_2D_MULTISAMPLE;
> +     GLenum intFormat = GL_RGBA32F;
> +     GLint samples = -1;  /* or array slices */
> +     GLint maxSize = -1;
> +     GLsizei width = -1, height = -1;
> +     GLfloat valueScale = 1.0;
> +     int i;
> +
> +     for (i = 1; i < argc; i++) {
> +             if (strcmp(argv[i], "--array") == 0) {
> +                     target = GL_TEXTURE_2D_ARRAY;
> +             }
> +             else if (strcmp(argv[i], "--samples") == 0) {
> +                     i++;
> +                     samples = atoi(argv[i]);
> +                     assert(samples > 0);
> +             }
> +             else if (strcmp(argv[i], "--texsize") == 0) {
> +                     i++;
> +                     maxSize = atoi(argv[i]);
> +                     assert(maxSize > 0);
> +             }
> +             else if (strcmp(argv[i], "--width") == 0) {
> +                     i++;
> +                     width = atoi(argv[i]);
> +                     assert(width > 0);
> +             }
> +             else if (strcmp(argv[i], "--height") == 0) {
> +                     i++;
> +                     height = atoi(argv[i]);
> +                     assert(height > 0);
> +             }
> +             else if (strcmp(argv[i], "--scale") == 0) {
> +                     i++;
> +                     valueScale = atof(argv[i]);
> +                     assert(valueScale > 0.0);
> +             }
> +             else if (strcmp(argv[i], "--fp16") == 0) {
> +                     intFormat = GL_RGBA16F;
> +             }
> +             else if (strcmp(argv[i], "--verbose") == 0) {
> +                     verbose = true;
> +             }
> +             else {
> +                     printf("Unknown option %s\n", argv[i]);
> +                     piglit_report_result(PIGLIT_FAIL);
> +             }
> +     }
> +
> +     piglit_require_extension("GL_ARB_texture_float");
> +     piglit_require_extension("GL_ARB_texture_multisample");
> +     piglit_require_GLSL_version(130);
> +
> +     if (maxSize == -1) {
> +             glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
> +     }
> +
> +     if (samples == -1) {
> +             if (target == GL_TEXTURE_2D_MULTISAMPLE) {
> +                     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &samples);
> +             }
> +             else {
> +                     samples = 16;  /* 16 texture array layers */
> +             }
> +     }
> +
> +     GLuint tex, fbo = 0;
> +
> +     if (width == -1 || height == -1) {
> +             width = height = maxSize;
> +     }
> +
> +     while (width > 1 && height > 1) {
> +             tex = create_texture_max_size(target, intFormat,
> +                                           &width, &height, samples);
> +
> +             if (!tex) {
> +                     printf("Failed to create MSAA texture\n");
> +                     piglit_report_result(PIGLIT_FAIL);
> +             }
> +
> +             fbo = create_fbo(tex, target);
> +             if (!fbo) {
> +                     /* texture creation worked, but FBO failed.
> +                      * Try smaller texture.
> +                      */
> +                     glDeleteTextures(1, &tex);
> +                     if (height >= width) {
> +                             height /= 2;
> +                     }
> +                     else {
> +                             width /= 2;
> +                     }
> +             }
> +             else {
> +                     break;
> +             }
> +     }
> +
> +     if (!fbo) {
> +             printf("Failed to create FBO\n");
> +             piglit_report_result(PIGLIT_SKIP);
> +     }
> +
> +     GLint64 mbytes = (GLint64) width * height * samples
> +             * texel_size(intFormat) / (1024 * 1024);
> +
> +     const char *formatName = piglit_get_gl_enum_name(intFormat);
> +     if (target == GL_TEXTURE_2D_ARRAY) {
> +             printf("Created %d x %d %d-layer %s texture/FBO"
> +                    " (%lld MB)\n",
> +                    width, height, samples, formatName,
> +                    (long long int) mbytes);
> +     }
> +     else {
> +             printf("Created %d x %d %d-sample MSAA %s texture/FBO"
> +                    " (%lld MB)\n",
> +                    width, height, samples, formatName,
> +                    (long long int) mbytes);
> +     }
> +
> +     GLuint readbackProg = create_readback_program(target);
> +
> +     glViewport(0, 0, width, height);
> +     glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
> +     glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
> +
> +     if (verbose) {
> +             printf("Loading...\n");
> +     }
> +
> +     load_texture_image(target, fbo, tex, width, height,
> +                        samples, valueScale);
> +
> +     if (verbose) {
> +             printf("Validating...\n");
> +     }
> +
> +     bool pass = validate_texture_image(target, intFormat, readbackProg, tex,
> +                                        width, height, samples, valueScale);
> +
> +     if (!piglit_check_gl_error(GL_NO_ERROR)) {
> +             pass = false;
> +     }
> +
> +     piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
> +}
> +
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +     /* should never get here */
> +     return PIGLIT_FAIL;
> +}
> 

_______________________________________________
Piglit mailing list
Piglit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to