[Piglit] [PATCH 3/3] GL 3.2: Test layered framebuffers clear the depth attachment properly.
Paul Berry
stereotype441 at gmail.com
Wed Sep 4 10:34:48 PDT 2013
(Note: Cc'ing Chad, since this test erroneously passes on i965 due to a
subtle HiZ bug. See my comments below)
On 3 September 2013 15:52, Jacob Penner <jkpenner91 at gmail.com> wrote:
> ---
> tests/all.tests | 1 +
> .../gl-3.2/layered-rendering/CMakeLists.gl.txt | 1 +
> tests/spec/gl-3.2/layered-rendering/clear-depth.c | 185
> +++++++++++++++++++++
> 3 files changed, 187 insertions(+)
> create mode 100644 tests/spec/gl-3.2/layered-rendering/clear-depth.c
>
> diff --git a/tests/all.tests b/tests/all.tests
> index 59fb0e2..c6d0c71 100644
> --- a/tests/all.tests
> +++ b/tests/all.tests
> @@ -750,6 +750,7 @@ spec['!OpenGL 3.2/get-integer-64iv'] =
> concurrent_test('gl-3.2-get-integer-64iv'
> spec['!OpenGL 3.2/get-integer-64v'] =
> concurrent_test('gl-3.2-get-integer-64v')
> spec['!OpenGL 3.2/layered-rendering/blit'] =
> concurrent_test('gl-3.2-layered-rendering-blit')
> spec['!OpenGL 3.2/layered-rendering/clear-color'] =
> concurrent_test('gl-3.2-layered-rendering-clear-color')
> +spec['!OpenGL 3.2/layered-rendering/clear-depth'] =
> concurrent_test('gl-3.2-layered-rendering-clear-depth')
> spec['!OpenGL 3.2/layered-rendering/framebuffertexture-buffer-textures']
> =
> concurrent_test('gl-3.2-layered-rendering-framebuffertexture-buffer-textures')
> spec['!OpenGL 3.2/layered-rendering/readpixels'] =
> concurrent_test('gl-3.2-layered-rendering-readpixels')
> spec['!OpenGL 3.2/layered-rendering/gl-layer'] =
> concurrent_test('gl-3.2-layered-rendering-gl-layer')
> diff --git a/tests/spec/gl-3.2/layered-rendering/CMakeLists.gl.txt
> b/tests/spec/gl-3.2/layered-rendering/CMakeLists.gl.txt
> index 9a26b34..bc4415d 100644
> --- a/tests/spec/gl-3.2/layered-rendering/CMakeLists.gl.txt
> +++ b/tests/spec/gl-3.2/layered-rendering/CMakeLists.gl.txt
> @@ -11,6 +11,7 @@ link_libraries (
>
> piglit_add_executable (gl-3.2-layered-rendering-blit blit.c)
> piglit_add_executable (gl-3.2-layered-rendering-clear-color clear-color.c)
> +piglit_add_executable (gl-3.2-layered-rendering-clear-depth clear-depth.c)
> piglit_add_executable
> (gl-3.2-layered-rendering-framebuffertexture-buffer-textures
> framebuffertexture-buffer-textures.c)
> piglit_add_executable (gl-3.2-layered-rendering-readpixels readpixels.c)
> piglit_add_executable (gl-3.2-layered-rendering-gl-layer gl-layer.c)
> diff --git a/tests/spec/gl-3.2/layered-rendering/clear-depth.c
> b/tests/spec/gl-3.2/layered-rendering/clear-depth.c
> new file mode 100644
> index 0000000..9c0cd53
> --- /dev/null
> +++ b/tests/spec/gl-3.2/layered-rendering/clear-depth.c
> @@ -0,0 +1,185 @@
> +/*
> + * Copyright © 2013 Intel Corporation
> + *
> + * 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 clear-depth.c
> + *
> + * Section 4.4.7(Framebuffer Objects) From GL spec 3.2 core:
> + * When the Clear or ClearBuffer* commands are used to clear a layered
> + * framebuffer attachment, all layers of the attachment are cleared.
> + *
> + * Test Layout
> + * Tex1 Tex2
> + * *--------*--------*
> + * | layer4 | layer4 |
> + * *--------*--------* Each Layer for both tex1 and tex2 will be
> + * | layer3 | layer3 | different depths.
> + * *--------*--------*
> + * | layer2 | layer2 | Tex1 will be cleared using glClear()
> + * *--------*--------*
> + * | layer1 | layer1 | Tex2 will be cleared using glClearBuffer()
> + * *--------*--------*
> + *
> + * Result:
> + * Layer 1-4 of both tex1 and tex2 should be the clearDepth
> + */
> +
> +#include "piglit-util-gl-common.h"
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> + config.supports_gl_compat_version = 32;
> + config.supports_gl_core_version = 32;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +bool
> +probe_texture_layered_depth(GLuint texture, int x, int y, int z,
> + int w, int h, int d, float *expected)
> +{
> + GLint prev_read_fbo;
> + GLint prev_draw_fbo;
> +
> + GLuint fbo;
> + int i, j, k;
> +
> + GLfloat *probe;
> + GLfloat *pixels = malloc(w*h*sizeof(float));
> +
> + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_draw_fbo);
> + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &prev_read_fbo);
> +
> + glGenFramebuffers(1, &fbo);
> + glBindFramebuffer(GL_FRAMEBUFFER, fbo);
> +
> + for(k = z; k < z+d; k++ ) {
>
I prefer how you did this in patch 2, where k runs from 0 to d, and then
you use "k+d" in the call to glFramebufferTextureLayer call below. That
way if the caller passes a nonzero value for z, then expected[0] is the
expected depth value of the first layer to be probed.
> +
> + glFramebufferTextureLayer(GL_FRAMEBUFFER,
> GL_DEPTH_ATTACHMENT,
> + texture, 0, k);
> +
> + glReadPixels(x, y, w, h, GL_DEPTH_COMPONENT, GL_FLOAT,
> pixels);
> +
> + for(j = 0; j < h; j++) {
> + for(i = 0; i < w; i++) {
> + probe = &pixels[j*w+i];
> + if (fabs(*probe - expected[k]) >= 0.01) {
> + printf("Probe depth at
> (%i,%i,%i)\n", x+i, y+j,z+k);
> + printf(" Expected: %f\n",
> expected[k]);
> + printf(" Observed: %f\n", *probe);
> +
> + free(pixels);
> + return false;
> + }
> + }
> + }
> + }
> + free(pixels);
> +
> + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prev_draw_fbo);
> + glBindFramebuffer(GL_READ_FRAMEBUFFER, prev_read_fbo);
> + return true;
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +
> + int i, j;
> + GLenum fbstatus;
> + bool pass = true;
> + GLuint fbo[2], texture[2];
> +
> + float depthData[4][10*10];
> + float depths[4] = {
> + 0.25, 0.5, 0.75, 1.0
> + };
> +
> + GLfloat clearDepth = 0.0;
> + float expected[4] = { 0.0, 0.0, 0.0, 0.0 };
> +
> + /* Create depth data for textures */
> + for(j = 0; j < 4; j++) {
> + for(i = 0; i < 10*10; i++) {
> + depthData[j][i] = depths[j];
> + }
> + }
> +
> + glGenTextures(2, texture);
> + glGenFramebuffers(2, fbo);
> + for(i = 0; i < 2; i++) {
> + glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
> + glTexParameteri(GL_TEXTURE_2D_ARRAY,
> GL_TEXTURE_MIN_FILTER, GL_LINEAR);
> + glTexParameteri(GL_TEXTURE_2D_ARRAY,
> GL_TEXTURE_MAG_FILTER, GL_LINEAR);
> + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S,
> GL_REPEAT);
> + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T,
> GL_REPEAT);
> + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT16,
> + 10, 10, 4, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
> depthData);
> +
> + glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
> + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
> + texture[i], 0);
> +
> + fbstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
> + if(fbstatus != GL_FRAMEBUFFER_COMPLETE){
> + printf("%s\n", piglit_get_gl_enum_name(fbstatus));
> + piglit_report_result(PIGLIT_FAIL);
> + }
> +
> + if(!piglit_check_gl_error(GL_NO_ERROR))
> + piglit_report_result(PIGLIT_FAIL);
> + }
> +
> + /* Clear fbo 0 with glClear() */
> + glClearDepth(clearDepth);
> +
> + glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
> + glClear(GL_DEPTH_BUFFER_BIT);
> +
> + if(!probe_texture_layered_depth(texture[0], 0, 0, 0, 10,
> + 10, 4, expected)) {
> + printf("Incorrect depth values recieved with glClear()\n");
> + pass = false;
> + }
> +
> + /* Clear fbo 1 with glClearBuffer() */
> + glBindFramebuffer(GL_FRAMEBUFFER, fbo[1]);
> + glClearBufferfv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &clearDepth);
>
This needs to be:
glClearBufferfv(GL_DEPTH, 0, &clearDepth);
With this fixed, the test passes, which surprised me, because I expected it
to fail (I've looked at the code in Mesa, and we haven't implemented proper
handling for layered depth clears yet).
I did a little digging and here's what is happening:
When the buffer is first created, its contents are undefined. But in a
typical test run it happens to get allocated using zero-initialized pages,
and zero in the HiZ buffer means "clear", so the state looks like this:
depth buffer: all layers 0. hiz buffer: all layers clear. resolve map:
all layers need HiZ resolve
So far so good. When the initial buffer contents get uploaded using
glTexImage3D, the state becomes:
depth buffer: layers initialized to {.25, .5, .75, 1}. hiz buffer: all
layers clear. resolve map: all layers need HiZ resolve
This is also correct (the HiZ buffer being in the clear state is not a
problem because all layers are marked as needing a HiZ resolve).
The next thing that happens is glClear(). What glClear() *should* do is
put all layers of the hiz buffer in the "clear" state, and all layers of
the resolve map in the "need depth resolve" state. It does the correct
thing to the resolve map, but due to a bug it only clears layer 0 of the
HiZ buffer.
The problem is, all layers of the HiZ buffer are already in the clear
state, so we wind up in the correct state by accident:
depth buffer: layers initialized to {.25, .5, .75, 1}. hiz buffer: all
layers clear. resolve map: all layers need depth resolve
And so the test passes by dumb luck.
I think what we need to do is modify the test so that rather than
populating the buffer using glTexImage3D, it populates it by doing drawing
operations to all layers. That way the HiZ buffer will be in a more
realistic state by the time we try to do the clear, so the test will notice
if the clear fails to have the proper effect on all layers.
But I wouldn't mind a second opinion on that. Chad (or anyone else
familiar with HiZ on Intel), care to comment?
> +
> + if(!probe_texture_layered_depth(texture[1], 0, 0, 0, 10,
> + 10, 4, expected)) {
> + printf("Incorrect depth values recieved with
> glClearBuffer()\n");
> + pass = false;
> + }
> +
> + pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
> +
> + piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
> +}
> +
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> + /* UNREACHABLE */
> + return PIGLIT_FAIL;
> +}
> --
> 1.8.3.1
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20130904/d335874a/attachment-0001.html>
More information about the Piglit
mailing list