[Piglit] [PATCH] fbo: add a test for blending with float special values

Ilia Mirkin imirkin at alum.mit.edu
Sun Nov 5 17:46:12 UTC 2017


On Sun, Nov 5, 2017 at 12:31 PM, Brian Paul <brianp at vmware.com> wrote:
> On 11/04/2017 02:44 PM, Ilia Mirkin wrote:
>>
>> See what happens when doing 0 * Inf and NaN.
>>
>> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
>> ---
>>
>> Not sure if this is worth checking in. I was just wondering what various
>> hardware did, and this covers many of the permutations. This test can be
>> run both in core profile, or with the -compat flag to force a compat
>> profile.
>> Perhaps different drivers do things differently for the two.
>>
>> On nouveau/nvc0, it assumes 0*inf = 0, on nouveau/nv50 it assumes 0*inf =
>> nan.
>> On i965/skl, it assumes 0*inf = nan. (I have patches to change nv50 to
>> match
>> the nvc0 behavior - it's configurable on both.)
>>
>> I'd be curious to hear what (a) radeonsi and r600 do and (b) how this
>> works
>> on the various blob drivers. For the blob drivers, you should run it with
>> both -compat and without, to see if the behavior is different. If it
>> prints
>> lots of stuff, that means the hw does 0*inf = nan. If it prints nothing
>> out,
>> then it think sthat 0*inf = 0. Either way, I'd be interested in hearing
>> what the full output is.
>>
>> Note that the piglit always passes, since there is no right or wrong here.
>>
>>   tests/fbo/CMakeLists.gl.txt |   2 +
>>   tests/fbo/fbo-float-nan.c   | 159
>> ++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 161 insertions(+)
>>   create mode 100644 tests/fbo/fbo-float-nan.c
>>
>> diff --git a/tests/fbo/CMakeLists.gl.txt b/tests/fbo/CMakeLists.gl.txt
>> index 2e2cac9d9..2db8bf700 100644
>> --- a/tests/fbo/CMakeLists.gl.txt
>> +++ b/tests/fbo/CMakeLists.gl.txt
>> @@ -97,4 +97,6 @@ piglit_add_executable (fbo-cubemap fbo-cubemap.c)
>>   piglit_add_executable (fbo-scissor-bitmap fbo-scissor-bitmap.c)
>>   piglit_add_executable (fbo-viewport fbo-viewport.c)
>>
>> +piglit_add_executable (fbo-float-nan fbo-float-nan.c)
>> +
>>   # vim: ft=cmake:
>> diff --git a/tests/fbo/fbo-float-nan.c b/tests/fbo/fbo-float-nan.c
>> new file mode 100644
>> index 000000000..ccbf53ae5
>> --- /dev/null
>> +++ b/tests/fbo/fbo-float-nan.c
>> @@ -0,0 +1,159 @@
>> +/*
>> + * Copyright © 2017 Ilia Mirkin <imirkin at alum.mit.edu>
>> + *
>> + * 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.
>> + */
>> +
>> +/*
>> + * The purpose of this test is to find out what happens when the
>> + * shader produces a NaN value with a floating point RT. This is all
>> + * undefined as far as the GL spec goes, but it's useful to be able to
>> + * compare implementations.
>> + */
>> +
>> +#include "piglit-util-gl.h"
>> +
>> +PIGLIT_GL_TEST_CONFIG_BEGIN
>> +       config.supports_gl_core_version = 31;
>> +       config.window_visual = PIGLIT_GL_VISUAL_RGBA |
>> PIGLIT_GL_VISUAL_DOUBLE;
>> +       config.khr_no_error_support = PIGLIT_NO_ERRORS;
>> +PIGLIT_GL_TEST_CONFIG_END
>> +
>> +static const char *vs_text =
>> +       "#version 130 \n"
>> +       "in vec4 piglit_vertex; \n"
>> +       "void main() { \n"
>> +       "  gl_Position = piglit_vertex; \n"
>> +       "}\n";
>> +
>> +static const char *fs_text =
>> +       "#version 130 \n"
>> +       "#extension GL_ARB_shader_bit_encoding: require \n"
>> +       "out vec4 color; \n"
>> +       "uniform uint c; \n"
>> +       "uniform uint a; \n"
>> +       "void main() { \n"
>> +       "  color = vec4(vec3(uintBitsToFloat(c)), uintBitsToFloat(a)); \n"
>> +       "}\n";
>> +
>> +GLuint program, fb, rb;
>> +
>> +static const unsigned uINF = 0x7f800000;
>> +static const unsigned uNAN = 0x7fc00000;
>> +
>> +bool is_nan(unsigned arg) {
>
>
> Brace on next line.
>
>
>> +       return ((arg & 0x7f800000) == 0x7f800000) &&
>> +               (arg & 0x007fffff);
>> +}
>> +
>> +void test_draw(unsigned u_c, unsigned u_a, unsigned r, unsigned g,
>> unsigned b, unsigned a)
>> +{
>> +       unsigned pixel[4];
>> +
>> +       glUniform1ui(glGetUniformLocation(program, "c"), u_c);
>> +       glUniform1ui(glGetUniformLocation(program, "a"), u_a);
>> +       piglit_draw_rect(-1, -1, 2, 2);
>> +       glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel);
>> +
>> +       bool rmatch = pixel[0] == r || (is_nan(pixel[0]) && is_nan(r));
>> +       bool gmatch = pixel[1] == g || (is_nan(pixel[1]) && is_nan(g));
>> +       bool bmatch = pixel[2] == b || (is_nan(pixel[2]) && is_nan(b));
>> +       bool amatch = pixel[3] == a || (is_nan(pixel[3]) && is_nan(a));
>> +       if (!rmatch || !gmatch || !bmatch || !amatch)
>> +               printf("Unexpected result c=%x, a=%x: %x %x %x %x != %x %x
>> %x %x\n",
>> +                      u_c, u_a,
>> +                      pixel[0], pixel[1], pixel[2], pixel[3],
>> +                      r, g, b, a);
>> +}
>> +
>> +void run_test() {
>
>
> Brace on next line.
>
>> +       glBindFramebuffer(GL_FRAMEBUFFER, fb);
>> +       glClearColor(0, 0, 0, 0);
>> +
>> +       printf("Testing without blending.\n");
>> +       glDisable(GL_BLEND);
>> +       test_draw(0, 0, 0, 0, 0, 0);
>> +       test_draw(uINF, uINF, uINF, uINF, uINF, uINF);
>> +       test_draw(uNAN, uNAN, uNAN, uNAN, uNAN, uNAN);
>> +
>> +       printf("Testing with blending src SRC_ALPHA + dst ZERO.\n");
>
>
> src * SRC_ALPHA + dst * ZERO  ?
>
> and below
>
>
>> +       glEnable(GL_BLEND);
>> +       glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
>> +       test_draw(0, uNAN, 0, 0, 0, uNAN); /* NaN * NaN = NaN? */
>> +       test_draw(uNAN, 0, 0, 0, 0, 0);
>> +       test_draw(0, uINF, 0, 0, 0, uINF);
>> +       test_draw(uINF, 0, 0, 0, 0, 0);
>> +       test_draw(uINF, uNAN, uNAN, uNAN, uNAN, uNAN); /* NaN * Inf = NaN
>> */
>> +       test_draw(uNAN, uINF, uNAN, uNAN, uNAN, uINF); /* NaN * Inf = NaN
>> */
>> +
>> +       printf("Testing with blending src DST_ALPHA + dst ZERO.\n");
>> +       glBlendFunc(GL_DST_ALPHA, GL_ZERO);
>> +       /* Zero in DST_ALPHA */
>> +       glClear(GL_COLOR_BUFFER_BIT);
>> +       test_draw(uINF, uNAN, 0, 0, 0, 0);
>> +       /* Get infinity into DST_ALPHA */
>> +       glDisable(GL_BLEND);
>> +       test_draw(0, uINF, 0, 0, 0, uINF);
>> +       glEnable(GL_BLEND);
>> +       test_draw(0, uINF, 0, 0, 0, uINF);
>> +
>> +       /* Get NaN into DST_ALPHA */
>> +       glDisable(GL_BLEND);
>> +       test_draw(0, uNAN, 0, 0, 0, uNAN);
>> +       glEnable(GL_BLEND);
>> +       test_draw(0, uINF, 0, 0, 0, uNAN);
>> +}
>> +
>> +enum piglit_result piglit_display(void)
>> +{
>> +       return PIGLIT_PASS;
>> +}
>> +
>> +void piglit_init(int argc, char **argv)
>> +{
>> +       piglit_require_extension("GL_ARB_shader_bit_encoding");
>
>
> Maybe move the test to tests/spec/arb_shader_bit_encoding/ ?

Well, it's really a blending test, where I just like to use the shader
bit encoding stuff to avoid any questions about whether the
infinity/NaN are *really* making it through to the shader outputs. I'd
be concerned about using float uniforms. I guess a UBO would be safe
enough though?

>
> Looks OK otherwise.
>
> Reviewed-by: Brian Paul <brianp at vmware.com>

Thanks. I actually followed up with a v2 which includes arguments to
pass in for different expectaitons (e.g. 0*inf = nan, and whether
GL_ZERO counts as 0 wins or doing the IEEE calc. It's tricky since if
there's no DST, it seems reasonable for the GPU to never even load the
DST and not find out that the DST has an infinity. This is the i965
behavior.)

But do you think it's reasonable to have this type of program in
piglit? It's not really a test, more of a debugging/informational aid.

So far I've confirmed that NVIDIA blob drivers on Kepler do it the
0*inf=0 way, both compat and core.

>
>
>
>> +       program = piglit_build_simple_program(vs_text, fs_text);
>> +       glUseProgram(program);
>> +
>> +       glGenFramebuffers(1, &fb);
>> +       glBindFramebuffer(GL_FRAMEBUFFER, fb);
>> +
>> +       glGenRenderbuffers(1, &rb);
>> +       glBindRenderbuffer(GL_RENDERBUFFER, rb);
>> +
>> +       glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
>> +                                 GL_RENDERBUFFER, rb);
>> +
>> +       printf("Testing GL_RGBA16F\n");
>> +       glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA16F, 64, 64);
>> +       run_test();
>> +
>> +       printf("Testing GL_RGBA32F\n");
>> +       glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 64, 64);
>> +       run_test();
>> +
>> +#if 0
>> +       printf("Testing GL_RGBA8. Lots of failures expected.\n");
>> +       glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
>> +       run_test();
>> +#endif
>> +
>> +       piglit_report_result(PIGLIT_PASS);
>> +}
>>
>


More information about the Piglit mailing list