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 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 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 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 GLint vec2Location = glGetUniformLocation(program, "v");
115
116 glUseProgram(program);
117 glUniform2f(vec2Location, input1, input2);
118
119 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
120
121 ASSERT_GL_NO_ERROR();
122
123 GLfloat p[2] = {0};
124 glReadPixels(8, 8, 1, 1, GL_RG, GL_FLOAT, p);
125
126 ASSERT_GL_NO_ERROR();
127
128 static const double epsilon = 0.0005;
129 EXPECT_NEAR(p[0], expect1, epsilon);
130 EXPECT_NEAR(p[1], expect2, epsilon);
131 }
132
133 GLuint mSNormProgram;
134 GLuint mUNormProgram;
135 GLuint mHalfProgram;
136 GLuint mOffscreenFramebuffer;
137 GLuint mOffscreenTexture2D;
138 };
139
140 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating normal floating
141 // numbers.
TEST_P(PackUnpackTest,PackUnpackSnormNormal)142 TEST_P(PackUnpackTest, PackUnpackSnormNormal)
143 {
144 // Expect the shader to output the same value as the input
145 compareBeforeAfter(mSNormProgram, 0.5f, -0.2f);
146 compareBeforeAfter(mSNormProgram, -0.35f, 0.75f);
147 compareBeforeAfter(mSNormProgram, 0.00392f, -0.99215f);
148 compareBeforeAfter(mSNormProgram, 1.0f, -0.00392f);
149 }
150
151 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating normal floating
152 // numbers.
TEST_P(PackUnpackTest,PackUnpackUnormNormal)153 TEST_P(PackUnpackTest, PackUnpackUnormNormal)
154 {
155 // Expect the shader to output the same value as the input
156 compareBeforeAfter(mUNormProgram, 0.5f, 0.2f, 0.5f, 0.2f);
157 compareBeforeAfter(mUNormProgram, 0.35f, 0.75f, 0.35f, 0.75f);
158 compareBeforeAfter(mUNormProgram, 0.00392f, 0.99215f, 0.00392f, 0.99215f);
159 compareBeforeAfter(mUNormProgram, 1.0f, 0.00392f, 1.0f, 0.00392f);
160 }
161
162 // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating normal floating
163 // numbers.
TEST_P(PackUnpackTest,PackUnpackHalfNormal)164 TEST_P(PackUnpackTest, PackUnpackHalfNormal)
165 {
166 // Expect the shader to output the same value as the input
167 compareBeforeAfter(mHalfProgram, 0.5f, -0.2f);
168 compareBeforeAfter(mHalfProgram, -0.35f, 0.75f);
169 compareBeforeAfter(mHalfProgram, 0.00392f, -0.99215f);
170 compareBeforeAfter(mHalfProgram, 1.0f, -0.00392f);
171 }
172
173 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating subnormal
174 // floating numbers.
TEST_P(PackUnpackTest,PackUnpackSnormSubnormal)175 TEST_P(PackUnpackTest, PackUnpackSnormSubnormal)
176 {
177 // Expect the shader to output the same value as the input
178 compareBeforeAfter(mSNormProgram, 0.00001f, -0.00001f);
179 }
180
181 // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating subnormal
182 // floating numbers.
TEST_P(PackUnpackTest,PackUnpackUnormSubnormal)183 TEST_P(PackUnpackTest, PackUnpackUnormSubnormal)
184 {
185 // Expect the shader to output the same value as the input for positive numbers and clamp
186 // to [0, 1]
187 compareBeforeAfter(mUNormProgram, 0.00001f, -0.00001f, 0.00001f, 0.0f);
188 }
189
190 // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating subnormal floating
191 // numbers.
TEST_P(PackUnpackTest,PackUnpackHalfSubnormal)192 TEST_P(PackUnpackTest, PackUnpackHalfSubnormal)
193 {
194 // Expect the shader to output the same value as the input
195 compareBeforeAfter(mHalfProgram, 0.00001f, -0.00001f);
196 }
197
198 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating zero floating
199 // numbers.
TEST_P(PackUnpackTest,PackUnpackSnormZero)200 TEST_P(PackUnpackTest, PackUnpackSnormZero)
201 {
202 // Expect the shader to output the same value as the input
203 compareBeforeAfter(mSNormProgram, 0.00000f, -0.00000f);
204 }
205
206 // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating zero floating
207 // numbers.
TEST_P(PackUnpackTest,PackUnpackUnormZero)208 TEST_P(PackUnpackTest, PackUnpackUnormZero)
209 {
210 compareBeforeAfter(mUNormProgram, 0.00000f, -0.00000f, 0.00000f, 0.00000f);
211 }
212
213 // Test the correctness of packHalf2x16 and unpackHalf2x16 functions calculating zero floating
214 // numbers.
TEST_P(PackUnpackTest,PackUnpackHalfZero)215 TEST_P(PackUnpackTest, PackUnpackHalfZero)
216 {
217 // Expect the shader to output the same value as the input
218 compareBeforeAfter(mHalfProgram, 0.00000f, -0.00000f);
219 }
220
221 // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions calculating overflow floating
222 // numbers.
TEST_P(PackUnpackTest,PackUnpackUnormOverflow)223 TEST_P(PackUnpackTest, PackUnpackUnormOverflow)
224 {
225 // Expect the shader to clamp the input to [0, 1]
226 compareBeforeAfter(mUNormProgram, 67000.0f, -67000.0f, 1.0f, 0.0f);
227 }
228
229 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions calculating overflow floating
230 // numbers.
TEST_P(PackUnpackTest,PackUnpackSnormOverflow)231 TEST_P(PackUnpackTest, PackUnpackSnormOverflow)
232 {
233 // Expect the shader to clamp the input to [-1, 1]
234 compareBeforeAfter(mSNormProgram, 67000.0f, -67000.0f, 1.0f, -1.0f);
235 }
236
237 ANGLE_INSTANTIATE_TEST(PackUnpackTest, ES3_OPENGL(), ES3_OPENGLES());
238 // http://anglebug.com/4092 Not instantiating on other backends currently
239 } // namespace
240