close
Skip to content
Open
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2ba0289
[Draft]
isplunke Sep 17, 2024
0a8c5bf
Moved functionst to new file DirectTexSwizzle
isplunke Sep 18, 2024
e29108a
cleanup move
isplunke Sep 18, 2024
406787d
added 3D
isplunke Sep 18, 2024
061f06c
Almost handel Block Compression.
isplunke Sep 19, 2024
f3b95e0
Fix 3d swizzle idexing into multiple images
isplunke Sep 19, 2024
c5ef2db
Undo: Almost handel Block Compression.
isplunke Sep 19, 2024
1ecf426
name the file in itself
isplunke Sep 19, 2024
b35faa5
handle compression... this time?
isplunke Sep 19, 2024
3466ba5
use extractBits
isplunke Sep 20, 2024
9be0db5
Update DirectXTexSwizzle.cpp
walbourn Sep 24, 2024
e5395d8
Update DirectXTexSwizzle.cpp
walbourn Sep 24, 2024
d70fef1
Update DirectXTexSwizzle.cpp
walbourn Sep 25, 2024
6f19a5a
Update DirectXTexSwizzle.cpp
walbourn Sep 25, 2024
93cb5a2
Update CMakeLists.txt
walbourn Sep 25, 2024
a41c71e
Update remaining vcxproj for new file
Sep 25, 2024
68b9cc7
StandardSwizzle3D merged into main function
Sep 25, 2024
94fc437
More work on 3D swizzle
Sep 26, 2024
74f7445
More code review
Sep 26, 2024
c0e91fc
Attempt to fix CodeQL warning
walbourn Nov 5, 2024
0cbb90b
Add 3D case for linear to swizzle
walbourn Mar 8, 2025
97dbf1a
Add DIRECTX_TEX_API to StandardSwizzle functions
walbourn Mar 9, 2025
f46356d
Implement 3D swizzle to linear
walbourn Mar 10, 2025
d3192d8
Delete DirectXTex/DirectXTex_Desktop_2019.vcxproj
walbourn Aug 6, 2026
1e31208
Delete DirectXTex/DirectXTex_Desktop_2019.vcxproj.filters
walbourn Aug 6, 2026
6dad807
Delete DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj
walbourn Aug 6, 2026
65f061a
Delete DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj.filters
walbourn Aug 6, 2026
2c64427
Delete DirectXTex/DirectXTex_GDK_2019.vcxproj
walbourn Aug 6, 2026
ef8492d
Delete DirectXTex/DirectXTex_GDK_2019.vcxproj.filters
walbourn Aug 6, 2026
9d3dddc
Delete DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj
walbourn Aug 6, 2026
88fa825
Delete DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj.filters
walbourn Aug 6, 2026
2c4abc8
Revert all vcxproj changes
walbourn Aug 6, 2026
1467da9
Code review feedback
walbourn Aug 6, 2026
b9d77da
Update DirectXTexSwizzle.cpp
walbourn Aug 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
More work on 3D swizzle
  • Loading branch information
Chuck Walbourn
Chuck Walbourn committed Sep 26, 2024
commit 94fc4373d284944f6b06439f19234efd630e7d6a
279 changes: 204 additions & 75 deletions DirectXTex/DirectXTexSwizzle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace
#else
// N3864 - A constexpr bitwise operations library for C++
// https://github.com/fmatthew5876/stdcxx-bitops
uint32_t deposit_bits(uint32_t val, int mask)
uint32_t deposit_bits(uint32_t val, int mask) noexcept
{
uint32_t res = 0;
for (uint32_t bb = 1; mask != 0; bb += bb)
Expand All @@ -38,7 +38,7 @@ namespace
return res;
}

