1 // Copyright 2018 The Amber Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/buffer.h"
16
17 #include <limits>
18 #include <utility>
19
20 #include "gtest/gtest.h"
21 #include "src/float16_helper.h"
22 #include "src/type_parser.h"
23
24 namespace amber {
25
26 using BufferTest = testing::Test;
27
TEST_F(BufferTest,EmptyByDefault)28 TEST_F(BufferTest, EmptyByDefault) {
29 Buffer b;
30 EXPECT_EQ(static_cast<size_t>(0U), b.ElementCount());
31 EXPECT_EQ(static_cast<size_t>(0U), b.ValueCount());
32 EXPECT_EQ(static_cast<size_t>(0U), b.GetSizeInBytes());
33 }
34
TEST_F(BufferTest,Size)35 TEST_F(BufferTest, Size) {
36 TypeParser parser;
37 auto type = parser.Parse("R16_SINT");
38 Format fmt(type.get());
39
40 Buffer b;
41 b.SetFormat(&fmt);
42 b.SetElementCount(10);
43 EXPECT_EQ(10u, b.ElementCount());
44 EXPECT_EQ(10u, b.ValueCount());
45 EXPECT_EQ(10u * sizeof(int16_t), b.GetSizeInBytes());
46 }
47
TEST_F(BufferTest,SizeFromData)48 TEST_F(BufferTest, SizeFromData) {
49 std::vector<Value> values;
50 values.resize(5);
51
52 TypeParser parser;
53 auto type = parser.Parse("R32_SFLOAT");
54 Format fmt(type.get());
55
56 Buffer b;
57 b.SetFormat(&fmt);
58 b.SetData(std::move(values));
59
60 EXPECT_EQ(5u, b.ElementCount());
61 EXPECT_EQ(5u, b.ValueCount());
62 EXPECT_EQ(5u * sizeof(float), b.GetSizeInBytes());
63 }
64
TEST_F(BufferTest,SizeFromDataDoesNotOverrideSize)65 TEST_F(BufferTest, SizeFromDataDoesNotOverrideSize) {
66 std::vector<Value> values;
67 values.resize(5);
68
69 TypeParser parser;
70 auto type = parser.Parse("R32_SFLOAT");
71 Format fmt(type.get());
72
73 Buffer b;
74 b.SetFormat(&fmt);
75 b.SetElementCount(20);
76 b.SetData(std::move(values));
77
78 EXPECT_EQ(20u, b.ElementCount());
79 EXPECT_EQ(20u, b.ValueCount());
80 EXPECT_EQ(20u * sizeof(float), b.GetSizeInBytes());
81 }
82
TEST_F(BufferTest,SizeMatrixStd430)83 TEST_F(BufferTest, SizeMatrixStd430) {
84 TypeParser parser;
85 auto type = parser.Parse("R16G16_SINT");
86 type->SetColumnCount(3);
87 Format fmt(type.get());
88
89 Buffer b;
90 b.SetFormat(&fmt);
91 b.SetElementCount(10);
92
93 EXPECT_EQ(10u, b.ElementCount());
94 EXPECT_EQ(60u, b.ValueCount());
95 EXPECT_EQ(60u * sizeof(int16_t), b.GetSizeInBytes());
96 }
97
TEST_F(BufferTest,SizeMatrixStd140)98 TEST_F(BufferTest, SizeMatrixStd140) {
99 TypeParser parser;
100 auto type = parser.Parse("R16G16_SINT");
101 type->SetColumnCount(3);
102 Format fmt(type.get());
103 fmt.SetLayout(Format::Layout::kStd140);
104
105 Buffer b;
106 b.SetFormat(&fmt);
107 b.SetElementCount(10);
108
109 EXPECT_EQ(10u, b.ElementCount());
110 EXPECT_EQ(10u * 2u * 3u, b.ValueCount());
111 EXPECT_EQ(120u * sizeof(int16_t), b.GetSizeInBytes());
112 }
113
TEST_F(BufferTest,SizeMatrixPaddedStd430)114 TEST_F(BufferTest, SizeMatrixPaddedStd430) {
115 TypeParser parser;
116 auto type = parser.Parse("R32G32B32_SINT");
117 type->SetColumnCount(3);
118 Format fmt(type.get());
119
120 Buffer b;
121 b.SetFormat(&fmt);
122 b.SetValueCount(9);
123
124 EXPECT_EQ(1U, b.ElementCount());
125 EXPECT_EQ(9U, b.ValueCount());
126 EXPECT_EQ(12U * sizeof(int32_t), b.GetSizeInBytes());
127 }
128
129 // Creates 10 RGBA pixel values, with the blue channels ranging from 0 to 255,
130 // and checks that the bin for each blue channel value contains 1, as expected.
TEST_F(BufferTest,GetHistogramForChannelGradient)131 TEST_F(BufferTest, GetHistogramForChannelGradient) {
132 TypeParser parser;
133 auto type = parser.Parse("R8G8B8A8_UINT");
134 Format fmt(type.get());
135
136 // Creates 10 RBGA pixel values with the blue channels ranging from 0 to 255.
137 // Every value gets multiplied by 25 to create a gradient
138 std::vector<Value> values(40);
139 for (uint32_t i = 0; i < values.size(); i += 4)
140 values[i + 2].SetIntValue(i / 4 * 25);
141
142 Buffer b;
143 b.SetFormat(&fmt);
144 b.SetData(values);
145
146 std::vector<uint64_t> bins = b.GetHistogramForChannel(2, 256);
147 for (uint32_t i = 0; i < values.size(); i += 4)
148 EXPECT_EQ(1u, bins[i / 4 * 25]);
149 }
150
151 // Creates 10 RGBA pixel values, with all channels being 0, and checks that all
152 // channels have a count of 10 (all pixels) in the 0 bin.
TEST_F(BufferTest,GetHistogramForChannelAllBlack)153 TEST_F(BufferTest, GetHistogramForChannelAllBlack) {
154 TypeParser parser;
155 auto type = parser.Parse("R8G8B8A8_UINT");
156 Format fmt(type.get());
157
158 std::vector<Value> values(40);
159 for (uint32_t i = 0; i < values.size(); i++)
160 values[i].SetIntValue(0);
161
162 Buffer b;
163 b.SetFormat(&fmt);
164 b.SetData(values);
165
166 for (uint8_t i = 0; i < 4; i++) {
167 std::vector<uint64_t> bins = b.GetHistogramForChannel(i, 256);
168 for (uint32_t y = 0; y < values.size(); y++)
169 EXPECT_EQ(10u, bins[0]);
170 }
171 }
172
173 // Creates 10 RGBA pixel values, with all channels being the maximum value of 8
174 // bit uint, and checks that all channels have a count of 10 (all pixels) in the
175 // 255 (max uint8_t) bin.
TEST_F(BufferTest,GetHistogramForChannelAllWhite)176 TEST_F(BufferTest, GetHistogramForChannelAllWhite) {
177 TypeParser parser;
178 auto type = parser.Parse("R8G8B8A8_UINT");
179 Format fmt(type.get());
180
181 std::vector<Value> values(40);
182 for (uint32_t i = 0; i < values.size(); i++)
183 values[i].SetIntValue(std::numeric_limits<uint8_t>::max());
184
185 Buffer b;
186 b.SetFormat(&fmt);
187 b.SetData(values);
188
189 for (uint8_t i = 0; i < 4; i++) {
190 std::vector<uint64_t> bins = b.GetHistogramForChannel(i, 256);
191 for (uint32_t y = 0; y < values.size(); y++)
192 EXPECT_EQ(10u, bins[255]);
193 }
194 }
195
196 // Creates two sets of equal pixel values, except for one pixel that has +50 in
197 // its red channel. Compares the histograms to see if they are equal with a low
198 // threshold, which we expect to fail.
TEST_F(BufferTest,CompareHistogramEMDToleranceFalse)199 TEST_F(BufferTest, CompareHistogramEMDToleranceFalse) {
200 TypeParser parser;
201 auto type = parser.Parse("R8G8B8A8_UINT");
202 Format fmt(type.get());
203
204 // Every value gets multiplied by 25 to create a gradient
205 std::vector<Value> values1(40);
206 for (uint32_t i = 0; i < values1.size(); i += 4)
207 values1[i].SetIntValue(i / 4 * 25);
208
209 std::vector<Value> values2 = values1;
210 values2[4].SetIntValue(values2[4].AsUint8() + 50);
211
212 Buffer b1;
213 b1.SetFormat(&fmt);
214 b1.SetData(values1);
215
216 Buffer b2;
217 b2.SetFormat(&fmt);
218 b2.SetData(values2);
219
220 EXPECT_FALSE(b1.CompareHistogramEMD(&b2, 0.001f).IsSuccess());
221 }
222
223 // Creates two sets of equal pixel values, except for one pixel that has +50 in
224 // its red channel. Compares the histograms to see if they are equal with a high
225 // threshold, which we expect to succeed.
TEST_F(BufferTest,CompareHistogramEMDToleranceTrue)226 TEST_F(BufferTest, CompareHistogramEMDToleranceTrue) {
227 TypeParser parser;
228 auto type = parser.Parse("R8G8B8A8_UINT");
229 Format fmt(type.get());
230
231 // Every value gets multiplied by 25 to create a gradient
232 std::vector<Value> values1(40);
233 for (uint32_t i = 0; i < values1.size(); i += 4)
234 values1[i].SetIntValue(i / 4 * 25);
235
236 std::vector<Value> values2 = values1;
237 values2[4].SetIntValue(values2[4].AsUint8() + 50);
238
239 Buffer b1;
240 b1.SetFormat(&fmt);
241 b1.SetData(values1);
242
243 Buffer b2;
244 b2.SetFormat(&fmt);
245 b2.SetData(values2);
246
247 EXPECT_TRUE(b1.CompareHistogramEMD(&b2, 0.02f).IsSuccess());
248 }
249
250 // Creates two identical sets of RGBA pixel values and checks that the
251 // histograms are equal.
TEST_F(BufferTest,CompareHistogramEMDToleranceAllBlack)252 TEST_F(BufferTest, CompareHistogramEMDToleranceAllBlack) {
253 TypeParser parser;
254 auto type = parser.Parse("R8G8B8A8_UINT");
255 Format fmt(type.get());
256
257 std::vector<Value> values1(40);
258 for (uint32_t i = 0; i < values1.size(); i++)
259 values1[i].SetIntValue(0);
260
261 std::vector<Value> values2 = values1;
262
263 Buffer b1;
264 b1.SetFormat(&fmt);
265 b1.SetData(values1);
266
267 Buffer b2;
268 b2.SetFormat(&fmt);
269 b2.SetData(values2);
270
271 EXPECT_TRUE(b1.CompareHistogramEMD(&b2, 0.0f).IsSuccess());
272 }
273
274 // Creates two identical sets of RGBA pixel values and checks that the
275 // histograms are equal.
TEST_F(BufferTest,CompareHistogramEMDToleranceAllWhite)276 TEST_F(BufferTest, CompareHistogramEMDToleranceAllWhite) {
277 TypeParser parser;
278 auto type = parser.Parse("R8G8B8A8_UINT");
279 Format fmt(type.get());
280
281 std::vector<Value> values1(40);
282 for (uint32_t i = 0; i < values1.size(); i++)
283 values1[i].SetIntValue(std::numeric_limits<uint8_t>().max());
284
285 std::vector<Value> values2 = values1;
286
287 Buffer b1;
288 b1.SetFormat(&fmt);
289 b1.SetData(values1);
290
291 Buffer b2;
292 b2.SetFormat(&fmt);
293 b2.SetData(values2);
294
295 EXPECT_TRUE(b1.CompareHistogramEMD(&b2, 0.0f).IsSuccess());
296 }
297
TEST_F(BufferTest,SetFloat16)298 TEST_F(BufferTest, SetFloat16) {
299 std::vector<Value> values;
300 values.resize(2);
301 values[0].SetDoubleValue(2.8);
302 values[1].SetDoubleValue(1234.567);
303
304 TypeParser parser;
305 auto type = parser.Parse("R16_SFLOAT");
306
307 Format fmt(type.get());
308 Buffer b;
309 b.SetFormat(&fmt);
310 b.SetData(std::move(values));
311
312 EXPECT_EQ(2u, b.ElementCount());
313 EXPECT_EQ(2u, b.ValueCount());
314 EXPECT_EQ(4u, b.GetSizeInBytes());
315
316 auto v = b.GetValues<uint16_t>();
317 EXPECT_EQ(float16::FloatToHexFloat16(2.8f), v[0]);
318 EXPECT_EQ(float16::FloatToHexFloat16(1234.567f), v[1]);
319 }
320
321 } // namespace amber
322