Skip to content

Commit 94fc437

Browse files
committed
More work on 3D swizzle
1 parent 68b9cc7 commit 94fc437

File tree

1 file changed

+204
-75
lines changed

1 file changed

+204
-75
lines changed

DirectXTex/DirectXTexSwizzle.cpp

+204-75
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace
2424
#else
2525
// N3864 - A constexpr bitwise operations library for C++
2626
// https://github.com/fmatthew5876/stdcxx-bitops
27-
uint32_t deposit_bits(uint32_t val, int mask)
27+
uint32_t deposit_bits(uint32_t val, int mask) noexcept
2828
{
2929
uint32_t res = 0;
3030
for (uint32_t bb = 1; mask != 0; bb += bb)
@@ -38,7 +38,7 @@ namespace
3838
return res;
3939
}
4040

41-
uint32_t extract_bits(uint32_t val, int mask)
41+
uint32_t extract_bits(uint32_t val, int mask) noexcept
4242
{
4343
uint32_t res = 0;
4444
for (uint32_t bb = 1; mask !=0; bb += bb)
@@ -61,6 +61,64 @@ namespace
6161
constexpr size_t MAX_TEXTURE_SIZE = UINT32_MAX;
6262
#endif
6363

64+
// Standard Swizzle is not defined for these formats.
65+
bool IsExcludedFormat(DXGI_FORMAT fmt) noexcept
66+
{
67+
switch(static_cast<int>(fmt))
68+
{
69+
// 96bpp
70+
case DXGI_FORMAT_R32G32B32_TYPELESS:
71+
case DXGI_FORMAT_R32G32B32_FLOAT:
72+
case DXGI_FORMAT_R32G32B32_UINT:
73+
case DXGI_FORMAT_R32G32B32_SINT:
74+
75+
// Depth/stencil
76+
case DXGI_FORMAT_R32G8X24_TYPELESS:
77+
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
78+
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
79+
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
80+
case DXGI_FORMAT_D32_FLOAT:
81+
case DXGI_FORMAT_R24G8_TYPELESS:
82+
case DXGI_FORMAT_D24_UNORM_S8_UINT:
83+
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
84+
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
85+
case DXGI_FORMAT_D16_UNORM:
86+
case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT:
87+
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
88+
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
89+
90+
// Monochrome
91+
case DXGI_FORMAT_R1_UNORM:
92+
93+
// Packed
94+
case DXGI_FORMAT_R8G8_B8G8_UNORM:
95+
case DXGI_FORMAT_G8R8_G8B8_UNORM:
96+
case DXGI_FORMAT_YUY2:
97+
case DXGI_FORMAT_Y210:
98+
case DXGI_FORMAT_Y216:
99+
100+
// Planar
101+
case DXGI_FORMAT_NV12:
102+
case DXGI_FORMAT_P010:
103+
case DXGI_FORMAT_P016:
104+
case DXGI_FORMAT_420_OPAQUE:
105+
case DXGI_FORMAT_NV11:
106+
case WIN10_DXGI_FORMAT_P208:
107+
case WIN10_DXGI_FORMAT_V208:
108+
case WIN10_DXGI_FORMAT_V408:
109+
110+
// Palettized
111+
case DXGI_FORMAT_AI44:
112+
case DXGI_FORMAT_IA44:
113+
case DXGI_FORMAT_P8:
114+
case DXGI_FORMAT_A8P8:
115+
return true;
116+
117+
default:
118+
return false;
119+
}
120+
}
121+
64122
//-------------------------------------------------------------------------------------
65123
// 2D z-order curve
66124
//-------------------------------------------------------------------------------------
@@ -218,40 +276,55 @@ namespace
218276
constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_64 = 0b0010010011000111;
219277
constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_128 = 0b0010010011001111;
220278

221-
inline int GetSwizzleMask3D_X(size_t bytesPerPixel) noexcept
222-
{
223-
switch(bytesPerPixel)
224-
{
225-
case 1: return VOLUME_STANDARD_SWIZZLE_X_8;
226-
case 2: return VOLUME_STANDARD_SWIZZLE_X_16;
227-
case 8: return VOLUME_STANDARD_SWIZZLE_X_64;
228-
case 16: return VOLUME_STANDARD_SWIZZLE_X_128;
229-
default: return VOLUME_STANDARD_SWIZZLE_X_32;
230-
}
231-
}
279+
// We rely on the fact that ScratchImage will put all slices in the same mip level
280+
// in continous memory. We do not assume that is true of the source images.
232281

233-
inline int GetSwizzleMask3D_Y(size_t bytesPerPixel) noexcept
282+
//---------------------------------------------------------------------------------
283+
// row-major to z-order curve
284+
//---------------------------------------------------------------------------------
285+
template<int xBytesMask, int yBytesMask, int zBytesMask, size_t bytesPerPixel>
286+
HRESULT LinearToStandardSwizzle3D(
287+
_In_reads_(depth) const Image* srcImages,
288+
const Image& destImage,
289+
size_t depth,
290+
bool isCompressed) noexcept
234291
{
235-
switch(bytesPerPixel)
236-
{
237-
case 1: return VOLUME_STANDARD_SWIZZLE_Y_8;
238-
case 2: return VOLUME_STANDARD_SWIZZLE_Y_16;
239-
case 8: return VOLUME_STANDARD_SWIZZLE_Y_64;
240-
case 16: return VOLUME_STANDARD_SWIZZLE_Y_128;
241-
default: return VOLUME_STANDARD_SWIZZLE_Y_32;
242-
}
292+
if (!srcImages || !depth)
293+
return E_INVALIDARG;
294+
295+
uint8_t* dptr = destImage.pixels;
296+
if (!dptr)
297+
return E_POINTER;
298+
299+
if (destImage.rowPitch > UINT32_MAX)
300+
return HRESULT_E_ARITHMETIC_OVERFLOW;
301+
302+
// TODO: linear to swizzle x,y,z
303+
return E_NOTIMPL;
243304
}
244305

245-
inline int GetSwizzleMask3D_Z(size_t bytesPerPixel) noexcept
306+
//---------------------------------------------------------------------------------
307+
// z-order curve to row-major
308+
//---------------------------------------------------------------------------------
309+
template<int xBytesMask, int yBytesMask, int zBytesMask, size_t bytesPerPixel>
310+
HRESULT StandardSwizzleToLinear3D(
311+
_In_reads_(depth) const Image* srcImages,
312+
const Image& destImage,
313+
size_t depth,
314+
bool isCompressed) noexcept
246315
{
247-
switch(bytesPerPixel)
248-
{
249-
case 1: return VOLUME_STANDARD_SWIZZLE_Z_8;
250-
case 2: return VOLUME_STANDARD_SWIZZLE_Z_16;
251-
case 8: return VOLUME_STANDARD_SWIZZLE_Z_64;
252-
case 16: return VOLUME_STANDARD_SWIZZLE_Z_128;
253-
default: return VOLUME_STANDARD_SWIZZLE_Z_32;
254-
}
316+
if (!srcImages || !depth)
317+
return E_INVALIDARG;
318+
319+
uint8_t* dptr = destImage.pixels;
320+
if (!dptr)
321+
return E_POINTER;
322+
323+
if (destImage.rowPitch > UINT32_MAX)
324+
return HRESULT_E_ARITHMETIC_OVERFLOW;
325+
326+
// TODO: swizzle x,y,z to linear
327+
return E_NOTIMPL;
255328
}
256329
}
257330