uint32_t extract_bits(uint32_t val, int mask)
uint32_t extract_bits(uint32_t val, int mask) noexcept
{
uint32_t res = 0;
for (uint32_t bb = 1; mask !=0; bb += bb)
Comment thread
walbourn marked this conversation as resolved.
Outdated
Expand All @@ -61,6 +61,64 @@ namespace
constexpr size_t MAX_TEXTURE_SIZE = UINT32_MAX;
#endif

// Standard Swizzle is not defined for these formats.
Comment thread
walbourn marked this conversation as resolved.
bool IsExcludedFormat(DXGI_FORMAT fmt) noexcept
{
switch(static_cast<int>(fmt))
{
// 96bpp
case DXGI_FORMAT_R32G32B32_TYPELESS:
case DXGI_FORMAT_R32G32B32_FLOAT:
case DXGI_FORMAT_R32G32B32_UINT:
case DXGI_FORMAT_R32G32B32_SINT:

// Depth/stencil
case DXGI_FORMAT_R32G8X24_TYPELESS:
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
case DXGI_FORMAT_D32_FLOAT:
case DXGI_FORMAT_R24G8_TYPELESS:
case DXGI_FORMAT_D24_UNORM_S8_UINT:
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
case DXGI_FORMAT_D16_UNORM:
case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT:
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:

// Monochrome
case DXGI_FORMAT_R1_UNORM:

// Packed
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_YUY2:
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y216:

// Planar
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
case DXGI_FORMAT_P016:
case DXGI_FORMAT_420_OPAQUE:
case DXGI_FORMAT_NV11:
case WIN10_DXGI_FORMAT_P208:
case WIN10_DXGI_FORMAT_V208:
case WIN10_DXGI_FORMAT_V408:

// Palettized
case DXGI_FORMAT_AI44:
case DXGI_FORMAT_IA44:
case DXGI_FORMAT_P8:
case DXGI_FORMAT_A8P8:
return true;

default:
return false;
}
}

//-------------------------------------------------------------------------------------
// 2D z-order curve
//-------------------------------------------------------------------------------------
Expand Down Expand Up @@ -218,40 +276,55 @@ namespace
constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_64 = 0b0010010011000111;
constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_128 = 0b0010010011001111;

inline int GetSwizzleMask3D_X(size_t bytesPerPixel) noexcept
{
switch(bytesPerPixel)
{
case 1: return VOLUME_STANDARD_SWIZZLE_X_8;
case 2: return VOLUME_STANDARD_SWIZZLE_X_16;
case 8: return VOLUME_STANDARD_SWIZZLE_X_64;
case 16: return VOLUME_STANDARD_SWIZZLE_X_128;
default: return VOLUME_STANDARD_SWIZZLE_X_32;
}
}
// We rely on the fact that ScratchImage will put all slices in the same mip level
// in continous memory. We do not assume that is true of the source images.

inline int GetSwizzleMask3D_Y(size_t bytesPerPixel) noexcept
//---------------------------------------------------------------------------------
// row-major to z-order curve
//---------------------------------------------------------------------------------
template<int xBytesMask, int yBytesMask, int zBytesMask, size_t bytesPerPixel>
HRESULT LinearToStandardSwizzle3D(
_In_reads_(depth) const Image* srcImages,
const Image& destImage,
size_t depth,
bool isCompressed) noexcept
{
switch(bytesPerPixel)
{
case 1: return VOLUME_STANDARD_SWIZZLE_Y_8;
case 2: return VOLUME_STANDARD_SWIZZLE_Y_16;
case 8: return VOLUME_STANDARD_SWIZZLE_Y_64;
case 16: return VOLUME_STANDARD_SWIZZLE_Y_128;
default: return VOLUME_STANDARD_SWIZZLE_Y_32;
}
if (!srcImages || !depth)
return E_INVALIDARG;

uint8_t* dptr = destImage.pixels;
if (!dptr)
return E_POINTER;

if (destImage.rowPitch > UINT32_MAX)
return HRESULT_E_ARITHMETIC_OVERFLOW;

// TODO: linear to swizzle x,y,z
return E_NOTIMPL;
}

inline int GetSwizzleMask3D_Z(size_t bytesPerPixel) noexcept
//---------------------------------------------------------------------------------
// z-order curve to row-major
//---------------------------------------------------------------------------------
template<int xBytesMask, int yBytesMask, int zBytesMask, size_t bytesPerPixel>
HRESULT StandardSwizzleToLinear3D(
_In_reads_(depth) const Image* srcImages,
const Image& destImage,
size_t depth,
bool isCompressed) noexcept
{
switch(bytesPerPixel)
{
case 1: return VOLUME_STANDARD_SWIZZLE_Z_8;
case 2: return VOLUME_STANDARD_SWIZZLE_Z_16;
case 8: return VOLUME_STANDARD_SWIZZLE_Z_64;
case 16: return VOLUME_STANDARD_SWIZZLE_Z_128;
default: return VOLUME_STANDARD_SWIZZLE_Z_32;
}
if (!srcImages || !depth)
return E_INVALIDARG;

uint8_t* dptr = destImage.pixels;
if (!dptr)
return E_POINTER;

if (destImage.rowPitch > UINT32_MAX)
return HRESULT_E_ARITHMETIC_OVERFLOW;

// TODO: swizzle x,y,z to linear
return E_NOTIMPL;
}
}

Expand All @@ -273,7 +346,7 @@ HRESULT DirectX::StandardSwizzle(
return HRESULT_E_NOT_SUPPORTED;
}

if (IsPlanar(srcImage.format) || IsPalettized(srcImage.format) || (srcImage.format == DXGI_FORMAT_R1_UNORM))
if (IsExcludedFormat(srcImage.format))
return HRESULT_E_NOT_SUPPORTED;

if (!srcImage.pixels)
Expand Down Expand Up @@ -368,7 +441,7 @@ HRESULT DirectX::StandardSwizzle(
return HRESULT_E_NOT_SUPPORTED;
}

if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || (metadata.format == DXGI_FORMAT_R1_UNORM))
if (IsExcludedFormat(metadata.format))
return HRESULT_E_NOT_SUPPORTED;

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

