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