Skip to content

Commit ab4e114

Browse files
committed
Add float conversion flags
1 parent 40b3b10 commit ab4e114

File tree

5 files changed

+47
-16
lines changed

5 files changed

+47
-16
lines changed

DirectXTex/DirectXTex.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,12 @@ namespace DirectX
450450
TEX_FILTER_FLOAT_X2BIAS = 0x200,
451451
// Enable *2 - 1 conversion cases for unorm<->float and positive-only float formats
452452

453+
TEX_FILTER_FLOAT_SATURATE_TO_INF = 0x400,
454+
// When converting to smaller float formats, saturate out-of-range values to +INF/-INF instead of largest in-range value
455+
456+
TEX_FILTER_FLOAT_KEEP_NANS = 0x800,
457+
// When converting to smaller float formats, preserve NaNs instead of converting to zero
458+
453459
TEX_FILTER_RGB_COPY_RED = 0x1000,
454460
TEX_FILTER_RGB_COPY_GREEN = 0x2000,
455461
TEX_FILTER_RGB_COPY_BLUE = 0x4000,

DirectXTex/DirectXTexConvert.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,30 @@ namespace
192192
const XMVECTORF32 g_HalfMin = { { { -65504.f, -65504.f, -65504.f, -65504.f } } };
193193
const XMVECTORF32 g_HalfMax = { { { 65504.f, 65504.f, 65504.f, 65504.f } } };
194194
const XMVECTORF32 g_8BitBias = { { { 0.5f / 255.f, 0.5f / 255.f, 0.5f / 255.f, 0.5f / 255.f } } };
195+
196+
inline void SanitizeFloat16(XMVECTOR& v, DWORD flags)
197+
{
198+
// Convert NaNs to 0.0f
199+
if (!(flags & TEX_FILTER_FLOAT_KEEP_NANS))
200+
v = XMVectorSelect(XMVectorZero(), v, XMVectorIsNaN(v));
201+
202+
if (!(flags & TEX_FILTER_FLOAT_SATURATE_TO_INF))
203+
v = XMVectorClamp(v, g_HalfMin, g_HalfMax);
204+
}
205+
206+
inline void SanitizeFloat16(float& v, DWORD flags)
207+
{
208+
if (std::isnan(v))
209+
{
210+
if (!(flags & TEX_FILTER_FLOAT_KEEP_NANS))
211+
v = 0.0f;
212+
}
213+
else
214+
{
215+
if (!(flags & TEX_FILTER_FLOAT_SATURATE_TO_INF))
216+
v = std::min(std::max(v, -65504.f), 65504.f);
217+
}
218+
}
195219
}
196220

197221
//-------------------------------------------------------------------------------------
@@ -1609,7 +1633,8 @@ bool DirectX::_StoreScanline(
16091633
DXGI_FORMAT format,
16101634
const XMVECTOR* pSource,
16111635
size_t count,
1612-
float threshold)
1636+
float threshold,
1637+
DWORD flags)
16131638
{
16141639
assert(pDestination && size > 0);
16151640
assert(pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0));
@@ -1649,7 +1674,7 @@ bool DirectX::_StoreScanline(
16491674
{
16501675
if (sPtr >= ePtr) break;
16511676
XMVECTOR v = *sPtr++;
1652-
v = XMVectorClamp(v, g_HalfMin, g_HalfMax);
1677+
SanitizeFloat16(v, flags);
16531678
XMStoreHalf4(dPtr++, v);
16541679
}
16551680
return true;
@@ -1743,7 +1768,7 @@ bool DirectX::_StoreScanline(
17431768
{
17441769
if (sPtr >= ePtr) break;
17451770
XMVECTOR v = *sPtr++;
1746-
v = XMVectorClamp(v, g_HalfMin, g_HalfMax);
1771+
SanitizeFloat16(v, flags);
17471772
XMStoreHalf2(dPtr++, v);
17481773
}
17491774
return true;
@@ -1842,7 +1867,7 @@ bool DirectX::_StoreScanline(
18421867
{
18431868
if (sPtr >= ePtr) break;
18441869
float v = XMVectorGetX(*sPtr++);
1845-
v = std::max<float>(std::min<float>(v, 65504.f), -65504.f);
1870+
SanitizeFloat16(v, flags);
18461871
*(dPtr++) = XMConvertFloatToHalf(v);
18471872
}
18481873
return true;
@@ -2699,7 +2724,7 @@ bool DirectX::_StoreScanlineLinear(
26992724
}
27002725
}
27012726

2702-
return _StoreScanline(pDestination, size, format, pSource, count, threshold);
2727+
return _StoreScanline(pDestination, size, format, pSource, count, threshold, flags);
27032728
}
27042729

27052730

@@ -4542,7 +4567,7 @@ namespace
45424567

45434568
_ConvertScanline(scanline.get(), width, destImage.format, srcImage.format, filter);
45444569

4545-
if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), width, threshold))
4570+
if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), width, threshold, filter))
45464571
return E_FAIL;
45474572