if (metadata.dimension == TEX_DIMENSION_TEXTURE3D)
{
// TODO -
return E_NOTIMPL;
size_t index = 0;
size_t depth = metadata.depth;
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
const Image* srcBase = &srcImages[index];
const Image& destBase = dest[index];

for(size_t slice = 0; slice < depth; ++slice, ++index)
{
if (index >= nimages)
{
result.Release();
return E_UNEXPECTED;
}

const Image& src = srcImages[index];
if (!src.pixels)
{
result.Release();
return E_POINTER;
}

if (src.format != metadata.format)
{
result.Release();
return E_FAIL;
}

if ((src.width > MAX_TEXTURE_DIMENSION) || (src.height > MAX_TEXTURE_DIMENSION))
{
result.Release();
return E_FAIL;
}

const Image& dst = dest[index];
assert(dst.format == metadata.format);

if (src.width != dst.width || src.height != dst.height)
{
result.Release();
return E_FAIL;
}
}

if (toSwizzle)
{
switch(bytesPerPixel)
{
case 1:
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_8, VOLUME_STANDARD_SWIZZLE_Y_8, VOLUME_STANDARD_SWIZZLE_Z_8, 1>(srcBase, destBase, depth, false);
break;
case 2:
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_16, VOLUME_STANDARD_SWIZZLE_Y_16, VOLUME_STANDARD_SWIZZLE_Z_16, 2>(srcBase, destBase, depth, false);
break;
case 8:
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_64, VOLUME_STANDARD_SWIZZLE_Y_64, VOLUME_STANDARD_SWIZZLE_Z_64, 8>(srcBase, destBase, depth, isCompressed);
break;
case 16:
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_128, VOLUME_STANDARD_SWIZZLE_Y_128, VOLUME_STANDARD_SWIZZLE_Z_128, 16>(srcBase, destBase, depth, isCompressed);
break;
default:
hr = LinearToStandardSwizzle3D<VOLUME_STANDARD_SWIZZLE_X_32, VOLUME_STANDARD_SWIZZLE_Y_32, VOLUME_STANDARD_SWIZZLE_Z_32, 4>(srcBase, destBase, depth, false);
break;
}
}
else
{
switch(bytesPerPixel)
{
case 1:
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_8, VOLUME_STANDARD_SWIZZLE_Y_8, VOLUME_STANDARD_SWIZZLE_Z_8, 1>(srcBase, destBase, depth, false);
break;
case 2:
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_16, VOLUME_STANDARD_SWIZZLE_Y_16, VOLUME_STANDARD_SWIZZLE_Z_16, 2>(srcBase, destBase, depth, false);
break;
case 8:
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_64, VOLUME_STANDARD_SWIZZLE_Y_64, VOLUME_STANDARD_SWIZZLE_Z_64, 8>(srcBase, destBase, depth, isCompressed);
break;
case 16:
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_128, VOLUME_STANDARD_SWIZZLE_Y_128, VOLUME_STANDARD_SWIZZLE_Z_128, 16>(srcBase, destBase, depth, isCompressed);
break;
default:
hr = StandardSwizzleToLinear3D<VOLUME_STANDARD_SWIZZLE_X_32, VOLUME_STANDARD_SWIZZLE_Y_32, VOLUME_STANDARD_SWIZZLE_Z_32, 4>(srcBase, destBase, depth, false);
break;
}
}

if (FAILED(hr))
{
result.Release();
return hr;
}

if (depth > 1)
depth >>= 1;
}

return S_OK;
}
else
{
Expand Down Expand Up @@ -484,43 +653,6 @@ HRESULT DirectX::StandardSwizzle(


#if 0
// TODO: merging into main based on metadata
_Use_decl_annotations_
HRESULT DirectX::StandardSwizzle3D(
const Image* srcImages,
size_t depth,
const TexMetadata& metadata,
bool toSwizzle,
ScratchImage& result) noexcept
{
if (!srcImages || !depth || (metadata.dimension != TEX_DIMENSION_TEXTURE3D))
return E_INVALIDARG;

if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || (metadata.format == DXGI_FORMAT_R1_UNORM))
return HRESULT_E_NOT_SUPPORTED;

HRESULT hr = result.Initialize(metadata);
if (FAILED(hr))
return hr;

if ((depth * metadata.mipLevels) != result.GetImageCount())
{
result.Release();
return E_FAIL;
}

const bool isCompressed = IsCompressed(metadata.format);
const size_t bytesPerPixel = isCompressed ? BytesPerBlock(metadata.format) : (BitsPerPixel(metadata.format) / 8);
if (!bytesPerPixel)
{
result.Release();
return E_FAIL;
}

const int xBytesMask = GetSwizzleMask3D_X(metadata.format);
const int yBytesMask = GetSwizzleMask3D_Y(metadata.format);
const int zBytesMask = GetSwizzleMask3D_Z(metadata.format);

if (toSwizzle)
{
// row-major to z-order curve
Expand Down Expand Up @@ -584,7 +716,4 @@ HRESULT DirectX::StandardSwizzle3D(
}
}
}

return S_OK;
}
#endif