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

Brian Paul brianp at vmware.com
Sun Nov 5 18:03:22 UTC 2017


On 11/05/2017 10:46 AM, Ilia Mirkin wrote:
> 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?

Probably.

>
>>
>> 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.

I'm fine with it.  Maybe someday this won't be undefined behavior.

v2 R-b.


>
> 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