From 549e4ba6eb74774ebd3c2a510e0acdf182d57f79 Mon Sep 17 00:00:00 2001 From: elasota Date: Sun, 20 May 2018 00:47:13 -0400 Subject: [PATCH 1/4] Move half float sanitization out of StoreScanline and to Convert, add sanitization control flags. --- DirectXTex/DirectXTex.h | 6 ++++++ DirectXTex/DirectXTexConvert.cpp | 26 ++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 4b411fe1..ac068e79 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -450,6 +450,12 @@ namespace DirectX TEX_FILTER_FLOAT_X2BIAS = 0x200, // Enable *2 - 1 conversion cases for unorm<->float and positive-only float formats + TEX_FILTER_FLOAT16_SATURATE_TO_INF = 0x400, + // When converting to half float, saturate out-of-range values to +INF/-INF instead of largest in-range value + + TEX_FILTER_FLOAT16_KEEP_NANS = 0x800, + // When converting to half float, preserve NaNs instead of converting to zero + TEX_FILTER_RGB_COPY_RED = 0x1000, TEX_FILTER_RGB_COPY_GREEN = 0x2000, TEX_FILTER_RGB_COPY_BLUE = 0x4000, diff --git a/DirectXTex/DirectXTexConvert.cpp b/DirectXTex/DirectXTexConvert.cpp index 00958770..7c110d1d 100644 --- a/DirectXTex/DirectXTexConvert.cpp +++ b/DirectXTex/DirectXTexConvert.cpp @@ -1648,9 +1648,7 @@ bool DirectX::_StoreScanline( for (size_t icount = 0; icount < (size - sizeof(XMHALF4) + 1); icount += sizeof(XMHALF4)) { if (sPtr >= ePtr) break; - XMVECTOR v = *sPtr++; - v = XMVectorClamp(v, g_HalfMin, g_HalfMax); - XMStoreHalf4(dPtr++, v); + XMStoreHalf4(dPtr++, *sPtr++); } return true; } @@ -1841,9 +1839,7 @@ bool DirectX::_StoreScanline( for (size_t icount = 0; icount < (size - sizeof(HALF) + 1); icount += sizeof(HALF)) { if (sPtr >= ePtr) break; - float v = XMVectorGetX(*sPtr++); - v = std::max(std::min(v, 65504.f), -65504.f); - *(dPtr++) = XMConvertFloatToHalf(v); + *(dPtr++) = XMConvertFloatToHalf(XMVectorGetX(*sPtr++)); } return true; } @@ -3598,6 +3594,24 @@ void DirectX::_ConvertScanline( } } } + + // Half-float sanitization + if (!(out->flags & CONVF_DEPTH) && (out->flags & CONVF_FLOAT) && out->datasize == 16 && (!(flags & TEX_FILTER_FLOAT16_SATURATE_TO_INF) || !(flags & TEX_FILTER_FLOAT16_KEEP_NANS))) + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i, ++ptr) + { + XMVECTOR v = *ptr; + + if (!(flags & TEX_FILTER_FLOAT16_SATURATE_TO_INF)) + v = XMVectorClamp(v, g_HalfMin, g_HalfMax); + + if (!(flags & TEX_FILTER_FLOAT16_KEEP_NANS)) + v = XMVectorSelect(v, XMVectorZero(), XMVectorIsNaN(v)); + + *ptr = v; + } + } } From 1b531b25ebc4340e463a7174c6db1a3a17210f0a Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Sat, 18 Mar 2023 21:33:18 -0700 Subject: [PATCH 2/4] Update DirectXTex.h Trim whitespace --- DirectXTex/DirectXTex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 7552327c..c9afdbda 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -575,7 +575,7 @@ namespace DirectX TEX_FILTER_FLOAT16_SATURATE_TO_INF = 0x400, TEX_FILTER_FLOAT16_KEEP_NANS = 0x800, // Float to half16 conversion options - + TEX_FILTER_RGB_COPY_RED = 0x1000, TEX_FILTER_RGB_COPY_GREEN = 0x2000, TEX_FILTER_RGB_COPY_BLUE = 0x4000, From e61095099e53dcffbfb5f0db937781a7c35cc144 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Sat, 18 Mar 2023 21:47:27 -0700 Subject: [PATCH 3/4] Update DirectXTexConvert.cpp Code review --- DirectXTex/DirectXTexConvert.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/DirectXTex/DirectXTexConvert.cpp b/DirectXTex/DirectXTexConvert.cpp index 31cc2df1..37b99099 100644 --- a/DirectXTex/DirectXTexConvert.cpp +++ b/DirectXTex/DirectXTexConvert.cpp @@ -3721,8 +3721,11 @@ void DirectX::Internal::ConvertScanline( } // Half-float sanitization - if (!(out->flags & CONVF_DEPTH) && (out->flags & CONVF_FLOAT) && out->datasize == 16 && (!(flags & TEX_FILTER_FLOAT16_SATURATE_TO_INF) || !(flags & TEX_FILTER_FLOAT16_KEEP_NANS))) + if (((out->flags & (CONVF_FLOAT | CONVF_DEPTH)) == CONVF_FLOAT) + && (out->datasize == 16) + && ((flags & (TEX_FILTER_FLOAT16_SATURATE_TO_INF | TEX_FILTER_FLOAT16_KEEP_NANS)) != (TEX_FILTER_FLOAT16_SATURATE_TO_INF | TEX_FILTER_FLOAT16_KEEP_NANS))) { + const XMVECTOR zero = XMVectorZero(); XMVECTOR* ptr = pBuffer; for (size_t i = 0; i < count; ++i, ++ptr) { @@ -3732,7 +3735,7 @@ void DirectX::Internal::ConvertScanline( v = XMVectorClamp(v, g_HalfMin, g_HalfMax); if (!(flags & TEX_FILTER_FLOAT16_KEEP_NANS)) - v = XMVectorSelect(v, XMVectorZero(), XMVectorIsNaN(v)); + v = XMVectorSelect(v, zero, XMVectorIsNaN(v)); *ptr = v; } From 691e4e5b04547f7969a80efffe428c9c4d702cec Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Sat, 18 Mar 2023 21:58:03 -0700 Subject: [PATCH 4/4] Update DirectXTexConvert.cpp Conversion logic for WIC vs. non-WIC update for new flags. --- DirectXTex/DirectXTexConvert.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/DirectXTex/DirectXTexConvert.cpp b/DirectXTex/DirectXTexConvert.cpp index 37b99099..a1515f55 100644 --- a/DirectXTex/DirectXTexConvert.cpp +++ b/DirectXTex/DirectXTexConvert.cpp @@ -4458,6 +4458,12 @@ namespace return false; } + if (filter & (TEX_FILTER_FLOAT16_SATURATE_TO_INF | TEX_FILTER_FLOAT16_KEEP_NANS)) + { + // Float16 specials preservation not supported by WIC code paths + return false; + } + // Check for special cases #if (defined(_XBOX_ONE) && defined(_TITLE)) || defined(_GAMING_XBOX) if (sformat == DXGI_FORMAT_R16G16B16A16_FLOAT