45484573
pSrc += srcImage.rowPitch;

DirectXTex/DirectXTexMipmaps.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ namespace
641641
}
642642

643643
//--- 2D Point Filter ---
644-
HRESULT Generate2DMipsPointFilter(size_t levels, const ScratchImage& mipChain, size_t item)
644+
HRESULT Generate2DMipsPointFilter(size_t levels, const ScratchImage& mipChain, size_t item, DWORD flags)
645645
{
646646
if (!mipChain.GetImages())
647647
return E_INVALIDARG;
@@ -706,7 +706,7 @@ namespace
706706
sx += xinc;
707707
}
708708

709-
if (!_StoreScanline(pDest, dest->rowPitch, dest->format, target, nwidth))
709+
if (!_StoreScanline(pDest, dest->rowPitch, dest->format, target, nwidth, 0.0f, flags))
710710
return E_FAIL;
711711
pDest += dest->rowPitch;
712712

@@ -1386,7 +1386,7 @@ namespace
13861386

13871387

13881388
//--- 3D Point Filter ---
1389-
HRESULT Generate3DMipsPointFilter(size_t depth, size_t levels, const ScratchImage& mipChain)
1389+
HRESULT Generate3DMipsPointFilter(size_t depth, size_t levels, const ScratchImage& mipChain, DWORD flags)
13901390
{
13911391
if (!depth || !mipChain.GetImages())
13921392
return E_INVALIDARG;
@@ -1460,7 +1460,7 @@ namespace
14601460
sx += xinc;
14611461
}
14621462

1463-
if (!_StoreScanline(pDest, dest->rowPitch, dest->format, target, nwidth))
1463+
if (!_StoreScanline(pDest, dest->rowPitch, dest->format, target, nwidth, 0.0f, flags))
14641464
return E_FAIL;
14651465
pDest += dest->rowPitch;
14661466

@@ -2658,7 +2658,7 @@ HRESULT DirectX::GenerateMipMaps(
26582658
if (FAILED(hr))
26592659
return hr;
26602660

2661-
hr = Generate2DMipsPointFilter(levels, mipChain, 0);
2661+
hr = Generate2DMipsPointFilter(levels, mipChain, 0, filter);
26622662
if (FAILED(hr))
26632663
mipChain.Release();
26642664
return hr;
@@ -2856,7 +2856,7 @@ HRESULT DirectX::GenerateMipMaps(
28562856

28572857
for (size_t item = 0; item < metadata.arraySize; ++item)
28582858
{
2859-
hr = Generate2DMipsPointFilter(levels, mipChain, item);
2859+
hr = Generate2DMipsPointFilter(levels, mipChain, item, filter);
28602860
if (FAILED(hr))
28612861
mipChain.Release();
28622862
}
@@ -2978,7 +2978,7 @@ HRESULT DirectX::GenerateMipMaps3D(
29782978
if (FAILED(hr))
29792979
return hr;
29802980

2981-
hr = Generate3DMipsPointFilter(depth, levels, mipChain);
2981+
hr = Generate3DMipsPointFilter(depth, levels, mipChain, filter);
29822982
if (FAILED(hr))
29832983
mipChain.Release();
29842984
return hr;
@@ -3094,7 +3094,7 @@ HRESULT DirectX::GenerateMipMaps3D(
30943094
if (FAILED(hr))
30953095
return hr;
30963096

3097-
hr = Generate3DMipsPointFilter(metadata.depth, levels, mipChain);
3097+
hr = Generate3DMipsPointFilter(metadata.depth, levels, mipChain, filter);
30983098
if (FAILED(hr))
30993099
mipChain.Release();
31003100
return hr;

DirectXTex/DirectXTexMisc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ HRESULT DirectX::CopyRectangle(
364364

365365
_ConvertScanline(scanline.get(), srcRect.w, dstImage.format, srcImage.format, filter);
366366

367-
if (!_StoreScanline(pDest, copyD, dstImage.format, scanline.get(), srcRect.w))
367+
if (!_StoreScanline(pDest, copyD, dstImage.format, scanline.get(), srcRect.w, 0.0f, filter))
368368
return E_FAIL;
369369

370370
pSrc += srcImage.rowPitch;

DirectXTex/DirectXTexP.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ namespace DirectX
242242

243243
_Success_(return != false) bool __cdecl _StoreScanline(
244244
_Out_writes_bytes_(size) void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
245-
_In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0);
245+
_In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0, _In_ DWORD flags = 0);
246246

247247
_Success_(return != false) bool __cdecl _StoreScanlineLinear(
248248
_Out_writes_bytes_(size) void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,

0 commit comments

Comments
 (0)