1 
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2018 Francois Beaune, The appleseedhq Organization
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27 //
28 
29 // appleseed.foundation headers.
30 #include "foundation/math/half.h"
31 #include "foundation/math/rng/distribution.h"
32 #include "foundation/math/rng/xoroshiro128plus.h"
33 #include "foundation/utility/benchmark.h"
34 
35 // Standard headers.
36 #include <cstddef>
37 #include <vector>
38 
39 using namespace foundation;
40 using namespace std;
41 
BENCHMARK_SUITE(Foundation_Math_Half)42 BENCHMARK_SUITE(Foundation_Math_Half)
43 {
44     //
45     // Float -> half benchmarks.
46     //
47 
48     template <size_t Size>
49     struct FloatToHalfFixture
50     {
51         vector<float> m_input;
52         vector<Half> m_output;
53 
54         FloatToHalfFixture()
55         {
56             Xoroshiro128plus rng;
57 
58             m_input.resize(Size);
59 
60             for (size_t i = 0, e = m_input.size(); i < e; ++i)
61                 m_input[i] = rand_float1(rng, -1.0f, 100.0f);
62 
63             m_output.resize(m_input.size());
64         }
65     };
66 
67     //
68     // Float -> half, 2x2 RGBA block.
69     //
70 
71     BENCHMARK_CASE_F(FloatToHalf_2x2RGBABlock, FloatToHalfFixture<2 * 2 * 4>)
72     {
73         for (size_t i = 0, e = m_input.size(); i < e; ++i)
74             m_output[i] = float_to_half(m_input[i]);
75     }
76 
77     BENCHMARK_CASE_F(FloatToHalfAlt_2x2RGBABlock, FloatToHalfFixture<2 * 2 * 4>)
78     {
79         for (size_t i = 0, e = m_input.size(); i < e; ++i)
80             m_output[i] = float_to_half_alt(m_input[i]);
81     }
82 
83     BENCHMARK_CASE_F(FastFloatToHalf_2x2RGBABlock, FloatToHalfFixture<2 * 2 * 4>)
84     {
85         for (size_t i = 0, e = m_input.size(); i < e; ++i)
86             m_output[i] = fast_float_to_half(m_input[i]);
87     }
88 
89     //
90     // Float -> half, 32x32 RGBA tile.
91     //
92 
93     BENCHMARK_CASE_F(FloatToHalf_32x32RGBATile, FloatToHalfFixture<32 * 32 * 4>)
94     {
95         for (size_t i = 0, e = m_input.size(); i < e; ++i)
96             m_output[i] = float_to_half(m_input[i]);
97     }
98 
99     BENCHMARK_CASE_F(FloatToHalfAlt_32x32RGBATile, FloatToHalfFixture<32 * 32 * 4>)
100     {
101         for (size_t i = 0, e = m_input.size(); i < e; ++i)
102             m_output[i] = float_to_half_alt(m_input[i]);
103     }
104 
105     BENCHMARK_CASE_F(FastFloatToHalf_32x32RGBATile, FloatToHalfFixture<32 * 32 * 4>)
106     {
107         for (size_t i = 0, e = m_input.size(); i < e; ++i)
108             m_output[i] = fast_float_to_half(m_input[i]);
109     }
110 
111     //
112     // Float -> half, 2048x2048 RGBA texture.
113     //
114 
115     BENCHMARK_CASE_F(FloatToHalf_2Kx2KRGBATexture, FloatToHalfFixture<2048 * 2048 * 4>)
116     {
117         for (size_t i = 0, e = m_input.size(); i < e; ++i)
118             m_output[i] = float_to_half(m_input[i]);
119     }
120 
121     BENCHMARK_CASE_F(FloatToHalfAlt_2Kx2KRGBATexture, FloatToHalfFixture<2048 * 2048 * 4>)
122     {
123         for (size_t i = 0, e = m_input.size(); i < e; ++i)
124             m_output[i] = float_to_half_alt(m_input[i]);
125     }
126 
127     BENCHMARK_CASE_F(FastFloatToHalf_2Kx2KRGBATexture, FloatToHalfFixture<2048 * 2048 * 4>)
128     {
129         for (size_t i = 0, e = m_input.size(); i < e; ++i)
130             m_output[i] = fast_float_to_half(m_input[i]);
131     }
132 
133     //
134     // Half -> float benchmarks.
135     //
136 
137     template <size_t Size>
138     struct HalfToFloatFixture
139     {
140         vector<Half> m_input;
141         vector<float> m_output;
142 
143         HalfToFloatFixture()
144         {
145             Xoroshiro128plus rng;
146 
147             m_input.resize(Size);
148 
149             for (size_t i = 0, e = m_input.size(); i < e; ++i)
150                 m_input[i] = float_to_half(rand_float1(rng, -1.0f, 100.0f));
151 
152             m_output.resize(m_input.size());
153         }
154     };
155 
156     //
157     // Half -> float, 2x2 RGBA block.
158     //
159 
160     BENCHMARK_CASE_F(HalfToFloat_2x2RGBABlock, HalfToFloatFixture<2 * 2 * 4>)
161     {
162         for (size_t i = 0, e = m_input.size(); i < e; ++i)
163             m_output[i] = half_to_float(m_input[i]);
164     }
165 
166     BENCHMARK_CASE_F(HalfToFloatAlt_2x2RGBABlock, HalfToFloatFixture<2 * 2 * 4>)
167     {
168         for (size_t i = 0, e = m_input.size(); i < e; ++i)
169             m_output[i] = half_to_float_alt(m_input[i]);
170     }
171 
172     //
173     // Half -> float, 32x32 RGBA tile.
174     //
175 
176     BENCHMARK_CASE_F(HalfToFloat_32x32RGBATile, HalfToFloatFixture<32 * 32 * 4>)
177     {
178         for (size_t i = 0, e = m_input.size(); i < e; ++i)
179             m_output[i] = half_to_float(m_input[i]);
180     }
181 
182     BENCHMARK_CASE_F(HalfToFloatAlt_32x32RGBATile, HalfToFloatFixture<32 * 32 * 4>)
183     {
184         for (size_t i = 0, e = m_input.size(); i < e; ++i)
185             m_output[i] = half_to_float_alt(m_input[i]);
186     }
187 
188     //
189     // Half -> float, 2048x2048 RGBA texture.
190     //
191 
192     BENCHMARK_CASE_F(HalfToFloat_2Kx2KRGBATexture, HalfToFloatFixture<2048 * 2048 * 4>)
193     {
194         for (size_t i = 0, e = m_input.size(); i < e; ++i)
195             m_output[i] = half_to_float(m_input[i]);
196     }
197 
198     BENCHMARK_CASE_F(HalfToFloatAlt_2Kx2KRGBATexture, HalfToFloatFixture<2048 * 2048 * 4>)
199     {
200         for (size_t i = 0, e = m_input.size(); i < e; ++i)
201             m_output[i] = half_to_float_alt(m_input[i]);
202     }
203 }
204