1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * @file format_conversion.h
25 * @brief API implementation
27 ******************************************************************************/
28 #include "format_types.h"
29 #include "format_traits.h"
31 //////////////////////////////////////////////////////////////////////////
32 /// @brief Load SIMD packed pixels in SOA format and converts to
33 /// SOA RGBA32_FLOAT format.
34 /// @param pSrc - source data in SOA form
35 /// @param dst - output data in SOA form
36 template<SWR_FORMAT SrcFormat
>
37 INLINE
void LoadSOA(const uint8_t *pSrc
, simdvector
&dst
)
39 // fast path for float32
40 if ((FormatTraits
<SrcFormat
>::GetType(0) == SWR_TYPE_FLOAT
) && (FormatTraits
<SrcFormat
>::GetBPC(0) == 32))
42 auto lambda
= [&](int comp
)
44 simdscalar vComp
= _simd_load_ps((const float*)(pSrc
+ comp
*sizeof(simdscalar
)));
46 dst
.v
[FormatTraits
<SrcFormat
>::swizzle(comp
)] = vComp
;
49 UnrollerL
<0, FormatTraits
<SrcFormat
>::numComps
, 1>::step(lambda
);
53 auto lambda
= [&](int comp
)
55 // load SIMD components
56 simdscalar vComp
= FormatTraits
<SrcFormat
>::loadSOA(comp
, pSrc
);
59 vComp
= FormatTraits
<SrcFormat
>::unpack(comp
, vComp
);
62 if (FormatTraits
<SrcFormat
>::isNormalized(comp
))
64 vComp
= _simd_cvtepi32_ps(_simd_castps_si(vComp
));
65 vComp
= _simd_mul_ps(vComp
, _simd_set1_ps(FormatTraits
<SrcFormat
>::toFloat(comp
)));
68 dst
.v
[FormatTraits
<SrcFormat
>::swizzle(comp
)] = vComp
;
70 pSrc
+= (FormatTraits
<SrcFormat
>::GetBPC(comp
) * KNOB_SIMD_WIDTH
) / 8;
73 UnrollerL
<0, FormatTraits
<SrcFormat
>::numComps
, 1>::step(lambda
);
76 //////////////////////////////////////////////////////////////////////////
77 /// @brief Clamps the given component based on the requirements on the
78 /// Format template arg
79 /// @param vComp - SIMD vector of floats
80 /// @param Component - component
81 template<SWR_FORMAT Format
>
82 INLINE simdscalar
Clamp(simdscalar vComp
, uint32_t Component
)
84 if (FormatTraits
<Format
>::isNormalized(Component
))
86 if (FormatTraits
<Format
>::GetType(Component
) == SWR_TYPE_UNORM
)
88 vComp
= _simd_max_ps(vComp
, _simd_setzero_ps());
91 if (FormatTraits
<Format
>::GetType(Component
) == SWR_TYPE_SNORM
)
93 vComp
= _simd_max_ps(vComp
, _simd_set1_ps(-1.0f
));
95 vComp
= _simd_min_ps(vComp
, _simd_set1_ps(1.0f
));
97 else if (FormatTraits
<Format
>::GetBPC(Component
) < 32)
99 if (FormatTraits
<Format
>::GetType(Component
) == SWR_TYPE_UINT
)
101 int iMax
= (1 << FormatTraits
<Format
>::GetBPC(Component
)) - 1;
103 simdscalari vCompi
= _simd_castps_si(vComp
);
104 vCompi
= _simd_max_epu32(vCompi
, _simd_set1_epi32(iMin
));
105 vCompi
= _simd_min_epu32(vCompi
, _simd_set1_epi32(iMax
));
106 vComp
= _simd_castsi_ps(vCompi
);
108 else if (FormatTraits
<Format
>::GetType(Component
) == SWR_TYPE_SINT
)
110 int iMax
= (1 << (FormatTraits
<Format
>::GetBPC(Component
) - 1)) - 1;
111 int iMin
= -1 - iMax
;
112 simdscalari vCompi
= _simd_castps_si(vComp
);
113 vCompi
= _simd_max_epi32(vCompi
, _simd_set1_epi32(iMin
));
114 vCompi
= _simd_min_epi32(vCompi
, _simd_set1_epi32(iMax
));
115 vComp
= _simd_castsi_ps(vCompi
);
122 //////////////////////////////////////////////////////////////////////////
123 /// @brief Normalize the given component based on the requirements on the
124 /// Format template arg
125 /// @param vComp - SIMD vector of floats
126 /// @param Component - component
127 template<SWR_FORMAT Format
>
128 INLINE simdscalar
Normalize(simdscalar vComp
, uint32_t Component
)
130 if (FormatTraits
<Format
>::isNormalized(Component
))
132 vComp
= _simd_mul_ps(vComp
, _simd_set1_ps(FormatTraits
<Format
>::fromFloat(Component
)));
133 vComp
= _simd_castsi_ps(_simd_cvtps_epi32(vComp
));
138 //////////////////////////////////////////////////////////////////////////
139 /// @brief Convert and store simdvector of pixels in SOA
140 /// RGBA32_FLOAT to SOA format
141 /// @param src - source data in SOA form
142 /// @param dst - output data in SOA form
143 template<SWR_FORMAT DstFormat
>
144 INLINE
void StoreSOA(const simdvector
&src
, uint8_t *pDst
)
146 // fast path for float32
147 if ((FormatTraits
<DstFormat
>::GetType(0) == SWR_TYPE_FLOAT
) && (FormatTraits
<DstFormat
>::GetBPC(0) == 32))
149 for (uint32_t comp
= 0; comp
< FormatTraits
<DstFormat
>::numComps
; ++comp
)
151 simdscalar vComp
= src
.v
[FormatTraits
<DstFormat
>::swizzle(comp
)];
154 if (FormatTraits
<DstFormat
>::isSRGB
)
156 if (comp
< 3) // Input format is always RGBA32_FLOAT.
158 vComp
= FormatTraits
<R32G32B32A32_FLOAT
>::convertSrgb(comp
, vComp
);
162 _simd_store_ps((float*)(pDst
+ comp
*sizeof(simdscalar
)), vComp
);
167 auto lambda
= [&](int comp
)
169 simdscalar vComp
= src
.v
[FormatTraits
<DstFormat
>::swizzle(comp
)];
172 if (FormatTraits
<DstFormat
>::isSRGB
)
174 if (comp
< 3) // Input format is always RGBA32_FLOAT.
176 vComp
= FormatTraits
<R32G32B32A32_FLOAT
>::convertSrgb(comp
, vComp
);
181 vComp
= Clamp
<DstFormat
>(vComp
, comp
);
184 vComp
= Normalize
<DstFormat
>(vComp
, comp
);
187 vComp
= FormatTraits
<DstFormat
>::pack(comp
, vComp
);
190 FormatTraits
<DstFormat
>::storeSOA(comp
, pDst
, vComp
);
192 pDst
+= (FormatTraits
<DstFormat
>::GetBPC(comp
) * KNOB_SIMD_WIDTH
) / 8;
195 UnrollerL
<0, FormatTraits
<DstFormat
>::numComps
, 1>::step(lambda
);
198 #if ENABLE_AVX512_SIMD16
199 //////////////////////////////////////////////////////////////////////////
200 /// @brief Load SIMD packed pixels in SOA format and converts to
201 /// SOA RGBA32_FLOAT format.
202 /// @param pSrc - source data in SOA form
203 /// @param dst - output data in SOA form
204 template<SWR_FORMAT SrcFormat
>
205 INLINE
void LoadSOA(const uint8_t *pSrc
, simd16vector
&dst
)
207 // fast path for float32
208 if ((FormatTraits
<SrcFormat
>::GetType(0) == SWR_TYPE_FLOAT
) && (FormatTraits
<SrcFormat
>::GetBPC(0) == 32))
210 auto lambda
= [&](int comp
)
212 simd16scalar vComp
= _simd16_load_ps(reinterpret_cast<const float *>(pSrc
+ comp
* sizeof(simd16scalar
)));
214 dst
.v
[FormatTraits
<SrcFormat
>::swizzle(comp
)] = vComp
;
217 UnrollerL
<0, FormatTraits
<SrcFormat
>::numComps
, 1>::step(lambda
);
221 auto lambda
= [&](int comp
)
223 // load SIMD components
224 simd16scalar vComp
= FormatTraits
<SrcFormat
>::loadSOA_16(comp
, pSrc
);
227 vComp
= FormatTraits
<SrcFormat
>::unpack(comp
, vComp
);
230 if (FormatTraits
<SrcFormat
>::isNormalized(comp
))
232 vComp
= _simd16_cvtepi32_ps(_simd16_castps_si(vComp
));
233 vComp
= _simd16_mul_ps(vComp
, _simd16_set1_ps(FormatTraits
<SrcFormat
>::toFloat(comp
)));
236 dst
.v
[FormatTraits
<SrcFormat
>::swizzle(comp
)] = vComp
;
238 pSrc
+= (FormatTraits
<SrcFormat
>::GetBPC(comp
) * KNOB_SIMD16_WIDTH
) / 8;
241 UnrollerL
<0, FormatTraits
<SrcFormat
>::numComps
, 1>::step(lambda
);
244 //////////////////////////////////////////////////////////////////////////
245 /// @brief Clamps the given component based on the requirements on the
246 /// Format template arg
247 /// @param vComp - SIMD vector of floats
248 /// @param Component - component
249 template<SWR_FORMAT Format
>
250 INLINE simd16scalar
Clamp(simd16scalar vComp
, uint32_t Component
)
252 if (FormatTraits
<Format
>::isNormalized(Component
))
254 if (FormatTraits
<Format
>::GetType(Component
) == SWR_TYPE_UNORM
)
256 vComp
= _simd16_max_ps(vComp
, _simd16_setzero_ps());
259 if (FormatTraits
<Format
>::GetType(Component
) == SWR_TYPE_SNORM
)
261 vComp
= _simd16_max_ps(vComp
, _simd16_set1_ps(-1.0f
));
263 vComp
= _simd16_min_ps(vComp
, _simd16_set1_ps(1.0f
));
265 else if (FormatTraits
<Format
>::GetBPC(Component
) < 32)
267 if (FormatTraits
<Format
>::GetType(Component
) == SWR_TYPE_UINT
)
269 int iMax
= (1 << FormatTraits
<Format
>::GetBPC(Component
)) - 1;
271 simd16scalari vCompi
= _simd16_castps_si(vComp
);
272 vCompi
= _simd16_max_epu32(vCompi
, _simd16_set1_epi32(iMin
));
273 vCompi
= _simd16_min_epu32(vCompi
, _simd16_set1_epi32(iMax
));
274 vComp
= _simd16_castsi_ps(vCompi
);
276 else if (FormatTraits
<Format
>::GetType(Component
) == SWR_TYPE_SINT
)
278 int iMax
= (1 << (FormatTraits
<Format
>::GetBPC(Component
) - 1)) - 1;
279 int iMin
= -1 - iMax
;
280 simd16scalari vCompi
= _simd16_castps_si(vComp
);
281 vCompi
= _simd16_max_epi32(vCompi
, _simd16_set1_epi32(iMin
));
282 vCompi
= _simd16_min_epi32(vCompi
, _simd16_set1_epi32(iMax
));
283 vComp
= _simd16_castsi_ps(vCompi
);
290 //////////////////////////////////////////////////////////////////////////
291 /// @brief Normalize the given component based on the requirements on the
292 /// Format template arg
293 /// @param vComp - SIMD vector of floats
294 /// @param Component - component
295 template<SWR_FORMAT Format
>
296 INLINE simd16scalar
Normalize(simd16scalar vComp
, uint32_t Component
)
298 if (FormatTraits
<Format
>::isNormalized(Component
))
300 vComp
= _simd16_mul_ps(vComp
, _simd16_set1_ps(FormatTraits
<Format
>::fromFloat(Component
)));
301 vComp
= _simd16_castsi_ps(_simd16_cvtps_epi32(vComp
));
306 //////////////////////////////////////////////////////////////////////////
307 /// @brief Convert and store simdvector of pixels in SOA
308 /// RGBA32_FLOAT to SOA format
309 /// @param src - source data in SOA form
310 /// @param dst - output data in SOA form
311 template<SWR_FORMAT DstFormat
>
312 INLINE
void StoreSOA(const simd16vector
&src
, uint8_t *pDst
)
314 // fast path for float32
315 if ((FormatTraits
<DstFormat
>::GetType(0) == SWR_TYPE_FLOAT
) && (FormatTraits
<DstFormat
>::GetBPC(0) == 32))
317 for (uint32_t comp
= 0; comp
< FormatTraits
<DstFormat
>::numComps
; ++comp
)
319 simd16scalar vComp
= src
.v
[FormatTraits
<DstFormat
>::swizzle(comp
)];
322 if (FormatTraits
<DstFormat
>::isSRGB
)
324 if (comp
< 3) // Input format is always RGBA32_FLOAT.
326 vComp
= FormatTraits
<R32G32B32A32_FLOAT
>::convertSrgb(comp
, vComp
);
330 _simd16_store_ps(reinterpret_cast<float *>(pDst
+ comp
* sizeof(simd16scalar
)), vComp
);
335 auto lambda
= [&](int comp
)
337 simd16scalar vComp
= src
.v
[FormatTraits
<DstFormat
>::swizzle(comp
)];
340 if (FormatTraits
<DstFormat
>::isSRGB
)
342 if (comp
< 3) // Input format is always RGBA32_FLOAT.
344 vComp
= FormatTraits
<R32G32B32A32_FLOAT
>::convertSrgb(comp
, vComp
);
349 vComp
= Clamp
<DstFormat
>(vComp
, comp
);
352 vComp
= Normalize
<DstFormat
>(vComp
, comp
);
355 vComp
= FormatTraits
<DstFormat
>::pack(comp
, vComp
);
358 FormatTraits
<DstFormat
>::storeSOA(comp
, pDst
, vComp
);
360 pDst
+= (FormatTraits
<DstFormat
>::GetBPC(comp
) * KNOB_SIMD16_WIDTH
) / 8;
363 UnrollerL
<0, FormatTraits
<DstFormat
>::numComps
, 1>::step(lambda
);