@@ -273,7 +346,7 @@ HRESULT DirectX::StandardSwizzle(
273346
return HRESULT_E_NOT_SUPPORTED;
274347
}
275348

276-
if (IsPlanar(srcImage.format) || IsPalettized(srcImage.format) || (srcImage.format == DXGI_FORMAT_R1_UNORM))
349+
if (IsExcludedFormat(srcImage.format))
277350
return HRESULT_E_NOT_SUPPORTED;
278351

279352
if (!srcImage.pixels)
@@ -368,7 +441,7 @@ HRESULT DirectX::StandardSwizzle(
368441
return HRESULT_E_NOT_SUPPORTED;
369442
}
370443

371-
if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || (metadata.format == DXGI_FORMAT_R1_UNORM))
444+
if (IsExcludedFormat(metadata.format))
372445
return HRESULT_E_NOT_SUPPORTED;
373446

374447
HRESULT hr = result.Initialize(metadata);
@@ -398,8 +471,104 @@ HRESULT DirectX::StandardSwizzle(
398471

399472
if (metadata.dimension == TEX_DIMENSION_TEXTURE3D)
400473
{
401-
// TODO -
402-
return E_NOTIMPL;
474+
size_t index = 0;
475+
size_t depth = metadata.depth;
476+
for (size_t level = 0; level < metadata.mipLevels; ++level)
477+
{
478+
const Image* srcBase = &srcImages[index];
479+
const Image& destBase = dest[index];
480+
481+
for(size_t slice = 0; slice < depth; ++slice, ++index)
482+
{
483+
if (index >= nimages)
484+
{
485+
result.Release();
486+
return E_UNEXPECTED;
487+
}
488+
489+
const Image& src = srcImages[index];
490+
if (!src.pixels)
491+
{
492+
result.Release();
493+
return E_POINTER;
494+
}
495+
496+
if (src.format != metadata.format)
497+
{
498+
result.Release();
499+
return E_FAIL;
500+
}
501+
502+
if ((src.width > MAX_TEXTURE_DIMENSION) || (src.height > MAX_TEXTURE_DIMENSION))
503+
{
504+
result.Release();
505+
return E_FAIL;
506+
}
507+
508+
const Image& dst = dest[index];
509+
assert(dst.format == metadata.format);
510+
511+
if (src.width != dst.width || src.height != dst.height)
512+
{
513+
result.Release();
514+
return E_FAIL;
515+
}
516+
}
517+
518+
if (toSwizzle)
519+
{
520+
switch(bytesPerPixel)
521+
{
522+
case 1:
523+
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_8, VOLUME_STANDARD_SWIZZLE_Y_8, VOLUME_STANDARD_SWIZZLE_Z_8, 1>(srcBase, destBase, depth, false);
524+
break;
525+
case 2:
526+
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_16, VOLUME_STANDARD_SWIZZLE_Y_16, VOLUME_STANDARD_SWIZZLE_Z_16, 2>(srcBase, destBase, depth, false);
527+
break;
528+
case 8:
529+
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_64, VOLUME_STANDARD_SWIZZLE_Y_64, VOLUME_STANDARD_SWIZZLE_Z_64, 8>(srcBase, destBase, depth, isCompressed);
530+
break;
531+
case 16:
532+
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_128, VOLUME_STANDARD_SWIZZLE_Y_128, VOLUME_STANDARD_SWIZZLE_Z_128, 16>(srcBase, destBase, depth, isCompressed);
533+
break;
534+
default:
535+
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_32, VOLUME_STANDARD_SWIZZLE_Y_32, VOLUME_STANDARD_SWIZZLE_Z_32, 4>(srcBase, destBase, depth, false);
536+
break;
537+
}
538+
}
539+
else
540+
{
541+
switch(bytesPerPixel)
542+
{
543+
case 1:
544+
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_8, VOLUME_STANDARD_SWIZZLE_Y_8, VOLUME_STANDARD_SWIZZLE_Z_8, 1>(srcBase, destBase, depth, false);
545+
break;
546+
case 2:
547+
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_16, VOLUME_STANDARD_SWIZZLE_Y_16, VOLUME_STANDARD_SWIZZLE_Z_16, 2>(srcBase, destBase, depth, false);
548+
break;
549+
case 8:
550+
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_64, VOLUME_STANDARD_SWIZZLE_Y_64, VOLUME_STANDARD_SWIZZLE_Z_64, 8>(srcBase, destBase, depth, isCompressed);
551+
break;
552+
case 16:
553+
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_128, VOLUME_STANDARD_SWIZZLE_Y_128, VOLUME_STANDARD_SWIZZLE_Z_128, 16>(srcBase, destBase, depth, isCompressed);
554+
break;
555+
default:
556+
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_32, VOLUME_STANDARD_SWIZZLE_Y_32, VOLUME_STANDARD_SWIZZLE_Z_32, 4>(srcBase, destBase, depth, false);
557+
break;
558+
}
559+
}
560+
561+
if (FAILED(hr))
562+
{
563+
result.Release();
564+
return hr;
565+
}
566+
567+
if (depth > 1)
568+
depth >>= 1;
569+
}
570+
571+
return S_OK;
403572
}
404573
else
405574
{
@@ -484,43 +653,6 @@ HRESULT DirectX::StandardSwizzle(
484653

485654

486655
#if 0
487-
// TODO: merging into main based on metadata
488-
_Use_decl_annotations_
489-
HRESULT DirectX::StandardSwizzle3D(
490-
const Image* srcImages,
491-
size_t depth,
492-
const TexMetadata& metadata,
493-
bool toSwizzle,
494-
ScratchImage& result) noexcept
495-
{
496-
if (!srcImages || !depth || (metadata.dimension != TEX_DIMENSION_TEXTURE3D))
497-
return E_INVALIDARG;
498-
499-
if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || (metadata.format == DXGI_FORMAT_R1_UNORM))
500-
return HRESULT_E_NOT_SUPPORTED;
501-
502-
HRESULT hr = result.Initialize(metadata);
503-
if (FAILED(hr))
504-
return hr;
505-
506-
if ((depth * metadata.mipLevels) != result.GetImageCount())
507-
{
508-
result.Release();
509-
return E_FAIL;
510-
}
511-
512-
const bool isCompressed = IsCompressed(metadata.format);
513-
const size_t bytesPerPixel = isCompressed ? BytesPerBlock(metadata.format) : (BitsPerPixel(metadata.format) / 8);
514-
if (!bytesPerPixel)
515-
{
516-
result.Release();
517-
return E_FAIL;
518-
}
519-
520-
const int xBytesMask = GetSwizzleMask3D_X(metadata.format);
521-
const int yBytesMask = GetSwizzleMask3D_Y(metadata.format);
522-
const int zBytesMask = GetSwizzleMask3D_Z(metadata.format);
523-
524656
if (toSwizzle)
525657
{
526658
// row-major to z-order curve
@@ -584,7 +716,4 @@ HRESULT DirectX::StandardSwizzle3D(
584716
}
585717
}
586718
}
587-
588-
return S_OK;
589-
}
590719
#endif

0 commit comments

Comments
 (0)