Edit

kc3-lang/angle/src/tests/gl_tests/DepthStencilTest.cpp

Branch :

  • Show log

    Commit

  • Author : Tobin Ehlis
    Date : 2019-11-11 16:41:07
    Hash : 1a01b4b3
    Message : Refactor end2end test macros This is a foundational CL to enabling the end2end tests on swiftshader. Refactored infrastructure with new ANGLE_INSTANTIATE_TEST_ES* macros that will run tests over all various combinations of all platforms for different ES versions. Just skipping failing tests initially to get the refactor landed. Bug: angleproject:4081 Bug: angleproject:4092 Change-Id: I017f6c3267179e49b6ae08cc7488096b423dcdb5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1904635 Commit-Queue: Tobin Ehlis <tobine@google.com> Reviewed-by: Courtney Goeltzenleuchter <courtneygo@google.com>

  • src/tests/gl_tests/DepthStencilTest.cpp
  • //
    // Copyright 2018 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // DepthStencilTest:
    //   Tests covering depth- or stencil-only rendering to make sure the other non-existing aspect is
    //   not affecting the results (since the format may be emulated with one that has both aspects).
    //
    
    #include "test_utils/ANGLETest.h"
    
    #include "platform/FeaturesVk.h"
    #include "test_utils/gl_raii.h"
    
    using namespace angle;
    
    namespace
    {
    
    class DepthStencilTest : public ANGLETest
    {
      protected:
        DepthStencilTest()
        {
            setWindowWidth(128);
            setWindowHeight(128);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
            setConfigDepthBits(24);
            setConfigStencilBits(8);
        }
    
        void testSetUp() override
        {
            glBindTexture(GL_TEXTURE_2D, mColorTexture);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
                         GL_UNSIGNED_BYTE, nullptr);
    
            // Setup Color/Stencil FBO with a stencil format that's emulated with packed depth/stencil.
            glBindFramebuffer(GL_FRAMEBUFFER, mColorStencilFBO);
    
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTexture,
                                   0);
            glBindRenderbuffer(GL_RENDERBUFFER, mStencilTexture);
            glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(),
                                  getWindowHeight());
            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
                                      mStencilTexture);
    
            ASSERT_GL_NO_ERROR();
    
            // Note: GL_DEPTH_COMPONENT24 is allowed in GLES2 with GL_OES_depth24 extension.
            if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_OES_depth24"))
            {
                // Setup Color/Depth FBO with a depth format that's emulated with packed depth/stencil.
                glBindFramebuffer(GL_FRAMEBUFFER, mColorDepthFBO);
    
                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                       mColorTexture, 0);
                glBindRenderbuffer(GL_RENDERBUFFER, mDepthTexture);
                glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, getWindowWidth(),
                                      getWindowHeight());
                glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
                                          mDepthTexture);
            }
    
            ASSERT_GL_NO_ERROR();
        }
    
        void bindColorStencilFBO()
        {
            glBindFramebuffer(GL_FRAMEBUFFER, mColorStencilFBO);
            mHasDepth = false;
        }
    
        void bindColorDepthFBO()
        {
            glBindFramebuffer(GL_FRAMEBUFFER, mColorDepthFBO);
            mHasStencil = false;
        }
    
        // Override a feature to force emulation of stencil-only and depth-only formats with a packed
        // depth/stencil format
        void overrideFeaturesVk(FeaturesVk *featuresVk) override
        {
            featuresVk->overrideFeatures({"force_fallback_format"}, true);
        }
    
        void prepareSingleEmulatedWithPacked();
        void ensureColor(GLColor color);
        void ensureDepthUnaffected();
        void ensureStencilUnaffected();
    
      private:
        GLFramebuffer mColorStencilFBO;
        GLFramebuffer mColorDepthFBO;
        GLTexture mColorTexture;
        GLRenderbuffer mDepthTexture;
        GLRenderbuffer mStencilTexture;
    
        bool mHasDepth   = true;
        bool mHasStencil = true;
    };
    
    void DepthStencilTest::ensureColor(GLColor color)
    {
        const int width  = getWindowWidth();
        const int height = getWindowHeight();
    
        std::vector<GLColor> pixelData(width * height);
        glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data());
    
        for (int i = 0; i < width * height; i += 16)
        {
            GLColor actualColor = pixelData[i];
            EXPECT_NEAR(color.R, actualColor.R, 1);
            EXPECT_NEAR(color.G, actualColor.G, 1);
            EXPECT_NEAR(color.B, actualColor.B, 1);
            EXPECT_NEAR(color.A, actualColor.A, 1);
    
            if (i % width == 0)
                i += 16 * width;
        }
    }
    
    void DepthStencilTest::ensureDepthUnaffected()
    {
        ANGLE_GL_PROGRAM(depthTestProgram, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_EQUAL);
        drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), 0.123f);
        glDisable(GL_DEPTH_TEST);
        ASSERT_GL_NO_ERROR();
    
        // Since depth shouldn't exist, the drawQuad above should succeed in turning the whole image
        // blue.
        ensureColor(GLColor::blue);
    }
    
    void DepthStencilTest::ensureStencilUnaffected()
    {
        ANGLE_GL_PROGRAM(stencilTestProgram, essl1_shaders::vs::Passthrough(),
                         essl1_shaders::fs::Green());
        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_EQUAL, 0x1B, 0xFF);
        drawQuad(stencilTestProgram, essl1_shaders::PositionAttrib(), 0.0f);
        glDisable(GL_STENCIL_TEST);
        ASSERT_GL_NO_ERROR();
    
        // Since stencil shouldn't exist, the drawQuad above should succeed in turning the whole image
        // green.
        ensureColor(GLColor::green);
    }
    
    void DepthStencilTest::prepareSingleEmulatedWithPacked()
    {
        const int w     = getWindowWidth();
        const int h     = getWindowHeight();
        const int whalf = w >> 1;
        const int hhalf = h >> 1;
    
        // Clear to a random color, 0.75 depth and 0x36 stencil
        Vector4 color1(0.1f, 0.2f, 0.3f, 0.4f);
        GLColor color1RGB(color1);
    
        glClearColor(color1[0], color1[1], color1[2], color1[3]);
        glClearDepthf(0.75f);
        glClearStencil(0x36);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        ASSERT_GL_NO_ERROR();
    
        // Verify color was cleared correctly.
        EXPECT_PIXEL_COLOR_NEAR(0, 0, color1RGB, 1);
    
        // Use masked color to clear two channels of the image to a second color, 0.25 depth and 0x59
        // stencil.
        Vector4 color2(0.2f, 0.4f, 0.6f, 0.8f);
        glClearColor(color2[0], color2[1], color2[2], color2[3]);
        glClearDepthf(0.25f);
        glClearStencil(0x59);
        glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        ASSERT_GL_NO_ERROR();
    
        GLColor color2RGB(Vector4(color2[0], color1[1], color2[2], color1[3]));
    
        EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, color2RGB, 1);
    
        EXPECT_PIXEL_COLOR_NEAR(0, 0, color2RGB, 1);
        EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, color2RGB, 1);
        EXPECT_PIXEL_COLOR_NEAR(0, h - 1, color2RGB, 1);
        EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, color2RGB, 1);
    
        // Use scissor to clear the center to a third color, 0.5 depth and 0xA9 stencil.
        glEnable(GL_SCISSOR_TEST);
        glScissor(whalf / 2, hhalf / 2, whalf, hhalf);
    
        Vector4 color3(0.3f, 0.5f, 0.7f, 0.9f);
        GLColor color3RGB(color3);
        glClearColor(color3[0], color3[1], color3[2], color3[3]);
        glClearDepthf(0.5f);
        glClearStencil(0xA9);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        glDisable(GL_SCISSOR_TEST);
        ASSERT_GL_NO_ERROR();
    
        EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, color3RGB, 1);
    
        EXPECT_PIXEL_COLOR_NEAR(0, 0, color2RGB, 1);
        EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, color2RGB, 1);
        EXPECT_PIXEL_COLOR_NEAR(0, h - 1, color2RGB, 1);
        EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, color2RGB, 1);
    
        // Use scissor to draw to the right half of the image with a fourth color, 0.6 depth and 0x84
        // stencil.
        glEnable(GL_SCISSOR_TEST);
        glScissor(whalf, 0, whalf, h);
    
        ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_ALWAYS, 0x84, 0xFF);
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
        glStencilMask(0xFF);
        drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.2f);
    
        glDisable(GL_STENCIL_TEST);
        glDisable(GL_SCISSOR_TEST);
    }
    
    // Tests that clearing or rendering into a depth-only format doesn't affect stencil.
    TEST_P(DepthStencilTest, DepthOnlyEmulatedWithPacked)
    {
        ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_depth24"));
    
        bindColorDepthFBO();
        prepareSingleEmulatedWithPacked();
        ensureStencilUnaffected();
    }
    
    // Tests that clearing or rendering into a stencil-only format doesn't affect depth.
    TEST_P(DepthStencilTest, StencilOnlyEmulatedWithPacked)
    {
        // http://anglebug.com/4092
        ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D9());
        bindColorStencilFBO();
        prepareSingleEmulatedWithPacked();
        ensureDepthUnaffected();
    }
    
    ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DepthStencilTest);
    
    }  // anonymous namespace