| // |
| // Copyright 2015 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. |
| // |
| // PackUnpackTest: |
| // Tests the corrrectness of opengl 4.1 emulation of pack/unpack built-in functions. |
| // |
| |
| #include "test_utils/ANGLETest.h" |
| |
| using namespace angle; |
| |
| namespace |
| { |
| |
| class PackUnpackTest : public ANGLETest |
| { |
| protected: |
| PackUnpackTest() |
| { |
| setWindowWidth(16); |
| setWindowHeight(16); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| |
| void SetUp() override |
| { |
| ANGLETest::SetUp(); |
| |
| // Vertex Shader source |
| const std::string vs = SHADER_SOURCE |
| ( #version 300 es\n |
| precision mediump float; |
| in vec4 position; |
| |
| void main() |
| { |
| gl_Position = position; |
| } |
| ); |
| |
| // clang-format off |
| // Fragment Shader source |
| const std::string sNormFS = SHADER_SOURCE |
| ( #version 300 es\n |
| precision mediump float; |
| uniform mediump vec2 v; |
| layout(location = 0) out mediump vec4 fragColor; |
| |
| void main() |
| { |
| uint u = packSnorm2x16(v); |
| vec2 r = unpackSnorm2x16(u); |
| fragColor = vec4(r, 0.0, 1.0); |
| } |
| ); |
| |
| // Fragment Shader source |
| const std::string uNormFS = SHADER_SOURCE |
| ( #version 300 es\n |
| precision mediump float; |
| uniform mediump vec2 v; |
| layout(location = 0) out mediump vec4 fragColor; |
| |
| void main() |
| { |
| uint u = packUnorm2x16(v); |
| vec2 r = unpackUnorm2x16(u); |
| fragColor = vec4(r, 0.0, 1.0); |
| } |
| ); |
| |
| // Fragment Shader source |
| const std::string halfFS = SHADER_SOURCE |
| ( #version 300 es\n |
| precision mediump float; |
| uniform mediump vec2 v; |
| layout(location = 0) out mediump vec4 fragColor; |
| |
| void main() |
| { |
| uint u = packHalf2x16(v); |
| vec2 r = unpackHalf2x16(u); |
| fragColor = vec4(r, 0.0, 1.0); |
| } |
| ); |
| // clang-format on |
| |
| mSNormProgram = CompileProgram(vs, sNormFS); |
| mUNormProgram = CompileProgram(vs, uNormFS); |
| mHalfProgram = CompileProgram(vs, halfFS); |
| if (mSNormProgram == 0 || mUNormProgram == 0 || mHalfProgram == 0) |
| { |
| FAIL() << "shader compilation failed."; |
| } |
| |
| glGenTextures(1, &mOffscreenTexture2D); |
| glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, getWindowWidth(), getWindowHeight()); |
| |
| glGenFramebuffers(1, &mOffscreenFramebuffer); |
| glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOffscreenTexture2D, 0); |
| |
| glViewport(0, 0, 16, 16); |
| |
| const GLfloat color[] = { 1.0f, 1.0f, 0.0f, 1.0f }; |
| glClearBufferfv(GL_COLOR, 0, color); |
| } |
| |
| void TearDown() override |
| { |
| glDeleteTextures(1, &mOffscreenTexture2D); |
| glDeleteFramebuffers(1, &mOffscreenFramebuffer); |
| glDeleteProgram(mSNormProgram); |
| glDeleteProgram(mUNormProgram); |
| glDeleteProgram(mHalfProgram); |
| |
| ANGLETest::TearDown(); |
| } |
| |
| void compareBeforeAfter(GLuint program, float input1, float input2) |
| { |
| compareBeforeAfter(program, input1, input2, input1, input2); |
| } |
| |
| void compareBeforeAfter(GLuint program, float input1, float input2, float expect1, float expect2) |
| { |
| GLint vec2Location = glGetUniformLocation(program, "v"); |
| |
| glUseProgram(program); |
| glUniform2f(vec2Location, input1, input2); |
| |
| drawQuad(program, "position", 0.5f); |
| |
| ASSERT_GL_NO_ERROR(); |
| |
| GLfloat p[2] = { 0 }; |
| glReadPixels(8, 8, 1, 1, GL_RG, GL_FLOAT, p); |
| |
| ASSERT_GL_NO_ERROR(); |
| |
| static const double epsilon = 0.0005; |
| EXPECT_NEAR(p[0], expect1, epsilon); |
| EXPECT_NEAR(p[1], expect2, epsilon); |
| } |
| |
| GLuint mSNormProgram; |
| GLuint mUNormProgram; |
| GLuint mHalfProgram; |
| GLuint mOffscreenFramebuffer; |
| GLuint mOffscreenTexture2D; |
| }; |
| |
| // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating normal floating numbers. |
| TEST_P(PackUnpackTest, PackUnpackSnormNormal) |
| { |
| // Expect the shader to output the same value as the input |
| compareBeforeAfter(mSNormProgram, 0.5f, -0.2f); |
| compareBeforeAfter(mSNormProgram, -0.35f, 0.75f); |
| compareBeforeAfter(mSNormProgram, 0.00392f, -0.99215f); |
| compareBeforeAfter(mSNormProgram, 1.0f, -0.00392f); |
| } |
| |
| // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating normal floating |
| // numbers. |
| TEST_P(PackUnpackTest, PackUnpackUnormNormal) |
| { |
| // Expect the shader to output the same value as the input |
| compareBeforeAfter(mUNormProgram, 0.5f, 0.2f, 0.5f, 0.2f); |
| compareBeforeAfter(mUNormProgram, 0.35f, 0.75f, 0.35f, 0.75f); |
| compareBeforeAfter(mUNormProgram, 0.00392f, 0.99215f, 0.00392f, 0.99215f); |
| compareBeforeAfter(mUNormProgram, 1.0f, 0.00392f, 1.0f, 0.00392f); |
| } |
| |
| // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating normal floating numbers. |
| TEST_P(PackUnpackTest, PackUnpackHalfNormal) |
| { |
| // TODO(cwallez) figure out why it is broken on Intel on Mac |
| #if defined(ANGLE_PLATFORM_APPLE) |
| if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE) |
| { |
| std::cout << "Test skipped on Intel on Mac." << std::endl; |
| return; |
| } |
| #endif |
| |
| // Expect the shader to output the same value as the input |
| compareBeforeAfter(mHalfProgram, 0.5f, -0.2f); |
| compareBeforeAfter(mHalfProgram, -0.35f, 0.75f); |
| compareBeforeAfter(mHalfProgram, 0.00392f, -0.99215f); |
| compareBeforeAfter(mHalfProgram, 1.0f, -0.00392f); |
| } |
| |
| // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating subnormal floating numbers. |
| TEST_P(PackUnpackTest, PackUnpackSnormSubnormal) |
| { |
| // Expect the shader to output the same value as the input |
| compareBeforeAfter(mSNormProgram, 0.00001f, -0.00001f); |
| } |
| |
| // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating subnormal |
| // floating numbers. |
| TEST_P(PackUnpackTest, PackUnpackUnormSubnormal) |
| { |
| // Expect the shader to output the same value as the input for positive numbers and clamp |
| // to [0, 1] |
| compareBeforeAfter(mUNormProgram, 0.00001f, -0.00001f, 0.00001f, 0.0f); |
| } |
| |
| // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating subnormal floating numbers. |
| TEST_P(PackUnpackTest, PackUnpackHalfSubnormal) |
| { |
| // Expect the shader to output the same value as the input |
| compareBeforeAfter(mHalfProgram, 0.00001f, -0.00001f); |
| } |
| |
| // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating zero floating numbers. |
| TEST_P(PackUnpackTest, PackUnpackSnormZero) |
| { |
| // Expect the shader to output the same value as the input |
| compareBeforeAfter(mSNormProgram, 0.00000f, -0.00000f); |
| } |
| |
| // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating zero floating |
| // numbers. |
| TEST_P(PackUnpackTest, PackUnpackUnormZero) |
| { |
| compareBeforeAfter(mUNormProgram, 0.00000f, -0.00000f, 0.00000f, 0.00000f); |
| } |
| |
| // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating zero floating numbers. |
| TEST_P(PackUnpackTest, PackUnpackHalfZero) |
| { |
| // Expect the shader to output the same value as the input |
| compareBeforeAfter(mHalfProgram, 0.00000f, -0.00000f); |
| } |
| |
| // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating overflow floating |
| // numbers. |
| TEST_P(PackUnpackTest, PackUnpackUnormOverflow) |
| { |
| // Expect the shader to clamp the input to [0, 1] |
| compareBeforeAfter(mUNormProgram, 67000.0f, -67000.0f, 1.0f, 0.0f); |
| } |
| |
| // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating overflow floating numbers. |
| TEST_P(PackUnpackTest, PackUnpackSnormOverflow) |
| { |
| // Expect the shader to clamp the input to [-1, 1] |
| compareBeforeAfter(mSNormProgram, 67000.0f, -67000.0f, 1.0f, -1.0f); |
| } |
| |
| // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. |
| ANGLE_INSTANTIATE_TEST(PackUnpackTest, |
| ES3_OPENGL(3, 3), |
| ES3_OPENGL(4, 0), |
| ES3_OPENGL(4, 1), |
| ES3_OPENGL(4, 2), |
| ES3_OPENGL(4, 3), |
| ES3_OPENGL(4, 4), |
| ES3_OPENGL(4, 5), |
| ES3_OPENGLES()); |
| } |