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