• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // PackUnpackTest:
7 //   Tests the corrrectness of opengl 4.1 emulation of pack/unpack built-in functions.
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 
12 using namespace angle;
13 
14 namespace
15 {
16 
17 class PackUnpackTest : public ANGLETest
18 {
19   protected:
PackUnpackTest()20     PackUnpackTest()
21     {
22         setWindowWidth(16);
23         setWindowHeight(16);
24         setConfigRedBits(8);
25         setConfigGreenBits(8);
26         setConfigBlueBits(8);
27         setConfigAlphaBits(8);
28     }
29 
testSetUp()30     void testSetUp() override
31     {
32         // Fragment Shader source
33         constexpr char kSNormFS[] = R"(#version 300 es
34 precision mediump float;
35 uniform mediump vec2 v;
36 layout(location = 0) out mediump vec4 fragColor;
37 
38 void main()
39 {
40     highp uint u = packSnorm2x16(v);
41     vec2 r = unpackSnorm2x16(u);
42     fragColor = vec4(r, 0.0, 1.0);
43 })";
44 
45         // Fragment Shader source
46         constexpr char kUNormFS[] = R"(#version 300 es
47 precision mediump float;
48 uniform mediump vec2 v;
49 layout(location = 0) out mediump vec4 fragColor;
50 
51 void main()
52 {
53     highp uint u = packUnorm2x16(v);
54     vec2 r = unpackUnorm2x16(u);
55     fragColor = vec4(r, 0.0, 1.0);
56 })";
57 
58         // Fragment Shader source
59         constexpr char kHalfFS[] = R"(#version 300 es
60 precision mediump float;
61 uniform mediump vec2 v;
62 layout(location = 0) out mediump vec4 fragColor;
63 
64 void main()
65 {
66     highp uint u = packHalf2x16(v);
67     vec2 r = unpackHalf2x16(u);
68     fragColor = vec4(r, 0.0, 1.0);
69 })";
70 
71         mSNormProgram = CompileProgram(essl3_shaders::vs::Simple(), kSNormFS);
72         mUNormProgram = CompileProgram(essl3_shaders::vs::Simple(), kUNormFS);
73         mHalfProgram  = CompileProgram(essl3_shaders::vs::Simple(), kHalfFS);
74         if (mSNormProgram == 0 || mUNormProgram == 0 || mHalfProgram == 0)
75         {
76             FAIL() << "shader compilation failed.";
77         }
78 
79         glGenTextures(1, &mOffscreenTexture2D);
80         glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
81         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG32F, getWindowWidth(), getWindowHeight());
82 
83         glGenFramebuffers(1, &mOffscreenFramebuffer);
84         glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
85         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
86                                mOffscreenTexture2D, 0);
87 
88         glViewport(0, 0, 16, 16);
89 
90         const GLfloat color[] = {1.0f, 1.0f, 0.0f, 1.0f};
91         glClearBufferfv(GL_COLOR, 0, color);
92     }
93 
testTearDown()94     void testTearDown() override
95     {
96         glDeleteTextures(1, &mOffscreenTexture2D);
97         glDeleteFramebuffers(1, &mOffscreenFramebuffer);
98         glDeleteProgram(mSNormProgram);
99         glDeleteProgram(mUNormProgram);
100         glDeleteProgram(mHalfProgram);
101     }
102 
compareBeforeAfter(GLuint program,float input1,float input2)103     void compareBeforeAfter(GLuint program, float input1, float input2)
104     {
105         compareBeforeAfter(program, input1, input2, input1, input2);
106     }
107 
compareBeforeAfter(GLuint program,float input1,float input2,float expect1,float expect2)108     void compareBeforeAfter(GLuint program,
109                             float input1,
110                             float input2,
111                             float expect1,
112                             float expect2)
113     {
114         // TODO(anglebug.com/5491) iOS doesn't support float32 framebuffers.
115         ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
116 
117         GLint vec2Location = glGetUniformLocation(program, "v");
118 
119         glUseProgram(program);
120         glUniform2f(vec2Location, input1, input2);
121 
122         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
123 
124         ASSERT_GL_NO_ERROR();
125 
126         GLfloat p[2] = {0};
127         glReadPixels(8, 8, 1, 1, GL_RG, GL_FLOAT, p);
128 
129         ASSERT_GL_NO_ERROR();
130 
131         static const double epsilon = 0.0005;
132         EXPECT_NEAR(p[0], expect1, epsilon);
133         EXPECT_NEAR(p[1], expect2, epsilon);
134     }
135 
136     GLuint mSNormProgram;
137     GLuint mUNormProgram;
138     GLuint mHalfProgram;
139     GLuint mOffscreenFramebuffer;
140     GLuint mOffscreenTexture2D;
141 };
142 
143 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating normal floating
144 // numbers.
TEST_P(PackUnpackTest,PackUnpackSnormNormal)145 TEST_P(PackUnpackTest, PackUnpackSnormNormal)
146 {
147     // Expect the shader to output the same value as the input
148     compareBeforeAfter(mSNormProgram, 0.5f, -0.2f);
149     compareBeforeAfter(mSNormProgram, -0.35f, 0.75f);
150     compareBeforeAfter(mSNormProgram, 0.00392f, -0.99215f);
151     compareBeforeAfter(mSNormProgram, 1.0f, -0.00392f);
152 }
153 
154 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating normal floating
155 // numbers.
TEST_P(PackUnpackTest,PackUnpackUnormNormal)156 TEST_P(PackUnpackTest, PackUnpackUnormNormal)
157 {
158     // Expect the shader to output the same value as the input
159     compareBeforeAfter(mUNormProgram, 0.5f, 0.2f, 0.5f, 0.2f);
160     compareBeforeAfter(mUNormProgram, 0.35f, 0.75f, 0.35f, 0.75f);
161     compareBeforeAfter(mUNormProgram, 0.00392f, 0.99215f, 0.00392f, 0.99215f);
162     compareBeforeAfter(mUNormProgram, 1.0f, 0.00392f, 1.0f, 0.00392f);
163 }
164 
165 // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating normal floating
166 // numbers.
TEST_P(PackUnpackTest,PackUnpackHalfNormal)167 TEST_P(PackUnpackTest, PackUnpackHalfNormal)
168 {
169     // Expect the shader to output the same value as the input
170     compareBeforeAfter(mHalfProgram, 0.5f, -0.2f);
171     compareBeforeAfter(mHalfProgram, -0.35f, 0.75f);
172     compareBeforeAfter(mHalfProgram, 0.00392f, -0.99215f);
173     compareBeforeAfter(mHalfProgram, 1.0f, -0.00392f);
174 }
175 
176 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating subnormal
177 // floating numbers.
TEST_P(PackUnpackTest,PackUnpackSnormSubnormal)178 TEST_P(PackUnpackTest, PackUnpackSnormSubnormal)
179 {
180     // Expect the shader to output the same value as the input
181     compareBeforeAfter(mSNormProgram, 0.00001f, -0.00001f);
182 }
183 
184 // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating subnormal
185 // floating numbers.
TEST_P(PackUnpackTest,PackUnpackUnormSubnormal)186 TEST_P(PackUnpackTest, PackUnpackUnormSubnormal)
187 {
188     // Expect the shader to output the same value as the input for positive numbers and clamp
189     // to [0, 1]
190     compareBeforeAfter(mUNormProgram, 0.00001f, -0.00001f, 0.00001f, 0.0f);
191 }
192 
193 // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating subnormal floating
194 // numbers.
TEST_P(PackUnpackTest,PackUnpackHalfSubnormal)195 TEST_P(PackUnpackTest, PackUnpackHalfSubnormal)
196 {
197     // Expect the shader to output the same value as the input
198     compareBeforeAfter(mHalfProgram, 0.00001f, -0.00001f);
199 }
200 
201 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating zero floating
202 // numbers.
TEST_P(PackUnpackTest,PackUnpackSnormZero)203 TEST_P(PackUnpackTest, PackUnpackSnormZero)
204 {
205     // Expect the shader to output the same value as the input
206     compareBeforeAfter(mSNormProgram, 0.00000f, -0.00000f);
207 }
208 
209 // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating zero floating
210 // numbers.
TEST_P(PackUnpackTest,PackUnpackUnormZero)211 TEST_P(PackUnpackTest, PackUnpackUnormZero)
212 {
213     compareBeforeAfter(mUNormProgram, 0.00000f, -0.00000f, 0.00000f, 0.00000f);
214 }
215 
216 // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating zero floating
217 // numbers.
TEST_P(PackUnpackTest,PackUnpackHalfZero)218 TEST_P(PackUnpackTest, PackUnpackHalfZero)
219 {
220     // Expect the shader to output the same value as the input
221     compareBeforeAfter(mHalfProgram, 0.00000f, -0.00000f);
222 }
223 
224 // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating overflow floating
225 // numbers.
TEST_P(PackUnpackTest,PackUnpackUnormOverflow)226 TEST_P(PackUnpackTest, PackUnpackUnormOverflow)
227 {
228     // Expect the shader to clamp the input to [0, 1]
229     compareBeforeAfter(mUNormProgram, 67000.0f, -67000.0f, 1.0f, 0.0f);
230 }
231 
232 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating overflow floating
233 // numbers.
TEST_P(PackUnpackTest,PackUnpackSnormOverflow)234 TEST_P(PackUnpackTest, PackUnpackSnormOverflow)
235 {
236     // Expect the shader to clamp the input to [-1, 1]
237     compareBeforeAfter(mSNormProgram, 67000.0f, -67000.0f, 1.0f, -1.0f);
238 }
239 
240 // http://anglebug.com/4092 Not instantiating on other backends currently
241 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PackUnpackTest);
242 ANGLE_INSTANTIATE_TEST(PackUnpackTest, ES3_OPENGL(), ES3_OPENGLES());
243 }  // namespace
244