From 549e4ba6eb74774ebd3c2a510e0acdf182d57f79 Mon Sep 17 00:00:00 2001 From: elasota Date: Sun, 20 May 2018 00:47:13 -0400 Subject: [PATCH] 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; + } + } }