1 /*
2 * Copyright (c) 2009-2022, Intel Corporation
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file vphal_common.c
24 //! \brief Definition common utilities for vphal
25 //! \details Definition common utilities for vphal including:
26 //! some macro, enum, union, structure, function
27 //!
28 #include "vphal.h"
29 #include "hal_kerneldll.h"
30 #include "mos_os.h"
31 #include "vp_hal_ddi_utils.h"
32 #include <math.h>
33
34 #if EMUL || VPHAL_LIB
35 #include "support.h"
36 #endif
37
38 union FP32
39 {
40 uint32_t u;
41 float f;
42 struct
43 {
44 uint32_t Mantissa : 23;
45 uint32_t Exponent : 8;
46 uint32_t Sign : 1;
47 };
48 };
49
50 union FP16
51 {
52 uint16_t u;
53 struct
54 {
55 uint16_t Mantissa : 10;
56 uint16_t Exponent : 5;
57 uint16_t Sign : 1;
58 };
59 };
60
61 //!
62 //! \brief sinc
63 //! \details Calculate sinc(x)
64 //! \param [in] x
65 //! float
66 //! \return float
67 //! sinc(x)
68 //!
VpHal_Sinc(float x)69 float VpHal_Sinc(float x)
70 {
71 return (VPHAL_ABS(x) < 1e-9f) ? 1.0F : (float)(sin(x) / x);
72 }
73
74 //!
75 //! \brief Lanczos
76 //! \details Calculate lanczos(x)
77 //! Basic formula is: lanczos(x)= VpHal_Sinc(x) * VpHal_Sinc(x / fLanczosT)
78 //! \param [in] x
79 //! float
80 //! \param [in] dwNumEntries
81 //! dword
82 //! \param [in] fLanczosT
83 //!
84 //! \return float
85 //! lanczos(x)
86 //!
VpHal_Lanczos(float x,uint32_t dwNumEntries,float fLanczosT)87 float VpHal_Lanczos(float x, uint32_t dwNumEntries, float fLanczosT)
88 {
89 uint32_t dwNumHalfEntries;
90
91 dwNumHalfEntries = dwNumEntries >> 1;
92 if (fLanczosT < dwNumHalfEntries)
93 {
94 fLanczosT = (float)dwNumHalfEntries;
95 }
96
97 if (VPHAL_ABS(x) >= dwNumHalfEntries)
98 {
99 return 0.0;
100 }
101
102 x *= VPHAL_PI;
103
104 return VpHal_Sinc(x) * VpHal_Sinc(x / fLanczosT);
105 }
106
IsSyncFreeNeededForMMCSurface(PVPHAL_SURFACE pSurface,PMOS_INTERFACE pOsInterface)107 bool IsSyncFreeNeededForMMCSurface(PVPHAL_SURFACE pSurface, PMOS_INTERFACE pOsInterface)
108 {
109 if (nullptr == pSurface || nullptr == pOsInterface)
110 {
111 return false;
112 }
113
114 //Compressed surface aux table update is after resource dealloction, aux table update need wait the WLs complete
115 //the sync deallocation flag will make sure deallocation API return after all surface related WL been completed and resource been destroyed by OS
116 auto *pSkuTable = pOsInterface->pfnGetSkuTable(pOsInterface);
117 if (pSkuTable &&
118 MEDIA_IS_SKU(pSkuTable, FtrE2ECompression) && //Compression enabled platform
119 !MEDIA_IS_SKU(pSkuTable, FtrFlatPhysCCS) && //NOT DGPU compression
120 ((pSurface->bCompressible) && (pSurface->CompressionMode != MOS_MMC_DISABLED))) //Compressed enabled surface
121 {
122 return true;
123 }
124
125 return false;
126 }
127
128 //!
129 //! \brief Allocates the Surface
130 //! \details Allocates the Surface
131 //! - if the surface is not already allocated OR
132 //! - resource dimenisions OR format changed
133 //! \param [in] pOsInterface
134 //! Pointer to MOS_INTERFACE
135 //! \param [in,out] pSurface
136 //! Pointer to VPHAL_SURFACE
137 //! \param [in] pSurfaceName
138 //! Pointer to surface name
139 //! \param [in] Format
140 //! Expected MOS_FORMAT
141 //! \param [in] DefaultResType
142 //! Expected Resource Type
143 //! \param [in] DefaultTileType
144 //! Expected Surface Tile Type
145 //! \param [in] dwWidth
146 //! Expected Surface Width
147 //! \param [in] dwHeight
148 //! Expected Surface Height
149 //! \param [in] bCompressible
150 //! Surface being compressible or not
151 //! \param [in] CompressionMode
152 //! Compression Mode
153 //! \param [out] pbAllocated
154 //! true if allocated, false for not
155 //! \param [in] resUsageType
156 //! resource usage type for caching
157 //! \param [in] tileModeByForce
158 //! Forced tile mode
159 //! \param [in] memType
160 //! vidoe memory location
161 //! \param [in] isNotLockable
162 //! true if surface not lockable
163 //! \return MOS_STATUS
164 //! MOS_STATUS_SUCCESS if success. Error code otherwise
165 //!
VpHal_ReAllocateSurface(PMOS_INTERFACE pOsInterface,PVPHAL_SURFACE pSurface,PCCHAR pSurfaceName,MOS_FORMAT Format,MOS_GFXRES_TYPE DefaultResType,MOS_TILE_TYPE DefaultTileType,uint32_t dwWidth,uint32_t dwHeight,bool bCompressible,MOS_RESOURCE_MMC_MODE CompressionMode,bool * pbAllocated,MOS_HW_RESOURCE_DEF resUsageType,MOS_TILE_MODE_GMM tileModeByForce,Mos_MemPool memType,bool isNotLockable)166 MOS_STATUS VpHal_ReAllocateSurface(
167 PMOS_INTERFACE pOsInterface,
168 PVPHAL_SURFACE pSurface,
169 PCCHAR pSurfaceName,
170 MOS_FORMAT Format,
171 MOS_GFXRES_TYPE DefaultResType,
172 MOS_TILE_TYPE DefaultTileType,
173 uint32_t dwWidth,
174 uint32_t dwHeight,
175 bool bCompressible,
176 MOS_RESOURCE_MMC_MODE CompressionMode,
177 bool* pbAllocated,
178 MOS_HW_RESOURCE_DEF resUsageType,
179 MOS_TILE_MODE_GMM tileModeByForce,
180 Mos_MemPool memType,
181 bool isNotLockable)
182 {
183 MOS_STATUS eStatus;
184 VPHAL_GET_SURFACE_INFO Info;
185 MOS_ALLOC_GFXRES_PARAMS AllocParams;
186 MOS_GFXRES_FREE_FLAGS resFreeFlags = {0};
187
188 //---------------------------------
189 VPHAL_PUBLIC_ASSERT(pOsInterface);
190 VPHAL_PUBLIC_ASSERT(pSurface);
191 //---------------------------------
192
193 eStatus = MOS_STATUS_SUCCESS;
194 *pbAllocated = false;
195
196 // bCompressible should be compared with bCompressible since it is inited by bCompressible in previous call
197 // TileType of surface should be compared since we need to reallocate surface if TileType changes
198 if (!Mos_ResourceIsNull(&pSurface->OsResource) &&
199 (pSurface->dwWidth == dwWidth) &&
200 (pSurface->dwHeight == dwHeight) &&
201 (pSurface->Format == Format) &&
202 (pSurface->bCompressible == bCompressible) &&
203 (pSurface->CompressionMode == CompressionMode) &&
204 (pSurface->TileType == DefaultTileType ||
205 MOS_TILE_Y == DefaultTileType &&
206 IS_Y_MAJOR_TILE_FORMAT(pSurface->TileType)))
207 {
208 goto finish;
209 }
210
211 if (pOsInterface->bOptimizeCpuTiming &&
212 (DefaultResType == MOS_GFXRES_BUFFER) &&
213 (pSurface->dwWidth >= dwWidth))
214 {
215 goto finish;
216 }
217
218 MOS_ZeroMemory(&AllocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
219
220 VpHal_AllocParamsInitType(&AllocParams, pSurface, DefaultResType, DefaultTileType);
221
222 AllocParams.dwWidth = dwWidth;
223 AllocParams.dwHeight = dwHeight;
224 AllocParams.Format = Format;
225 AllocParams.bIsCompressible = bCompressible;
226 AllocParams.CompressionMode = CompressionMode;
227 AllocParams.pBufName = pSurfaceName;
228 AllocParams.dwArraySize = 1;
229 AllocParams.ResUsageType = resUsageType;
230 AllocParams.m_tileModeByForce = tileModeByForce;
231 AllocParams.dwMemType = memType;
232 AllocParams.Flags.bNotLockable = isNotLockable;
233
234 // Delete resource if already allocated
235 //if free the compressed surface, need set the sync dealloc flag as 1 for sync dealloc for aux table update
236 if (IsSyncFreeNeededForMMCSurface(pSurface, pOsInterface))
237 {
238 resFreeFlags.SynchronousDestroy = 1;
239 VPHAL_PUBLIC_NORMALMESSAGE("Set SynchronousDestroy flag for compressed resource %s", pSurfaceName);
240 }
241 pOsInterface->pfnFreeResourceWithFlag(pOsInterface, &(pSurface->OsResource), resFreeFlags.Value);
242
243 // Allocate surface
244 VPHAL_PUBLIC_CHK_STATUS(pOsInterface->pfnAllocateResource(
245 pOsInterface,
246 &AllocParams,
247 &pSurface->OsResource));
248
249 // Get surface information
250 MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
251
252 // Pre-set to get surface info
253 pSurface->Format = Format;
254
255 VPHAL_PUBLIC_CHK_STATUS(VpHal_GetSurfaceInfo(pOsInterface, &Info, pSurface));
256
257 *pbAllocated = true;
258
259 MT_LOG7(MT_VP_HAL_REALLOC_SURF, MT_NORMAL, MT_VP_HAL_INTER_SURF_TYPE, pSurfaceName ? *((int64_t*)pSurfaceName) : 0,
260 MT_SURF_WIDTH, dwWidth, MT_SURF_HEIGHT, dwHeight, MT_SURF_MOS_FORMAT, Format, MT_SURF_TILE_MODE, pSurface->TileModeGMM,
261 MT_SURF_COMP_ABLE, pSurface->bCompressible, MT_SURF_COMP_MODE, pSurface->CompressionMode);
262
263 finish:
264 VPHAL_PUBLIC_ASSERT(eStatus == MOS_STATUS_SUCCESS);
265 return eStatus;
266 }
267
268 //!
269 //! \brief Reads the Surface contents and copy to the Dst Buffer
270 //! \details Reads the Surface contents and copy to the Dst Buffer
271 //! - 1 lock surface
272 //! - 2 copy surface data to pDst
273 //! - 3 unlock surface
274 //! \param [in] pOsInterface
275 //! Pointer to MOS_INTERFACE
276 //! \param [in] pSurface
277 //! Pointer to VPHAL_SURFACE
278 //! \param [in] uBpp
279 //! bit per pixel of surface contents
280 //! \param [out] pDst
281 //! output buffer to store Surface contents
282 //! \return MOS_STATUS
283 //! MOS_STATUS_SUCCESS if success. Error code otherwise
284 //!
VpHal_ReadSurface(PMOS_INTERFACE pOsInterface,PVPHAL_SURFACE pSurface,uint32_t uBpp,uint8_t * pDst)285 MOS_STATUS VpHal_ReadSurface (
286 PMOS_INTERFACE pOsInterface,
287 PVPHAL_SURFACE pSurface,
288 uint32_t uBpp,
289 uint8_t* pDst)
290 {
291 MOS_STATUS eStatus;
292 uint8_t* pSrc;
293 uint8_t* pTempSrc;
294 uint8_t* pTempDst;
295 uint32_t uSize;
296 uint32_t uWidthInBytes;
297 uint32_t uY;
298 uint32_t uZ;
299 MOS_LOCK_PARAMS LockFlags;
300
301 //----------------------------------------------
302 VPHAL_PUBLIC_ASSERT(pSurface);
303 VPHAL_PUBLIC_ASSERT(pSurface->dwWidth > 0);
304 VPHAL_PUBLIC_ASSERT(pSurface->dwHeight > 0);
305 VPHAL_PUBLIC_ASSERT(pSurface->dwDepth > 0);
306 VPHAL_PUBLIC_ASSERT(pSurface->dwPitch >= pSurface->dwWidth);
307 VPHAL_PUBLIC_ASSERT(uBpp > 0);
308 VPHAL_PUBLIC_ASSERT(pDst);
309 VPHAL_PUBLIC_ASSERT(!Mos_ResourceIsNull(&pSurface->OsResource));
310 //----------------------------------------------
311
312 MOS_ZeroMemory(&LockFlags, sizeof(MOS_LOCK_PARAMS));
313
314 LockFlags.ReadOnly = 1;
315
316 pSrc = (uint8_t*)pOsInterface->pfnLockResource(
317 pOsInterface,
318 &pSurface->OsResource,
319 &LockFlags);
320 VPHAL_PUBLIC_CHK_NULL(pSrc);
321
322 // Calculate Size in Bytes
323 uSize = pSurface->dwWidth * pSurface->dwHeight * pSurface->dwDepth * uBpp/8;
324 uWidthInBytes = pSurface->dwWidth * uBpp / 8;
325 if (pSurface->dwPitch == uWidthInBytes)
326 {
327 MOS_SecureMemcpy(pDst, uSize, pSrc, uSize);
328 }
329 else
330 {
331 pTempSrc = pSrc;
332 pTempDst = pDst;
333
334 for (uZ = 0; uZ < pSurface->dwDepth; uZ++)
335 {
336 for (uY = 0; uY < pSurface->dwHeight; uY++)
337 {
338 MOS_SecureMemcpy(pTempDst, uWidthInBytes, pTempSrc, uWidthInBytes);
339 pTempSrc += pSurface->dwPitch;
340 pTempDst += uWidthInBytes;
341 }
342 }
343 }
344
345 VPHAL_PUBLIC_CHK_STATUS(pOsInterface->pfnUnlockResource(pOsInterface, &pSurface->OsResource));
346
347 finish:
348 return eStatus;
349 }
350
351 //!
352 //! \brief Copy Data from input Buffer to the Surface contents
353 //! \details Copy Data from input Buffer to the Surface contents
354 //! - 1 lock surface
355 //! - 2 copy data from pSrc to Surface
356 //! - 3 unlock surface
357 //! \param [in] pOsInterface
358 //! Pointer to MOS_INTERFACE
359 //! \param [out] pSurface
360 //! Pointer to VPHAL_SURFACE
361 //! \param [in] uBpp
362 //! bit per pixel of input buffer
363 //! \param [in] pSrc
364 //! Input buffer to store Surface contents
365 //! \return MOS_STATUS
366 //! MOS_STATUS_SUCCESS if success. Error code otherwise
367 //!
VpHal_WriteSurface(PMOS_INTERFACE pOsInterface,PVPHAL_SURFACE pSurface,uint32_t uBpp,const uint8_t * pSrc)368 MOS_STATUS VpHal_WriteSurface (
369 PMOS_INTERFACE pOsInterface,
370 PVPHAL_SURFACE pSurface,
371 uint32_t uBpp,
372 const uint8_t* pSrc)
373 {
374 MOS_STATUS eStatus;
375 uint8_t* pDst;
376 uint8_t* pTempSrc;
377 uint8_t* pTempDst;
378 uint32_t uWidthInBytes;
379 uint32_t uSize;
380 uint32_t uY;
381 uint32_t uZ;
382 MOS_LOCK_PARAMS LockFlags;
383
384 //----------------------------------------------
385 VPHAL_PUBLIC_ASSERT(pSurface);
386 VPHAL_PUBLIC_ASSERT(pSurface->dwWidth > 0);
387 VPHAL_PUBLIC_ASSERT(pSurface->dwHeight > 0);
388 VPHAL_PUBLIC_ASSERT(pSurface->dwDepth > 0);
389 VPHAL_PUBLIC_ASSERT(pSurface->dwPitch >= pSurface->dwWidth);
390 VPHAL_PUBLIC_ASSERT(uBpp > 0);
391 VPHAL_PUBLIC_ASSERT(pSrc);
392 VPHAL_PUBLIC_ASSERT(!Mos_ResourceIsNull(&pSurface->OsResource));
393 //----------------------------------------------
394
395 MOS_ZeroMemory(&LockFlags, sizeof(MOS_LOCK_PARAMS));
396
397 LockFlags.WriteOnly = 1;
398
399 pDst = (uint8_t*)pOsInterface->pfnLockResource(
400 pOsInterface,
401 &pSurface->OsResource,
402 &LockFlags);
403 VPHAL_PUBLIC_CHK_NULL(pDst);
404
405 // Calculate Size in Bytes
406 uSize = pSurface->dwWidth * pSurface->dwHeight * pSurface->dwDepth * uBpp/8;
407 uWidthInBytes = pSurface->dwWidth * uBpp/8;
408
409 if (pSurface->dwPitch == uWidthInBytes)
410 {
411 MOS_SecureMemcpy(pDst, uSize, pSrc, uSize);
412 }
413 else
414 {
415 pTempSrc = (uint8_t*)pSrc;
416 pTempDst = pDst;
417
418 for (uZ = 0; uZ < pSurface->dwDepth; uZ++)
419 {
420 for (uY = 0; uY < pSurface->dwHeight; uY++)
421 {
422 MOS_SecureMemcpy(pTempDst, uWidthInBytes, pTempSrc, uWidthInBytes);
423 pTempSrc += uWidthInBytes;
424 pTempDst += pSurface->dwPitch;
425 }
426 }
427 }
428
429 VPHAL_PUBLIC_CHK_STATUS(pOsInterface->pfnUnlockResource(pOsInterface, &pSurface->OsResource));
430
431 finish:
432 return eStatus;
433 }
434
435 //!
436 //! \brief Decide whether Chroma up sampling is needed
437 //! \param [in] pSource
438 //! Pointer to Source Surface
439 //! \param [in] pTarget
440 //! Pointer to Target Surface
441 //! \return bool
442 //! Return true if Chroma up sampling is needed, otherwise false
443 //!
VpHal_IsChromaUpSamplingNeeded(PVPHAL_SURFACE pSource,PVPHAL_SURFACE pTarget)444 bool VpHal_IsChromaUpSamplingNeeded(
445 PVPHAL_SURFACE pSource,
446 PVPHAL_SURFACE pTarget)
447 {
448 bool bChromaUpSampling;
449 VPHAL_COLORPACK srcColorPack, dstColorPack;
450
451 VPHAL_PUBLIC_ASSERT(pSource);
452 VPHAL_PUBLIC_ASSERT(pTarget);
453
454 bChromaUpSampling = false;
455
456 srcColorPack = VpHalDDIUtils::GetSurfaceColorPack(pSource->Format);
457 dstColorPack = VpHalDDIUtils::GetSurfaceColorPack(pTarget->Format);
458
459 if ((srcColorPack == VPHAL_COLORPACK_420 &&
460 (dstColorPack == VPHAL_COLORPACK_422 || dstColorPack == VPHAL_COLORPACK_444)) ||
461 (srcColorPack == VPHAL_COLORPACK_422 && dstColorPack == VPHAL_COLORPACK_444))
462 {
463 bChromaUpSampling = true;
464 }
465
466 return bChromaUpSampling;
467 }
468
469 //!
470 //! \brief Decide whether Chroma down sampling is needed
471 //! \param [in] pSource
472 //! Pointer to Source Surface
473 //! \param [in] pTarget
474 //! Pointer to Target Surface
475 //! \return bool
476 //! Return true if Chroma down sampling is needed, otherwise false
477 //!
VpHal_IsChromaDownSamplingNeeded(PVPHAL_SURFACE pSource,PVPHAL_SURFACE pTarget)478 bool VpHal_IsChromaDownSamplingNeeded(
479 PVPHAL_SURFACE pSource,
480 PVPHAL_SURFACE pTarget)
481 {
482 bool bChromaDownSampling;
483 VPHAL_COLORPACK srcColorPack, dstColorPack;
484
485 VPHAL_PUBLIC_ASSERT(pSource);
486 VPHAL_PUBLIC_ASSERT(pTarget);
487
488 bChromaDownSampling = false;
489
490 srcColorPack = VpHalDDIUtils::GetSurfaceColorPack(pSource->Format);
491 dstColorPack = VpHalDDIUtils::GetSurfaceColorPack(pTarget->Format);
492
493 if ((srcColorPack == VPHAL_COLORPACK_444 &&
494 (dstColorPack == VPHAL_COLORPACK_422 || dstColorPack == VPHAL_COLORPACK_420)) ||
495 (srcColorPack == VPHAL_COLORPACK_422 && dstColorPack == VPHAL_COLORPACK_420))
496 {
497 bChromaDownSampling = true;
498 }
499
500 return bChromaDownSampling;
501 }
502
503 //!
504 //! \brief Get the scale ratio
505 //! \details Get the scale ratio from input surface to output surface
506 //! \param [in] pSource
507 //! Pointer to input Surface
508 //! \param [in] pTarget
509 //! Pointer to output Surface
510 //! \param [out] pfScaleX
511 //! Pointer to scaling ratio x
512 //! \param [out] pfScaleY
513 //! Pointer to scaling ratio y
514 //! \return void
515 //!
VpHal_GetScalingRatio(PVPHAL_SURFACE pSource,PVPHAL_SURFACE pTarget,float * pfScaleX,float * pfScaleY)516 void VpHal_GetScalingRatio(
517 PVPHAL_SURFACE pSource,
518 PVPHAL_SURFACE pTarget,
519 float* pfScaleX,
520 float* pfScaleY)
521 {
522 MOS_UNUSED(pTarget);
523
524 VPHAL_PUBLIC_ASSERT(pSource);
525 VPHAL_PUBLIC_ASSERT(pTarget);
526 VPHAL_PUBLIC_ASSERT(pfScaleX);
527 VPHAL_PUBLIC_ASSERT(pfScaleY);
528
529 float fScaleX = 0.0;
530 float fScaleY = 0.0;
531
532 // Source rectangle is pre-rotated, destination rectangle is post-rotated.
533 if (pSource->Rotation == VPHAL_ROTATION_IDENTITY ||
534 pSource->Rotation == VPHAL_ROTATION_180 ||
535 pSource->Rotation == VPHAL_MIRROR_HORIZONTAL ||
536 pSource->Rotation == VPHAL_MIRROR_VERTICAL)
537 {
538 fScaleX = (float)(pSource->rcDst.right - pSource->rcDst.left) /
539 (float)(pSource->rcSrc.right - pSource->rcSrc.left);
540 fScaleY = (float)(pSource->rcDst.bottom - pSource->rcDst.top) /
541 (float)(pSource->rcSrc.bottom - pSource->rcSrc.top);
542 }
543 else
544 {
545 // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 ||
546 // VPHAL_ROTATE_90_MIRROR_HORIZONTAL || VPHAL_ROTATE_90_MIRROR_VERTICAL
547 fScaleX = (float)(pSource->rcDst.bottom - pSource->rcDst.top) /
548 (float)(pSource->rcSrc.right - pSource->rcSrc.left);
549 fScaleY = (float)(pSource->rcDst.right - pSource->rcDst.left) /
550 (float)(pSource->rcSrc.bottom - pSource->rcSrc.top);
551 }
552
553 *pfScaleX = fScaleX;
554 *pfScaleY = fScaleY;
555 }
556
557 //! \brief Transfer float type to half precision float type
558 //! \details Transfer float type to half precision float (16bit) type
559 //! \param [in] fInputA
560 //! input FP32 number
561 //! \return uint16_t
562 //! half precision float value in bit
563 //!
VpHal_FloatToHalfFloatA(float fInputA)564 uint16_t VpHal_FloatToHalfFloatA(float fInputA)
565 {
566
567 FP32 fInput = *(FP32*)(&fInputA);
568 FP16 fOutput = { 0 };
569
570 // Based on ISPC reference code (with minor modifications)
571 if (fInput.Exponent == 0) // Signed zero/denormal (which will underflow)
572 {
573 fOutput.Exponent = 0;
574 }
575 else if (fInput.Exponent == 255) // Inf or NaN (all exponent bits set)
576 {
577 fOutput.Exponent = 31;
578 fOutput.Mantissa = fInput.Mantissa ? 0x200 : 0; // NaN->qNaN and Inf->Inf
579 }
580 else // Normalized number
581 {
582 // Exponent unbias the single, then bias the halfp
583 int newexp = fInput.Exponent - 127 + 15;
584 if (newexp >= 31) // Overflow, return signed infinity
585 {
586 fOutput.Exponent = 31;
587 }
588 else if (newexp <= 0) // Underflow
589 {
590 if ((14 - newexp) <= 24) // Mantissa might be non-zero
591 {
592 uint32_t mant = fInput.Mantissa | 0x800000; // Hidden 1 bit
593 fOutput.Mantissa = mant >> (14 - newexp);
594 if ((mant >> (13 - newexp)) & 1) // Check for rounding
595 {
596 fOutput.u++; // Round, might overflow into exp bit, but this is OK
597 }
598 }
599 }
600 else
601 {
602 fOutput.Exponent = newexp;
603 fOutput.Mantissa = fInput.Mantissa >> 13;
604 if (fInput.Mantissa & 0x1000) // Check for rounding
605 {
606 fOutput.u++; // Round, might overflow to inf, this is OK
607 }
608 }
609 }
610
611 fOutput.Sign = fInput.Sign;
612 uint16_t res = *(uint16_t*)(&fOutput);
613 return res;
614 }
615