From 2ba02895a8a4db4ac42f65cc1f4a3d35c7fc88fb Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Tue, 17 Sep 2024 13:41:45 -0700 Subject: [PATCH 01/19] [Draft] - needs to be tested. where to get dx12 boilerplate? test just that texute still looks correct, or also test performance improves when roteated? - maybe merge functions? would then pass a boolean/enum to determine rowToSwizzle versus swizzleToRow Added functions that converts pixel order from row major to standard swizzle and from standard swizzle to row major. Functions for both 1 Image, and an array of Images. Folwoing standard DirectXTex pattern: Uses Image and TexMetadata as input. Outputs/initializes a ScratchImage. --- DirectXTex/DirectXTex.h | 4 + DirectXTex/DirectXTexImage.cpp | 150 +++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 901fc4cc..6c210172 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -416,7 +416,11 @@ namespace DirectX HRESULT __cdecl InitializeCube(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t nCubes, _In_ size_t mipLevels, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; HRESULT __cdecl InitializeFromImage(_In_ const Image& srcImage, _In_ bool allow1D = false, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; + HRESULT __cdecl InitializeSwizzleFromImage(const Image& srcImage, CP_FLAGS flags) noexcept; + HRESULT __cdecl InitializeImageFromSwizzle(const Image& srcImage, CP_FLAGS flags) noexcept; HRESULT __cdecl InitializeArrayFromImages(_In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ bool allow1D = false, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; + HRESULT __cdecl InitializeSwizzlesFromImages(const Image* srcImage, size_t nImages, CP_FLAGS flags) noexcept; + HRESULT __cdecl InitializeImagesFromSwizzles(const Image* srcImage, size_t nImages, CP_FLAGS flags) noexcept; HRESULT __cdecl InitializeCubeFromImages(_In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; HRESULT __cdecl Initialize3DFromImages(_In_reads_(depth) const Image* images, _In_ size_t depth, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; diff --git a/DirectXTex/DirectXTexImage.cpp b/DirectXTex/DirectXTexImage.cpp index d2c7d408..a6ac8dc9 100644 --- a/DirectXTex/DirectXTexImage.cpp +++ b/DirectXTex/DirectXTexImage.cpp @@ -567,6 +567,78 @@ HRESULT ScratchImage::InitializeFromImage(const Image& srcImage, bool allow1D, C return S_OK; } +_Use_decl_annotations_ +HRESULT ScratchImage::InitializeSwizzleFromImage(const Image& srcImage, CP_FLAGS flags) noexcept +{ + HRESULT hr = Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1, flags); + + if (FAILED(hr)) + return hr; + + uint8_t* sptr = srcImage.pixels; + if (!sptr) + return E_POINTER; + + uint8_t* dptr = m_image[0].pixels; + if (!dptr) + return E_POINTER; + + size_t bytesPerPixel = BitsPerPixel(srcImage.format) / 8; + + uint32_t xBytesMask = 0b1010101010101010; + uint32_t yBytesMask = 0b0101010101010101; + + for (size_t y = 0; y < srcImage.height; y++) + { + for (size_t x = 0; x < srcImage.width; x++) + { + uint32_t swizzleIndex = _pdep_u32(x, xBytesMask) + _pdep_u32(y, yBytesMask); + + uint8_t* sourcePixelPointer = sptr + y * srcImage.rowPitch + x * bytesPerPixel; + uint8_t* destPixelPointer = dptr + swizzleIndex * bytesPerPixel; + memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + } + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::InitializeImageFromSwizzle(const Image& srcImage, CP_FLAGS flags) noexcept +{ + HRESULT hr = Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1, flags); + + if (FAILED(hr)) + return hr; + + uint8_t* sptr = srcImage.pixels; + if (!sptr) + return E_POINTER; + + uint8_t* dptr = m_image[0].pixels; + if (!dptr) + return E_POINTER; + + size_t bytesPerPixel = BitsPerPixel(srcImage.format) / 8; + + uint32_t xBytesMask = 0b1010101010101010; + uint32_t yBytesMask = 0b0101010101010101; + + for (size_t y = 0; y < srcImage.height; y++) + { + for (size_t x = 0; x < srcImage.width; x++) + { + uint32_t swizzleIndex = _pdep_u32(x, xBytesMask) + _pdep_u32(y, yBytesMask); + + uint8_t* sourcePixelPointer = sptr + swizzleIndex * bytesPerPixel; + uint8_t* destPixelPointer = dptr + y * m_image[0].rowPitch + x * bytesPerPixel; + memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + } + } + + return S_OK; +} + _Use_decl_annotations_ HRESULT ScratchImage::InitializeArrayFromImages(const Image* images, size_t nImages, bool allow1D, CP_FLAGS flags) noexcept { @@ -627,6 +699,84 @@ HRESULT ScratchImage::InitializeArrayFromImages(const Image* images, size_t nIma return S_OK; } +_Use_decl_annotations_ +HRESULT ScratchImage::InitializeSwizzlesFromImages(const Image* srcImage, size_t nImages, CP_FLAGS flags) noexcept +{ + HRESULT hr = Initialize2D(srcImage[0].format, srcImage[0].width, srcImage[0].height, nImages, 1, flags); + + if (FAILED(hr)) + return hr; + + for (size_t imageIndex = 0; imageIndex < nImages; imageIndex++) + { + uint8_t* sptr = srcImage[imageIndex].pixels; + if (!sptr) + return E_POINTER; + + uint8_t* dptr = m_image[imageIndex].pixels; + if (!dptr) + return E_POINTER; + + size_t bytesPerPixel = BitsPerPixel(srcImage[imageIndex].format) / 8; + + uint32_t xBytesMask = 0b1010101010101010; + uint32_t yBytesMask = 0b0101010101010101; + + for (size_t y = 0; y < srcImage[imageIndex].height; y++) + { + for (size_t x = 0; x < srcImage[imageIndex].width; x++) + { + uint32_t swizzleIndex = _pdep_u32(x, xBytesMask) + _pdep_u32(y, yBytesMask); + + uint8_t* sourcePixelPointer = sptr + y * srcImage[imageIndex].rowPitch + x * bytesPerPixel; + uint8_t* destPixelPointer = dptr + swizzleIndex * bytesPerPixel; + memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + } + } + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::InitializeImagesFromSwizzles(const Image* srcImage, size_t nImages, CP_FLAGS flags) noexcept +{ + HRESULT hr = Initialize2D(srcImage[0].format, srcImage[0].width, srcImage[0].height, nImages, 1, flags); + + if (FAILED(hr)) + return hr; + + for (size_t imageIndex = 0; imageIndex < nImages; imageIndex++) + { + uint8_t* sptr = srcImage[imageIndex].pixels; + if (!sptr) + return E_POINTER; + + uint8_t* dptr = m_image[imageIndex].pixels; + if (!dptr) + return E_POINTER; + + size_t bytesPerPixel = BitsPerPixel(srcImage[imageIndex].format) / 8; + + uint32_t xBytesMask = 0b1010101010101010; + uint32_t yBytesMask = 0b0101010101010101; + + for (size_t y = 0; y < srcImage[imageIndex].height; y++) + { + for (size_t x = 0; x < srcImage[imageIndex].width; x++) + { + uint32_t swizzleIndex = _pdep_u32(x, xBytesMask) + _pdep_u32(y, yBytesMask); + + uint8_t* sourcePixelPointer = sptr + swizzleIndex * bytesPerPixel; + uint8_t* destPixelPointer = dptr + y * m_image[imageIndex].rowPitch + x * bytesPerPixel; + memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + } + } + } + + return S_OK; +} + _Use_decl_annotations_ HRESULT ScratchImage::InitializeCubeFromImages(const Image* images, size_t nImages, CP_FLAGS flags) noexcept { From 0a8c5bf4aefce0d4b88a6abccc719d466ea66958 Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Wed, 18 Sep 2024 14:38:36 -0700 Subject: [PATCH 02/19] Moved functionst to new file DirectTexSwizzle Added new file to .vcxproj, other.vcxproj, and Cmake Merged to/from functions togeather memcpy src is const added non-AVX2 deposit_bits --- CMakeLists.txt | 1 + DirectXTex/DirectXTex.h | 7 +- DirectXTex/DirectXTexImage.cpp | 188 ++++-------------- DirectXTex/DirectXTexSwizzle.cpp | 142 +++++++++++++ DirectXTex/DirectXTex_Desktop_2022.vcxproj | 1 + .../DirectXTex_Desktop_2022.vcxproj.filters | 3 + 6 files changed, 188 insertions(+), 154 deletions(-) create mode 100644 DirectXTex/DirectXTexSwizzle.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8999965e..d1ba263c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,7 @@ set(LIBRARY_SOURCES DirectXTex/DirectXTexMipmaps.cpp DirectXTex/DirectXTexMisc.cpp DirectXTex/DirectXTexNormalMaps.cpp + DirectXTex/DirectxTexSwizzle.cpp DirectXTex/DirectXTexPMAlpha.cpp DirectXTex/DirectXTexResize.cpp DirectXTex/DirectXTexTGA.cpp diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 6c210172..143a6662 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -416,11 +416,7 @@ namespace DirectX HRESULT __cdecl InitializeCube(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t nCubes, _In_ size_t mipLevels, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; HRESULT __cdecl InitializeFromImage(_In_ const Image& srcImage, _In_ bool allow1D = false, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; - HRESULT __cdecl InitializeSwizzleFromImage(const Image& srcImage, CP_FLAGS flags) noexcept; - HRESULT __cdecl InitializeImageFromSwizzle(const Image& srcImage, CP_FLAGS flags) noexcept; HRESULT __cdecl InitializeArrayFromImages(_In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ bool allow1D = false, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; - HRESULT __cdecl InitializeSwizzlesFromImages(const Image* srcImage, size_t nImages, CP_FLAGS flags) noexcept; - HRESULT __cdecl InitializeImagesFromSwizzles(const Image* srcImage, size_t nImages, CP_FLAGS flags) noexcept; HRESULT __cdecl InitializeCubeFromImages(_In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; HRESULT __cdecl Initialize3DFromImages(_In_reads_(depth) const Image* images, _In_ size_t depth, _In_ CP_FLAGS flags = CP_FLAGS_NONE) noexcept; @@ -734,6 +730,9 @@ namespace DirectX _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ size_t item, _In_ float alphaReference, _Inout_ ScratchImage& mipChain) noexcept; + HRESULT __cdecl StandardSwizzle(_In_ const Image& srcImage, bool toSwizzle, _Out_ ScratchImage& image) noexcept; + + HRESULT __cdecl StandardSwizzle(_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, bool toSwizzle, _Out_ ScratchImage& result) noexcept; enum TEX_PMALPHA_FLAGS : unsigned long { diff --git a/DirectXTex/DirectXTexImage.cpp b/DirectXTex/DirectXTexImage.cpp index a6ac8dc9..10def60d 100644 --- a/DirectXTex/DirectXTexImage.cpp +++ b/DirectXTex/DirectXTexImage.cpp @@ -27,6 +27,44 @@ namespace } #endif +namespace +{ +#ifdef __AVX2__ +#define deposit_bits(v,m) _pdep_u32(v,m) +#define extract_bits(v,m) _pext_u32(v,m) +#else + // N3864 - A constexpr bitwise operations library for C++ + // https://github.com/fmatthew5876/stdcxx-bitops + uint32_t deposit_bits(uint32_t val, uint32_t mask) + { + uint32_t res = 0; + for (uint32_t bb = 1; mask != 0; bb += bb) + { + if (val & bb) + { + res |= mask & (-mask); + } + mask &= (mask - 1); + } + return res; + } + + uint32_t extract_bits(uint32_t val, uint32_t mask) + { + uint32_t res = 0; + for (uint32_t bb = 1; mask !=0; bb += bb) + { + if (val & mask & -mask) + { + res |= bb; + } + mask &= (mask - 1); + } + return res; + } +#endif +} + //------------------------------------------------------------------------------------- // Determines number of image array entries and pixel size //------------------------------------------------------------------------------------- @@ -567,78 +605,6 @@ HRESULT ScratchImage::InitializeFromImage(const Image& srcImage, bool allow1D, C return S_OK; } -_Use_decl_annotations_ -HRESULT ScratchImage::InitializeSwizzleFromImage(const Image& srcImage, CP_FLAGS flags) noexcept -{ - HRESULT hr = Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1, flags); - - if (FAILED(hr)) - return hr; - - uint8_t* sptr = srcImage.pixels; - if (!sptr) - return E_POINTER; - - uint8_t* dptr = m_image[0].pixels; - if (!dptr) - return E_POINTER; - - size_t bytesPerPixel = BitsPerPixel(srcImage.format) / 8; - - uint32_t xBytesMask = 0b1010101010101010; - uint32_t yBytesMask = 0b0101010101010101; - - for (size_t y = 0; y < srcImage.height; y++) - { - for (size_t x = 0; x < srcImage.width; x++) - { - uint32_t swizzleIndex = _pdep_u32(x, xBytesMask) + _pdep_u32(y, yBytesMask); - - uint8_t* sourcePixelPointer = sptr + y * srcImage.rowPitch + x * bytesPerPixel; - uint8_t* destPixelPointer = dptr + swizzleIndex * bytesPerPixel; - memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); - } - } - - return S_OK; -} - -_Use_decl_annotations_ -HRESULT ScratchImage::InitializeImageFromSwizzle(const Image& srcImage, CP_FLAGS flags) noexcept -{ - HRESULT hr = Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1, flags); - - if (FAILED(hr)) - return hr; - - uint8_t* sptr = srcImage.pixels; - if (!sptr) - return E_POINTER; - - uint8_t* dptr = m_image[0].pixels; - if (!dptr) - return E_POINTER; - - size_t bytesPerPixel = BitsPerPixel(srcImage.format) / 8; - - uint32_t xBytesMask = 0b1010101010101010; - uint32_t yBytesMask = 0b0101010101010101; - - for (size_t y = 0; y < srcImage.height; y++) - { - for (size_t x = 0; x < srcImage.width; x++) - { - uint32_t swizzleIndex = _pdep_u32(x, xBytesMask) + _pdep_u32(y, yBytesMask); - - uint8_t* sourcePixelPointer = sptr + swizzleIndex * bytesPerPixel; - uint8_t* destPixelPointer = dptr + y * m_image[0].rowPitch + x * bytesPerPixel; - memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); - } - } - - return S_OK; -} - _Use_decl_annotations_ HRESULT ScratchImage::InitializeArrayFromImages(const Image* images, size_t nImages, bool allow1D, CP_FLAGS flags) noexcept { @@ -699,84 +665,6 @@ HRESULT ScratchImage::InitializeArrayFromImages(const Image* images, size_t nIma return S_OK; } -_Use_decl_annotations_ -HRESULT ScratchImage::InitializeSwizzlesFromImages(const Image* srcImage, size_t nImages, CP_FLAGS flags) noexcept -{ - HRESULT hr = Initialize2D(srcImage[0].format, srcImage[0].width, srcImage[0].height, nImages, 1, flags); - - if (FAILED(hr)) - return hr; - - for (size_t imageIndex = 0; imageIndex < nImages; imageIndex++) - { - uint8_t* sptr = srcImage[imageIndex].pixels; - if (!sptr) - return E_POINTER; - - uint8_t* dptr = m_image[imageIndex].pixels; - if (!dptr) - return E_POINTER; - - size_t bytesPerPixel = BitsPerPixel(srcImage[imageIndex].format) / 8; - - uint32_t xBytesMask = 0b1010101010101010; - uint32_t yBytesMask = 0b0101010101010101; - - for (size_t y = 0; y < srcImage[imageIndex].height; y++) - { - for (size_t x = 0; x < srcImage[imageIndex].width; x++) - { - uint32_t swizzleIndex = _pdep_u32(x, xBytesMask) + _pdep_u32(y, yBytesMask); - - uint8_t* sourcePixelPointer = sptr + y * srcImage[imageIndex].rowPitch + x * bytesPerPixel; - uint8_t* destPixelPointer = dptr + swizzleIndex * bytesPerPixel; - memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); - } - } - } - - return S_OK; -} - -_Use_decl_annotations_ -HRESULT ScratchImage::InitializeImagesFromSwizzles(const Image* srcImage, size_t nImages, CP_FLAGS flags) noexcept -{ - HRESULT hr = Initialize2D(srcImage[0].format, srcImage[0].width, srcImage[0].height, nImages, 1, flags); - - if (FAILED(hr)) - return hr; - - for (size_t imageIndex = 0; imageIndex < nImages; imageIndex++) - { - uint8_t* sptr = srcImage[imageIndex].pixels; - if (!sptr) - return E_POINTER; - - uint8_t* dptr = m_image[imageIndex].pixels; - if (!dptr) - return E_POINTER; - - size_t bytesPerPixel = BitsPerPixel(srcImage[imageIndex].format) / 8; - - uint32_t xBytesMask = 0b1010101010101010; - uint32_t yBytesMask = 0b0101010101010101; - - for (size_t y = 0; y < srcImage[imageIndex].height; y++) - { - for (size_t x = 0; x < srcImage[imageIndex].width; x++) - { - uint32_t swizzleIndex = _pdep_u32(x, xBytesMask) + _pdep_u32(y, yBytesMask); - - uint8_t* sourcePixelPointer = sptr + swizzleIndex * bytesPerPixel; - uint8_t* destPixelPointer = dptr + y * m_image[imageIndex].rowPitch + x * bytesPerPixel; - memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); - } - } - } - - return S_OK; -} - _Use_decl_annotations_ HRESULT ScratchImage::InitializeCubeFromImages(const Image* images, size_t nImages, CP_FLAGS flags) noexcept { diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp new file mode 100644 index 00000000..8d4d4b23 --- /dev/null +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -0,0 +1,142 @@ +//------------------------------------------------------------------------------------- +// DirectXTexImage.cpp +// +// DirectX Texture Library - Image container +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "DirectXTex.h" +#include "DirectXTexP.h" + +using namespace DirectX; +using namespace DirectX::Internal; + +namespace +{ +#ifdef __AVX2__ +#define deposit_bits(v,m) _pdep_u32(v,m) +#else + // N3864 - A constexpr bitwise operations library for C++ + // https://github.com/fmatthew5876/stdcxx-bitops + uint32_t deposit_bits(uint32_t val, uint32_t mask) + { + uint32_t res = 0; + for (uint32_t bb = 1; mask != 0; bb += bb) + { + if (val & bb) + { + res |= mask & (-mask); + } + mask &= (mask - 1); + } + return res; + } +#endif +} + + +_Use_decl_annotations_ +HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchImage& image) noexcept +{ + if (!IsValid(srcImage.format)) + return E_INVALIDARG; + + if (IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format)) + return HRESULT_E_NOT_SUPPORTED; + + HRESULT hr = image.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const uint8_t* sptr = srcImage.pixels; + if (!sptr) + return E_POINTER; + + uint8_t* dptr = image.GetImages()[0].pixels; + if (!dptr) + return E_POINTER; + + size_t bytesPerPixel = BitsPerPixel(srcImage.format) / 8; + + uint32_t xBytesMask = 0b1010101010101010; + uint32_t yBytesMask = 0b0101010101010101; + + for (size_t y = 0; y < srcImage.height; y++) + { + for (size_t x = 0; x < srcImage.width; x++) + { + uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); + size_t swizzleOffset = swizzleIndex * bytesPerPixel; + + size_t rowMajorOffset = y * srcImage.rowPitch + x * bytesPerPixel; + + size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; + size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; + + const uint8_t* sourcePixelPointer = sptr + sourceOffset; + uint8_t* destPixelPointer = dptr + destOffset; + memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + } + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const TexMetadata& metadata, bool toSwizzle, ScratchImage& result) noexcept +{ + HRESULT hr = result.Initialize2D(srcImages[0].format, srcImages[0].width, srcImages[0].height, nimages, 1); + + if (!srcImages || !nimages || !IsValid(metadata.format) || nimages > metadata.mipLevels || !result.GetImages()) + return E_INVALIDARG; + + if (metadata.IsVolumemap() + || IsCompressed(metadata.format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + return HRESULT_E_NOT_SUPPORTED; + + if (srcImages[0].format != metadata.format || srcImages[0].width != metadata.width || srcImages[0].height != metadata.height) + { + // Base image must be the same format, width, and height + return E_FAIL; + } + + for (size_t imageIndex = 0; imageIndex < nimages; imageIndex++) + { + const uint8_t* sptr = srcImages[imageIndex].pixels; + if (!sptr) + return E_POINTER; + + uint8_t* dptr = result.GetImages()[imageIndex].pixels; + if (!dptr) + return E_POINTER; + + size_t bytesPerPixel = BitsPerPixel(srcImages[imageIndex].format) / 8; + + uint32_t xBytesMask = 0b1010101010101010; + uint32_t yBytesMask = 0b0101010101010101; + + for (size_t y = 0; y < srcImages[imageIndex].height; y++) + { + for (size_t x = 0; x < srcImages[imageIndex].width; x++) + { + uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); + size_t swizzleOffset = swizzleIndex * bytesPerPixel; + + size_t rowMajorOffset = y * srcImages[0].rowPitch + x * bytesPerPixel; + + size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; + size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; + + const uint8_t* sourcePixelPointer = sptr + sourceOffset; + uint8_t* destPixelPointer = dptr + destOffset; + memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + } + } + } + + return S_OK; +} diff --git a/DirectXTex/DirectXTex_Desktop_2022.vcxproj b/DirectXTex/DirectXTex_Desktop_2022.vcxproj index d79c3dc3..dacad8e3 100644 --- a/DirectXTex/DirectXTex_Desktop_2022.vcxproj +++ b/DirectXTex/DirectXTex_Desktop_2022.vcxproj @@ -318,6 +318,7 @@ + Create diff --git a/DirectXTex/DirectXTex_Desktop_2022.vcxproj.filters b/DirectXTex/DirectXTex_Desktop_2022.vcxproj.filters index 455eddaf..dd897453 100644 --- a/DirectXTex/DirectXTex_Desktop_2022.vcxproj.filters +++ b/DirectXTex/DirectXTex_Desktop_2022.vcxproj.filters @@ -95,6 +95,9 @@ Source Files + + Source Files + From e29108a1c7b6ed2dba7a7739f85f4d1053df2477 Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Wed, 18 Sep 2024 14:39:41 -0700 Subject: [PATCH 03/19] cleanup move --- DirectXTex/DirectXTexImage.cpp | 38 ---------------------------------- 1 file changed, 38 deletions(-) diff --git a/DirectXTex/DirectXTexImage.cpp b/DirectXTex/DirectXTexImage.cpp index 10def60d..d2c7d408 100644 --- a/DirectXTex/DirectXTexImage.cpp +++ b/DirectXTex/DirectXTexImage.cpp @@ -27,44 +27,6 @@ namespace } #endif -namespace -{ -#ifdef __AVX2__ -#define deposit_bits(v,m) _pdep_u32(v,m) -#define extract_bits(v,m) _pext_u32(v,m) -#else - // N3864 - A constexpr bitwise operations library for C++ - // https://github.com/fmatthew5876/stdcxx-bitops - uint32_t deposit_bits(uint32_t val, uint32_t mask) - { - uint32_t res = 0; - for (uint32_t bb = 1; mask != 0; bb += bb) - { - if (val & bb) - { - res |= mask & (-mask); - } - mask &= (mask - 1); - } - return res; - } - - uint32_t extract_bits(uint32_t val, uint32_t mask) - { - uint32_t res = 0; - for (uint32_t bb = 1; mask !=0; bb += bb) - { - if (val & mask & -mask) - { - res |= bb; - } - mask &= (mask - 1); - } - return res; - } -#endif -} - //------------------------------------------------------------------------------------- // Determines number of image array entries and pixel size //------------------------------------------------------------------------------------- From 406787dde081de40dc098b5e50363a8b5ee9d252 Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Wed, 18 Sep 2024 16:27:51 -0700 Subject: [PATCH 04/19] added 3D --- DirectXTex/DirectXTex.h | 6 ++-- DirectXTex/DirectXTexSwizzle.cpp | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 143a6662..a2bc4074 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -730,9 +730,9 @@ namespace DirectX _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ size_t item, _In_ float alphaReference, _Inout_ ScratchImage& mipChain) noexcept; - HRESULT __cdecl StandardSwizzle(_In_ const Image& srcImage, bool toSwizzle, _Out_ ScratchImage& image) noexcept; - - HRESULT __cdecl StandardSwizzle(_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, bool toSwizzle, _Out_ ScratchImage& result) noexcept; + HRESULT __cdecl StandardSwizzle(_In_ const Image& srcImage, _In_ bool toSwizzle, _Out_ ScratchImage& image) noexcept; + HRESULT __cdecl StandardSwizzle(_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ bool toSwizzle, _Out_ ScratchImage& result) noexcept; + HRESULT __cdecl StandardSwizzle3D(_In_reads_(depth) const Image* srcImages, _In_ size_t depth, _In_ const TexMetadata& metadata, _In_ bool toSwizzle, _Out_ ScratchImage& result) noexcept; enum TEX_PMALPHA_FLAGS : unsigned long { diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index 8d4d4b23..d0af204c 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -140,3 +140,59 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T return S_OK; } + +_Use_decl_annotations_ +HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const TexMetadata& metadata, bool toSwizzle, ScratchImage& result) noexcept +{ + HRESULT hr = result.Initialize3D(srcImages[0].format, srcImages[0].width, srcImages[0].height, depth, 1); + + if (!srcImages || !depth || !IsValid(metadata.format) || depth > metadata.depth || !result.GetImages()) + return E_INVALIDARG; + + if (metadata.IsVolumemap() + || IsCompressed(metadata.format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + return HRESULT_E_NOT_SUPPORTED; + + if (srcImages[0].format != metadata.format || srcImages[0].width != metadata.width || srcImages[0].height != metadata.height) + { + // Base image must be the same format, width, and height + return E_FAIL; + } + + for (size_t slice = 0; slice < depth; slice++) + { + const uint8_t* sptr = srcImages[slice].pixels; + if (!sptr) + return E_POINTER; + + uint8_t* dptr = result.GetImages()[slice].pixels; + if (!dptr) + return E_POINTER; + + size_t bytesPerPixel = BitsPerPixel(srcImages[slice].format) / 8; + + uint32_t xBytesMask = 0b1001001001001001; + uint32_t yBytesMask = 0b0100100100100100; + uint32_t zBytesMask = 0b0010010010010010; + + for (size_t y = 0; y < srcImages[slice].height; y++) + { + for (size_t x = 0; x < srcImages[slice].width; x++) + { + uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask) + deposit_bits(slice, zBytesMask); + size_t swizzleOffset = swizzleIndex * bytesPerPixel; + + size_t rowMajorOffset = y * srcImages[0].rowPitch + x * bytesPerPixel; + + size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; + size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; + + const uint8_t* sourcePixelPointer = sptr + sourceOffset; + uint8_t* destPixelPointer = dptr + destOffset; + memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + } + } + } + + return S_OK; +} From 061f06c539bbb5ce43fcf6263fdfed5d106f0ca5 Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Thu, 19 Sep 2024 13:59:29 -0700 Subject: [PATCH 05/19] Almost handel Block Compression. TODO what flags/threshold to use to re-Compress? --- DirectXTex/DirectXTexSwizzle.cpp | 142 ++++++++++++++++++++++++++----- 1 file changed, 122 insertions(+), 20 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index d0af204c..5e441375 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -40,7 +40,7 @@ namespace _Use_decl_annotations_ -HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchImage& image) noexcept +HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchImage& result) noexcept { if (!IsValid(srcImage.format)) return E_INVALIDARG; @@ -48,31 +48,55 @@ HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchI if (IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format)) return HRESULT_E_NOT_SUPPORTED; - HRESULT hr = image.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); + HRESULT hr = result.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); if (FAILED(hr)) return hr; - const uint8_t* sptr = srcImage.pixels; + Image uncompressedSource; + Image uncompressedDestination; + ScratchImage wide; + ScratchImage dest; + if (IsCompressed(srcImage.format)) + { + wide = ScratchImage(); + HRESULT de = Decompress(srcImage, srcImage.format, wide); + if (FAILED(de)) + return de; + uncompressedSource = wide.GetImages()[0]; + + dest = ScratchImage(); + HRESULT dcom = dest.Initialize2D(uncompressedSource.format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(dcom)) + return dcom; + uncompressedDestination = dest.GetImages()[0]; + } + else + { + uncompressedSource = srcImage; + uncompressedDestination = result.GetImages()[0]; + } + + const uint8_t* sptr = uncompressedSource.pixels; if (!sptr) return E_POINTER; - uint8_t* dptr = image.GetImages()[0].pixels; + uint8_t* dptr = uncompressedDestination.pixels; if (!dptr) return E_POINTER; - size_t bytesPerPixel = BitsPerPixel(srcImage.format) / 8; + size_t bytesPerPixel = BitsPerPixel(uncompressedSource.format) / 8; uint32_t xBytesMask = 0b1010101010101010; uint32_t yBytesMask = 0b0101010101010101; - for (size_t y = 0; y < srcImage.height; y++) + for (size_t y = 0; y < uncompressedSource.height; y++) { - for (size_t x = 0; x < srcImage.width; x++) + for (size_t x = 0; x < uncompressedSource.width; x++) { uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); size_t swizzleOffset = swizzleIndex * bytesPerPixel; - size_t rowMajorOffset = y * srcImage.rowPitch + x * bytesPerPixel; + size_t rowMajorOffset = y * uncompressedSource.rowPitch + x * bytesPerPixel; size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; @@ -83,6 +107,16 @@ HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchI } } + if (IsCompressed(srcImage.format)) + { + TEX_COMPRESS_FLAGS flags = TEX_COMPRESS_DEFAULT; // !!TODO!! actual value + float threshold = -42; // !!TODO!! actual value + + Compress(uncompressedDestination, srcImage.format, flags, threshold, result); + wide.Release(); + dest.Release(); + } + return S_OK; } @@ -104,29 +138,53 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T return E_FAIL; } + const Image* uncompressedSource; + const Image* uncompressedDestination; + ScratchImage wide; + ScratchImage dest; + if (IsCompressed(metadata.format)) + { + wide = ScratchImage(); + HRESULT de = Decompress(srcImages, nimages, metadata, metadata.format, wide); + if (FAILED(de)) + return de; + uncompressedSource = wide.GetImages(); + + dest = ScratchImage(); + HRESULT dcom = dest.Initialize2D(uncompressedSource[0].format, srcImages[0].width, srcImages[0].height, nimages, 1); + if (FAILED(dcom)) + return dcom; + uncompressedDestination = dest.GetImages(); + } + else + { + uncompressedSource = srcImages; + uncompressedDestination = result.GetImages(); + } + for (size_t imageIndex = 0; imageIndex < nimages; imageIndex++) { - const uint8_t* sptr = srcImages[imageIndex].pixels; + const uint8_t* sptr = uncompressedSource[imageIndex].pixels; if (!sptr) return E_POINTER; - uint8_t* dptr = result.GetImages()[imageIndex].pixels; + uint8_t* dptr = uncompressedDestination[imageIndex].pixels; if (!dptr) return E_POINTER; - size_t bytesPerPixel = BitsPerPixel(srcImages[imageIndex].format) / 8; + size_t bytesPerPixel = BitsPerPixel(uncompressedSource[imageIndex].format) / 8; uint32_t xBytesMask = 0b1010101010101010; uint32_t yBytesMask = 0b0101010101010101; - for (size_t y = 0; y < srcImages[imageIndex].height; y++) + for (size_t y = 0; y < uncompressedSource[imageIndex].height; y++) { - for (size_t x = 0; x < srcImages[imageIndex].width; x++) + for (size_t x = 0; x < uncompressedSource[imageIndex].width; x++) { uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); size_t swizzleOffset = swizzleIndex * bytesPerPixel; - size_t rowMajorOffset = y * srcImages[0].rowPitch + x * bytesPerPixel; + size_t rowMajorOffset = y * uncompressedSource[0].rowPitch + x * bytesPerPixel; size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; @@ -138,6 +196,16 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T } } + if (IsCompressed(metadata.format)) + { + TEX_COMPRESS_FLAGS flags = TEX_COMPRESS_DEFAULT; // !!TODO!! actual value + float threshold = -42; // !!TODO!! actual value + + Compress(uncompressedDestination, nimages, metadata, metadata.format, flags, threshold, result); + wide.Release(); + dest.Release(); + } + return S_OK; } @@ -159,30 +227,54 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T return E_FAIL; } + const Image* uncompressedSource; + const Image* uncompressedDestination; + ScratchImage wide; + ScratchImage dest; + if (IsCompressed(metadata.format)) + { + wide = ScratchImage(); + HRESULT de = Decompress(srcImages, depth, metadata, metadata.format, wide); + if (FAILED(de)) + return de; + uncompressedSource = wide.GetImages(); + + dest = ScratchImage(); + HRESULT dcom = dest.Initialize3D(uncompressedSource[0].format, srcImages[0].width, srcImages[0].height, depth, 1); + if (FAILED(dcom)) + return dcom; + uncompressedDestination = dest.GetImages(); + } + else + { + uncompressedSource = srcImages; + uncompressedDestination = result.GetImages(); + } + for (size_t slice = 0; slice < depth; slice++) { - const uint8_t* sptr = srcImages[slice].pixels; + const uint8_t* sptr = uncompressedSource[slice].pixels; if (!sptr) return E_POINTER; - uint8_t* dptr = result.GetImages()[slice].pixels; + uint8_t* dptr = uncompressedDestination[slice].pixels; if (!dptr) return E_POINTER; - size_t bytesPerPixel = BitsPerPixel(srcImages[slice].format) / 8; + size_t bytesPerPixel = BitsPerPixel(uncompressedSource[slice].format) / 8; uint32_t xBytesMask = 0b1001001001001001; uint32_t yBytesMask = 0b0100100100100100; uint32_t zBytesMask = 0b0010010010010010; - for (size_t y = 0; y < srcImages[slice].height; y++) + for (size_t y = 0; y < uncompressedSource[slice].height; y++) { - for (size_t x = 0; x < srcImages[slice].width; x++) + for (size_t x = 0; x < uncompressedSource[slice].width; x++) { uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask) + deposit_bits(slice, zBytesMask); size_t swizzleOffset = swizzleIndex * bytesPerPixel; - size_t rowMajorOffset = y * srcImages[0].rowPitch + x * bytesPerPixel; + size_t rowMajorOffset = y * uncompressedSource[0].rowPitch + x * bytesPerPixel; size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; @@ -194,5 +286,15 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T } } + if (IsCompressed(metadata.format)) + { + TEX_COMPRESS_FLAGS flags = TEX_COMPRESS_DEFAULT; // !!TODO!! actual value + float threshold = -42; // !!TODO!! actual value + + Compress(uncompressedDestination, depth, metadata, metadata.format, flags, threshold, result); + wide.Release(); + dest.Release(); + } + return S_OK; } From f3b95e0ceb2dc517f52d575d4a08f439b1ba47df Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Thu, 19 Sep 2024 15:01:34 -0700 Subject: [PATCH 06/19] Fix 3d swizzle idexing into multiple images --- DirectXTex/DirectXTexSwizzle.cpp | 41 +++++++++++++++++--------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index 5e441375..d4161390 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -251,33 +251,36 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T uncompressedDestination = result.GetImages(); } - for (size_t slice = 0; slice < depth; slice++) - { - const uint8_t* sptr = uncompressedSource[slice].pixels; - if (!sptr) - return E_POINTER; - - uint8_t* dptr = uncompressedDestination[slice].pixels; - if (!dptr) - return E_POINTER; + size_t bytesPerPixel = BitsPerPixel(uncompressedSource[0].format) / 8; + uint32_t xBytesMask = 0b1001001001001001; + uint32_t yBytesMask = 0b0100100100100100; + uint32_t zBytesMask = 0b0010010010010010; - size_t bytesPerPixel = BitsPerPixel(uncompressedSource[slice].format) / 8; - - uint32_t xBytesMask = 0b1001001001001001; - uint32_t yBytesMask = 0b0100100100100100; - uint32_t zBytesMask = 0b0010010010010010; - - for (size_t y = 0; y < uncompressedSource[slice].height; y++) + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < metadata.height; y++) { - for (size_t x = 0; x < uncompressedSource[slice].width; x++) + for (size_t x = 0; x < metadata.width; x++) { - uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask) + deposit_bits(slice, zBytesMask); - size_t swizzleOffset = swizzleIndex * bytesPerPixel; + uint32_t swizzle3Dindex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask) + deposit_bits(z, zBytesMask); + uint32_t swizzle2Dindex = swizzle3Dindex % (metadata.width * metadata.height); + uint32_t swizzleSlice = swizzle3Dindex / (metadata.width * metadata.height); + size_t swizzleOffset = swizzle2Dindex * bytesPerPixel; size_t rowMajorOffset = y * uncompressedSource[0].rowPitch + x * bytesPerPixel; size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; + uint32_t sourceSlice = toSwizzle ? z : swizzleSlice; + size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; + uint32_t destSlice = toSwizzle ? swizzleSlice : z; + + const uint8_t* sptr = uncompressedSource[sourceSlice].pixels; + if (!sptr) + return E_POINTER; + uint8_t* dptr = uncompressedDestination[destSlice].pixels; + if (!dptr) + return E_POINTER; const uint8_t* sourcePixelPointer = sptr + sourceOffset; uint8_t* destPixelPointer = dptr + destOffset; From c5ef2dbf81eb85820f1f7fbca712cf2bd753f50b Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Thu, 19 Sep 2024 16:31:35 -0700 Subject: [PATCH 07/19] Undo: Almost handel Block Compression. --- DirectXTex/DirectXTexSwizzle.cpp | 134 ++++--------------------------- 1 file changed, 16 insertions(+), 118 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index d4161390..b3625aec 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -52,51 +52,27 @@ HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchI if (FAILED(hr)) return hr; - Image uncompressedSource; - Image uncompressedDestination; - ScratchImage wide; - ScratchImage dest; - if (IsCompressed(srcImage.format)) - { - wide = ScratchImage(); - HRESULT de = Decompress(srcImage, srcImage.format, wide); - if (FAILED(de)) - return de; - uncompressedSource = wide.GetImages()[0]; - - dest = ScratchImage(); - HRESULT dcom = dest.Initialize2D(uncompressedSource.format, srcImage.width, srcImage.height, 1, 1); - if (FAILED(dcom)) - return dcom; - uncompressedDestination = dest.GetImages()[0]; - } - else - { - uncompressedSource = srcImage; - uncompressedDestination = result.GetImages()[0]; - } - - const uint8_t* sptr = uncompressedSource.pixels; + const uint8_t* sptr = srcImage.pixels; if (!sptr) return E_POINTER; - uint8_t* dptr = uncompressedDestination.pixels; + uint8_t* dptr = result.GetImages()[0].pixels; if (!dptr) return E_POINTER; - size_t bytesPerPixel = BitsPerPixel(uncompressedSource.format) / 8; + size_t bytesPerPixel = BitsPerPixel(srcImage.format) / 8; uint32_t xBytesMask = 0b1010101010101010; uint32_t yBytesMask = 0b0101010101010101; - for (size_t y = 0; y < uncompressedSource.height; y++) + for (size_t y = 0; y < srcImage.height; y++) { - for (size_t x = 0; x < uncompressedSource.width; x++) + for (size_t x = 0; x < srcImage.width; x++) { uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); size_t swizzleOffset = swizzleIndex * bytesPerPixel; - size_t rowMajorOffset = y * uncompressedSource.rowPitch + x * bytesPerPixel; + size_t rowMajorOffset = y * srcImage.rowPitch + x * bytesPerPixel; size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; @@ -107,16 +83,6 @@ HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchI } } - if (IsCompressed(srcImage.format)) - { - TEX_COMPRESS_FLAGS flags = TEX_COMPRESS_DEFAULT; // !!TODO!! actual value - float threshold = -42; // !!TODO!! actual value - - Compress(uncompressedDestination, srcImage.format, flags, threshold, result); - wide.Release(); - dest.Release(); - } - return S_OK; } @@ -138,53 +104,29 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T return E_FAIL; } - const Image* uncompressedSource; - const Image* uncompressedDestination; - ScratchImage wide; - ScratchImage dest; - if (IsCompressed(metadata.format)) - { - wide = ScratchImage(); - HRESULT de = Decompress(srcImages, nimages, metadata, metadata.format, wide); - if (FAILED(de)) - return de; - uncompressedSource = wide.GetImages(); - - dest = ScratchImage(); - HRESULT dcom = dest.Initialize2D(uncompressedSource[0].format, srcImages[0].width, srcImages[0].height, nimages, 1); - if (FAILED(dcom)) - return dcom; - uncompressedDestination = dest.GetImages(); - } - else - { - uncompressedSource = srcImages; - uncompressedDestination = result.GetImages(); - } - for (size_t imageIndex = 0; imageIndex < nimages; imageIndex++) { - const uint8_t* sptr = uncompressedSource[imageIndex].pixels; + const uint8_t* sptr = srcImages[imageIndex].pixels; if (!sptr) return E_POINTER; - uint8_t* dptr = uncompressedDestination[imageIndex].pixels; + uint8_t* dptr = result.GetImages()[imageIndex].pixels; if (!dptr) return E_POINTER; - size_t bytesPerPixel = BitsPerPixel(uncompressedSource[imageIndex].format) / 8; + size_t bytesPerPixel = BitsPerPixel(srcImages[imageIndex].format) / 8; uint32_t xBytesMask = 0b1010101010101010; uint32_t yBytesMask = 0b0101010101010101; - for (size_t y = 0; y < uncompressedSource[imageIndex].height; y++) + for (size_t y = 0; y < srcImages[imageIndex].height; y++) { - for (size_t x = 0; x < uncompressedSource[imageIndex].width; x++) + for (size_t x = 0; x < srcImages[imageIndex].width; x++) { uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); size_t swizzleOffset = swizzleIndex * bytesPerPixel; - size_t rowMajorOffset = y * uncompressedSource[0].rowPitch + x * bytesPerPixel; + size_t rowMajorOffset = y * srcImages[0].rowPitch + x * bytesPerPixel; size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; @@ -196,16 +138,6 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T } } - if (IsCompressed(metadata.format)) - { - TEX_COMPRESS_FLAGS flags = TEX_COMPRESS_DEFAULT; // !!TODO!! actual value - float threshold = -42; // !!TODO!! actual value - - Compress(uncompressedDestination, nimages, metadata, metadata.format, flags, threshold, result); - wide.Release(); - dest.Release(); - } - return S_OK; } @@ -227,31 +159,7 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T return E_FAIL; } - const Image* uncompressedSource; - const Image* uncompressedDestination; - ScratchImage wide; - ScratchImage dest; - if (IsCompressed(metadata.format)) - { - wide = ScratchImage(); - HRESULT de = Decompress(srcImages, depth, metadata, metadata.format, wide); - if (FAILED(de)) - return de; - uncompressedSource = wide.GetImages(); - - dest = ScratchImage(); - HRESULT dcom = dest.Initialize3D(uncompressedSource[0].format, srcImages[0].width, srcImages[0].height, depth, 1); - if (FAILED(dcom)) - return dcom; - uncompressedDestination = dest.GetImages(); - } - else - { - uncompressedSource = srcImages; - uncompressedDestination = result.GetImages(); - } - - size_t bytesPerPixel = BitsPerPixel(uncompressedSource[0].format) / 8; + size_t bytesPerPixel = BitsPerPixel(srcImages[0].format) / 8; uint32_t xBytesMask = 0b1001001001001001; uint32_t yBytesMask = 0b0100100100100100; uint32_t zBytesMask = 0b0010010010010010; @@ -267,7 +175,7 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T uint32_t swizzleSlice = swizzle3Dindex / (metadata.width * metadata.height); size_t swizzleOffset = swizzle2Dindex * bytesPerPixel; - size_t rowMajorOffset = y * uncompressedSource[0].rowPitch + x * bytesPerPixel; + size_t rowMajorOffset = y * srcImages[0].rowPitch + x * bytesPerPixel; size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; uint32_t sourceSlice = toSwizzle ? z : swizzleSlice; @@ -275,10 +183,10 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; uint32_t destSlice = toSwizzle ? swizzleSlice : z; - const uint8_t* sptr = uncompressedSource[sourceSlice].pixels; + const uint8_t* sptr = srcImages[sourceSlice].pixels; if (!sptr) return E_POINTER; - uint8_t* dptr = uncompressedDestination[destSlice].pixels; + uint8_t* dptr = result.GetImages()[destSlice].pixels; if (!dptr) return E_POINTER; @@ -289,15 +197,5 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T } } - if (IsCompressed(metadata.format)) - { - TEX_COMPRESS_FLAGS flags = TEX_COMPRESS_DEFAULT; // !!TODO!! actual value - float threshold = -42; // !!TODO!! actual value - - Compress(uncompressedDestination, depth, metadata, metadata.format, flags, threshold, result); - wide.Release(); - dest.Release(); - } - return S_OK; } From 1ecf426786c56a518f57f616dcd5a805941689fb Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Thu, 19 Sep 2024 16:33:51 -0700 Subject: [PATCH 08/19] name the file in itself --- DirectXTex/DirectXTexSwizzle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index b3625aec..fe0dab6b 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -1,5 +1,5 @@ //------------------------------------------------------------------------------------- -// DirectXTexImage.cpp +// DirectXTexSwizzle.cpp // // DirectX Texture Library - Image container // From b35faa508cb264538930035ec363a9d1e6655ab1 Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Thu, 19 Sep 2024 16:39:17 -0700 Subject: [PATCH 09/19] handle compression... this time? --- DirectXTex/DirectXTexSwizzle.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index fe0dab6b..b310919e 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -65,9 +65,12 @@ HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchI uint32_t xBytesMask = 0b1010101010101010; uint32_t yBytesMask = 0b0101010101010101; - for (size_t y = 0; y < srcImage.height; y++) + size_t height = IsCompressed(srcImage.format) ? (srcImage.height + 3) / 4 : srcImage.height; + size_t width = IsCompressed(srcImage.format) ? (srcImage.width + 3) / 4 : srcImage.width; + + for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < srcImage.width; x++) + for (size_t x = 0; x < width; x++) { uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); size_t swizzleOffset = swizzleIndex * bytesPerPixel; @@ -94,8 +97,7 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T if (!srcImages || !nimages || !IsValid(metadata.format) || nimages > metadata.mipLevels || !result.GetImages()) return E_INVALIDARG; - if (metadata.IsVolumemap() - || IsCompressed(metadata.format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + if (metadata.IsVolumemap() || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) return HRESULT_E_NOT_SUPPORTED; if (srcImages[0].format != metadata.format || srcImages[0].width != metadata.width || srcImages[0].height != metadata.height) @@ -104,6 +106,9 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T return E_FAIL; } + size_t height = IsCompressed(metadata.format) ? (metadata.height + 3) / 4 : metadata.height; + size_t width = IsCompressed(metadata.format) ? (metadata.width + 3) / 4 : metadata.width; + for (size_t imageIndex = 0; imageIndex < nimages; imageIndex++) { const uint8_t* sptr = srcImages[imageIndex].pixels; @@ -119,9 +124,9 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T uint32_t xBytesMask = 0b1010101010101010; uint32_t yBytesMask = 0b0101010101010101; - for (size_t y = 0; y < srcImages[imageIndex].height; y++) + for (size_t y = 0; y metadata.depth || !result.GetImages()) return E_INVALIDARG; - if (metadata.IsVolumemap() - || IsCompressed(metadata.format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + if (metadata.IsVolumemap() || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) return HRESULT_E_NOT_SUPPORTED; if (srcImages[0].format != metadata.format || srcImages[0].width != metadata.width || srcImages[0].height != metadata.height) @@ -159,6 +163,9 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T return E_FAIL; } + size_t height = IsCompressed(metadata.format) ? (metadata.height + 3) / 4 : metadata.height; + size_t width = IsCompressed(metadata.format) ? (metadata.width + 3) / 4 : metadata.width; + size_t bytesPerPixel = BitsPerPixel(srcImages[0].format) / 8; uint32_t xBytesMask = 0b1001001001001001; uint32_t yBytesMask = 0b0100100100100100; @@ -166,9 +173,9 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T for (size_t z = 0; z < depth; z++) { - for (size_t y = 0; y < metadata.height; y++) + for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < metadata.width; x++) + for (size_t x = 0; x < width; x++) { uint32_t swizzle3Dindex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask) + deposit_bits(z, zBytesMask); uint32_t swizzle2Dindex = swizzle3Dindex % (metadata.width * metadata.height); From 3466ba5859b7b9cb70e86d8fdb20e57e04e5bb88 Mon Sep 17 00:00:00 2001 From: Isaac Plunkett Date: Thu, 19 Sep 2024 17:27:30 -0700 Subject: [PATCH 10/19] use extractBits --- DirectXTex/DirectXTexSwizzle.cpp | 151 +++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 37 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index b310919e..14e2d881 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -19,6 +19,7 @@ namespace { #ifdef __AVX2__ #define deposit_bits(v,m) _pdep_u32(v,m) +#define extract_bits(v,m) _pext_u32(v,m) #else // N3864 - A constexpr bitwise operations library for C++ // https://github.com/fmatthew5876/stdcxx-bitops @@ -35,6 +36,19 @@ namespace } return res; } + uint32_t extract_bits(uint32_t val, uint32_t mask) + { + uint32_t res = 0; + for (uint32_t bb = 1; mask !=0; bb += bb) + { + if (val & mask & -mask) + { + res |= bb; + } + mask &= (mask - 1); + } + return res; + } #endif } @@ -68,20 +82,37 @@ HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchI size_t height = IsCompressed(srcImage.format) ? (srcImage.height + 3) / 4 : srcImage.height; size_t width = IsCompressed(srcImage.format) ? (srcImage.width + 3) / 4 : srcImage.width; - for (size_t y = 0; y < height; y++) + if (toSwizzle) { - for (size_t x = 0; x < width; x++) + size_t rowPitch = srcImage.rowPitch; + for (size_t y = 0; y < height; y++) { - uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); - size_t swizzleOffset = swizzleIndex * bytesPerPixel; + for (size_t x = 0; x < width; x++) + { + uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); + size_t swizzleOffset = swizzleIndex * bytesPerPixel; - size_t rowMajorOffset = y * srcImage.rowPitch + x * bytesPerPixel; + size_t rowMajorOffset = y * rowPitch + x * bytesPerPixel; - size_t sourceOffset = toSwizzle ? rowMajorOffset : swizzleOffset; - size_t destOffset = toSwizzle ? swizzleOffset : rowMajorOffset; + const uint8_t* sourcePixelPointer = sptr + rowMajorOffset; + uint8_t* destPixelPointer = dptr + swizzleOffset; + memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + } + } + } + else + { + size_t rowPitch = result.GetImages()[0].rowPitch; + for (size_t swizzleIndex = 0; swizzleIndex < (width * height); swizzleIndex++) + { + size_t swizzleOffset = swizzleIndex * bytesPerPixel; - const uint8_t* sourcePixelPointer = sptr + sourceOffset; - uint8_t* destPixelPointer = dptr + destOffset; + uint32_t destX = extract_bits(swizzleIndex, xBytesMask); + uint32_t destY = extract_bits(swizzleIndex, yBytesMask); + size_t rowMajorOffset = destY * rowPitch + destX * bytesPerPixel; + + const uint8_t* sourcePixelPointer = sptr + swizzleOffset; + uint8_t* destPixelPointer = dptr + rowMajorOffset; memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); } } @@ -124,20 +155,37 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T uint32_t xBytesMask = 0b1010101010101010; uint32_t yBytesMask = 0b0101010101010101; - for (size_t y = 0; y Date: Tue, 24 Sep 2024 11:55:17 -0700 Subject: [PATCH 11/19] Update DirectXTexSwizzle.cpp --- DirectXTex/DirectXTexSwizzle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index 14e2d881..00ce5149 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------------- // DirectXTexSwizzle.cpp // -// DirectX Texture Library - Image container +// DirectX Texture Library - Standard Swizzle (z-order curve) // // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. From e5395d8d69689de3569da537273293032775db34 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 24 Sep 2024 13:22:45 -0700 Subject: [PATCH 12/19] Update DirectXTexSwizzle.cpp More code review --- DirectXTex/DirectXTexSwizzle.cpp | 287 +++++++++++++++++++++++++------ 1 file changed, 238 insertions(+), 49 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index 00ce5149..98d51ee8 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -15,6 +15,7 @@ using namespace DirectX; using namespace DirectX::Internal; + namespace { #ifdef __AVX2__ @@ -23,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, uint32_t mask) + uint32_t deposit_bits(uint32_t val, int mask) { uint32_t res = 0; for (uint32_t bb = 1; mask != 0; bb += bb) @@ -36,7 +37,8 @@ namespace } return res; } - uint32_t extract_bits(uint32_t val, uint32_t mask) + + uint32_t extract_bits(uint32_t val, int mask) { uint32_t res = 0; for (uint32_t bb = 1; mask !=0; bb += bb) @@ -50,70 +52,166 @@ namespace return res; } #endif + +#if defined(_M_X64) || defined(_M_ARM64) + constexpr size_t MAX_TEXTURE_SIZE = 16384u * 16384u * 16u; // D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION is 16384 +#else + constexpr size_t MAX_TEXTURE_SIZE = UINT32_MAX; +#endif } +//------------------------------------------------------------------------------------- +// 2D z-order curve +//------------------------------------------------------------------------------------- +namespace +{ + constexpr uint16_t STANDARD_SWIZZLE_MASK_8 = 0b1010101000001111; + constexpr uint16_t STANDARD_SWIZZLE_MASK_16 = 0b1010101010001111; + constexpr uint16_t STANDARD_SWIZZLE_MASK_32 = 0b1010101010001111; + constexpr uint16_t STANDARD_SWIZZLE_MASK_64 = 0b1010101011001111; + constexpr uint16_t STANDARD_SWIZZLE_MASK_128 = 0b1010101011001111; + + inline int GetSwizzleMask(size_t bytesPerPixel) noexcept + { + switch(bytesPerPixel) + { + case 1: return STANDARD_SWIZZLE_MASK_8; + case 2: return STANDARD_SWIZZLE_MASK_16; + case 8: return STANDARD_SWIZZLE_MASK_64; + case 16: return STANDARD_SWIZZLE_MASK_128; + default: return STANDARD_SWIZZLE_MASK_32; + } + } +} + _Use_decl_annotations_ -HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchImage& result) noexcept +HRESULT DirectX::StandardSwizzle( + const Image& srcImage, + bool toSwizzle, + ScratchImage& result) noexcept { - if (!IsValid(srcImage.format)) + if (srcImage.height == 1) + { + // Standard Swizzle doesn't apply to 1D textures. return E_INVALIDARG; + } - if (IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format)) + if (IsPlanar(srcImage.format) || IsPalettized(srcImage.format) || (srcImage.format == DXGI_FORMAT_R1_UNORM)) return HRESULT_E_NOT_SUPPORTED; + if (srcImage.rowPitch > UINT32_MAX || srcImage.slicePitch > UINT32_MAX) + return HRESULT_E_ARITHMETIC_OVERFLOW; + HRESULT hr = result.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); if (FAILED(hr)) return hr; + const bool isCompressed = IsCompressed(srcImage.format); + const size_t bytesPerPixel = isCompressed ? BytesPerBlock(srcImage.format) : (BitsPerPixel(srcImage.format) / 8); + if (!bytesPerPixel) + { + result.Release(); + return E_FAIL; + } + + const size_t height = isCompressed ? (srcImage.height + 3) / 4 : srcImage.height; + const size_t width = isCompressed ? (srcImage.width + 3) / 4 : srcImage.width; + + if ((width > UINT32_MAX) || (height > UINT32_MAX)) + return E_INVALIDARG; + const uint8_t* sptr = srcImage.pixels; if (!sptr) + { + result.Release(); return E_POINTER; + } - uint8_t* dptr = result.GetImages()[0].pixels; + uint8_t* dptr = result.GetPixels(); if (!dptr) + { + result.Release(); return E_POINTER; + } - size_t bytesPerPixel = BitsPerPixel(srcImage.format) / 8; - - uint32_t xBytesMask = 0b1010101010101010; - uint32_t yBytesMask = 0b0101010101010101; - - size_t height = IsCompressed(srcImage.format) ? (srcImage.height + 3) / 4 : srcImage.height; - size_t width = IsCompressed(srcImage.format) ? (srcImage.width + 3) / 4 : srcImage.width; + const int xBytesMask = GetSwizzleMask(bytesPerPixel); + const size_t maxOffset = result.GetPixelsSize(); if (toSwizzle) { - size_t rowPitch = srcImage.rowPitch; - for (size_t y = 0; y < height; y++) + // row-major to z-order curve + const size_t rowPitch = srcImage.rowPitch; + const uint8_t* endPtr = sptr + (rowPitch * height); + for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; x++) + if (sptr >= endPtr) { - uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); - size_t swizzleOffset = swizzleIndex * bytesPerPixel; + result.Release(); + return E_FAIL; + } - size_t rowMajorOffset = y * rowPitch + x * bytesPerPixel; + const uint8_t* sourcePixelPointer = sptr; + for (size_t x = 0; x < width; ++x) + { + const uint32_t swizzleIndex = deposit_bits(static_cast(x), xBytesMask) + deposit_bits(static_cast(y), ~xBytesMask); + const size_t swizzleOffset = swizzleIndex * bytesPerPixel; + if (swizzleOffset >= maxOffset) + { + result.Release(); + return E_UNEXPECTED; + } - const uint8_t* sourcePixelPointer = sptr + rowMajorOffset; uint8_t* destPixelPointer = dptr + swizzleOffset; memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + + sourcePixelPointer += bytesPerPixel; } + + sptr += rowPitch; } } else { - size_t rowPitch = result.GetImages()[0].rowPitch; - for (size_t swizzleIndex = 0; swizzleIndex < (width * height); swizzleIndex++) + // z-order curve to row-major + const size_t rowPitch = result.GetImages()[0].rowPitch; + + const uint64_t totalPixels = static_cast(width) * static_cast(height); + if (totalPixels > UINT32_MAX) { - size_t swizzleOffset = swizzleIndex * bytesPerPixel; + result.Release(); + return HRESULT_E_ARITHMETIC_OVERFLOW; + } + + const uint64_t totalDataSize = totalPixels * static_cast(bytesPerPixel); + if (totalDataSize > MAX_TEXTURE_SIZE) + { + result.Release(); + return HRESULT_E_ARITHMETIC_OVERFLOW; + } + + const uint8_t* endPtr = sptr + static_cast(totalDataSize); + for (size_t swizzleIndex = 0; swizzleIndex < static_cast(totalPixels); ++swizzleIndex) + { + if (sptr >= endPtr) + { + result.Release(); + return E_FAIL; + } uint32_t destX = extract_bits(swizzleIndex, xBytesMask); - uint32_t destY = extract_bits(swizzleIndex, yBytesMask); + uint32_t destY = extract_bits(swizzleIndex, ~xBytesMask); + size_t rowMajorOffset = destY * rowPitch + destX * bytesPerPixel; + if (rowMajorOffset >= maxOffset) + { + result.Release(); + return E_UNEXPECTED; + } - const uint8_t* sourcePixelPointer = sptr + swizzleOffset; uint8_t* destPixelPointer = dptr + rowMajorOffset; - memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + memcpy(destPixelPointer, sptr, bytesPerPixel); + sptr += bytesPerPixel; } } @@ -121,26 +219,40 @@ HRESULT DirectX::StandardSwizzle(const Image& srcImage, bool toSwizzle, ScratchI } _Use_decl_annotations_ -HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const TexMetadata& metadata, bool toSwizzle, ScratchImage& result) noexcept +HRESULT DirectX::StandardSwizzle( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + bool toSwizzle, + ScratchImage& result) noexcept { - HRESULT hr = result.Initialize2D(srcImages[0].format, srcImages[0].width, srcImages[0].height, nimages, 1); - - if (!srcImages || !nimages || !IsValid(metadata.format) || nimages > metadata.mipLevels || !result.GetImages()) + if (!srcImages || !nimages || (metadata.dimension != TEX_DIMENSION_TEXTURE2D)) return E_INVALIDARG; - if (metadata.IsVolumemap() || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || (metadata.format == DXGI_FORMAT_R1_UNORM)) return HRESULT_E_NOT_SUPPORTED; - if (srcImages[0].format != metadata.format || srcImages[0].width != metadata.width || srcImages[0].height != metadata.height) + HRESULT hr = result.Initialize(metadata); + if (FAILED(hr)) + return hr; + + if (nimages != result.GetImageCount()) { - // Base image must be the same format, width, and height + result.Release(); return E_FAIL; } - size_t height = IsCompressed(metadata.format) ? (metadata.height + 3) / 4 : metadata.height; - size_t width = IsCompressed(metadata.format) ? (metadata.width + 3) / 4 : metadata.width; + 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; + } - for (size_t imageIndex = 0; imageIndex < nimages; imageIndex++) + const int xBytesMask = GetSwizzleMask(bytesPerPixel); + + for (size_t imageIndex = 0; imageIndex < nimages; ++imageIndex) { const uint8_t* sptr = srcImages[imageIndex].pixels; if (!sptr) @@ -157,6 +269,8 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T if (toSwizzle) { + // row-major to z-order curve + size_t height = size_t rowPitch = srcImages[imageIndex].rowPitch; for (size_t y = 0; y < height; y++) { @@ -175,6 +289,7 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T } else { + // z-order curve to row-major size_t rowPitch = result.GetImages()[imageIndex].rowPitch; for (size_t swizzleIndex = 0; swizzleIndex < (width * height); swizzleIndex++) { @@ -194,33 +309,106 @@ HRESULT DirectX::StandardSwizzle(const Image* srcImages, size_t nimages, const T return S_OK; } -_Use_decl_annotations_ -HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const TexMetadata& metadata, bool toSwizzle, ScratchImage& result) noexcept + +//------------------------------------------------------------------------------------- +// 3D z-order curve +//------------------------------------------------------------------------------------- +namespace { - HRESULT hr = result.Initialize3D(srcImages[0].format, srcImages[0].width, srcImages[0].height, depth, 1); + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_8 = 0b1001000000001111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_16 = 0b1001000000001111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_32 = 0b1001001000001111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_64 = 0b1001001100001111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_128 = 0b1001001100001111; + + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_8 = 0b0100101000110000; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_16 = 0b0100101000110001; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_32 = 0b0100100100110011; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_64 = 0b0100100000110111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_128 = 0b0100100000111111; + + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_8 = 0b0010010111000000; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_16 = 0b0010010111000001; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_32 = 0b0010010011000011; + 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; + } + } - if (!srcImages || !depth || !IsValid(metadata.format) || depth > metadata.depth || !result.GetImages()) + inline int GetSwizzleMask3D_Y(size_t bytesPerPixel) 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; + } + } + + inline int GetSwizzleMask3D_Z(size_t bytesPerPixel) 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; + } + } +} + +_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 (metadata.IsVolumemap() || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || (metadata.format == DXGI_FORMAT_R1_UNORM)) return HRESULT_E_NOT_SUPPORTED; - if (srcImages[0].format != metadata.format || srcImages[0].width != metadata.width || srcImages[0].height != metadata.height) + HRESULT hr = result.Initialize(metadata); + if (FAILED(hr)) + return hr; + + if ((depth * metadata.mipLevels) != result.GetImageCount()) { - // Base image must be the same format, width, and height + result.Release(); return E_FAIL; } - size_t height = IsCompressed(metadata.format) ? (metadata.height + 3) / 4 : metadata.height; - size_t width = IsCompressed(metadata.format) ? (metadata.width + 3) / 4 : metadata.width; + 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; + } - size_t bytesPerPixel = BitsPerPixel(srcImages[0].format) / 8; - uint32_t xBytesMask = 0b1001001001001001; - uint32_t yBytesMask = 0b0100100100100100; - uint32_t zBytesMask = 0b0010010010010010; + 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 const Image* destImages = result.GetImages(); for (size_t z = 0; z < depth; z++) { @@ -252,6 +440,7 @@ HRESULT DirectX::StandardSwizzle3D(const Image* srcImages, size_t depth, const T } else { + // z-order curve to row-major const Image* destImages = result.GetImages(); for (size_t z = 0; z < depth; z++) { From d70fef1e8cf7b4620417b9b942c79ab9c9024501 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 24 Sep 2024 17:59:51 -0700 Subject: [PATCH 13/19] Update DirectXTexSwizzle.cpp Rework 2D swizzle into templates --- DirectXTex/DirectXTexSwizzle.cpp | 339 +++++++++++++++++++------------ 1 file changed, 213 insertions(+), 126 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index 98d51ee8..890ec01c 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -53,8 +53,10 @@ namespace } #endif + constexpr size_t MAX_TEXTURE_DIMENSION = 16384u; + #if defined(_M_X64) || defined(_M_ARM64) - constexpr size_t MAX_TEXTURE_SIZE = 16384u * 16384u * 16u; // D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION is 16384 + constexpr size_t MAX_TEXTURE_SIZE = 16384u * 16384u * 16u; #else constexpr size_t MAX_TEXTURE_SIZE = UINT32_MAX; #endif @@ -72,84 +74,42 @@ namespace constexpr uint16_t STANDARD_SWIZZLE_MASK_64 = 0b1010101011001111; constexpr uint16_t STANDARD_SWIZZLE_MASK_128 = 0b1010101011001111; - inline int GetSwizzleMask(size_t bytesPerPixel) noexcept + //--------------------------------------------------------------------------------- + // row-major to z-order curve + //--------------------------------------------------------------------------------- + template + HRESULT LinearToStandardSwizzle2D( + const Image& srcImage, + const Image& destImage, + bool isCompressed) noexcept { - switch(bytesPerPixel) - { - case 1: return STANDARD_SWIZZLE_MASK_8; - case 2: return STANDARD_SWIZZLE_MASK_16; - case 8: return STANDARD_SWIZZLE_MASK_64; - case 16: return STANDARD_SWIZZLE_MASK_128; - default: return STANDARD_SWIZZLE_MASK_32; - } - } -} + assert((srcImage.format == destImage.format) || (srcImage.width == destImage.width) || (srcImage.height == destImage.height)); -_Use_decl_annotations_ -HRESULT DirectX::StandardSwizzle( - const Image& srcImage, - bool toSwizzle, - ScratchImage& result) noexcept -{ - if (srcImage.height == 1) - { - // Standard Swizzle doesn't apply to 1D textures. - return E_INVALIDARG; - } - - if (IsPlanar(srcImage.format) || IsPalettized(srcImage.format) || (srcImage.format == DXGI_FORMAT_R1_UNORM)) - return HRESULT_E_NOT_SUPPORTED; - - if (srcImage.rowPitch > UINT32_MAX || srcImage.slicePitch > UINT32_MAX) - return HRESULT_E_ARITHMETIC_OVERFLOW; - - HRESULT hr = result.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); - if (FAILED(hr)) - return hr; + const uint8_t* sptr = srcImage.pixels; + if (!sptr) + return E_POINTER; - const bool isCompressed = IsCompressed(srcImage.format); - const size_t bytesPerPixel = isCompressed ? BytesPerBlock(srcImage.format) : (BitsPerPixel(srcImage.format) / 8); - if (!bytesPerPixel) - { - result.Release(); - return E_FAIL; - } + uint8_t* dptr = destImage.pixels; + if (!dptr) + return E_POINTER; - const size_t height = isCompressed ? (srcImage.height + 3) / 4 : srcImage.height; - const size_t width = isCompressed ? (srcImage.width + 3) / 4 : srcImage.width; + if ((srcImage.rowPitch > UINT32_MAX) || (destImage.rowPitch > UINT32_MAX)) + return HRESULT_E_ARITHMETIC_OVERFLOW; - if ((width > UINT32_MAX) || (height > UINT32_MAX)) - return E_INVALIDARG; + const size_t height = isCompressed ? (srcImage.height + 3) / 4 : srcImage.height; + const size_t width = isCompressed ? (srcImage.width + 3) / 4 : srcImage.width; - const uint8_t* sptr = srcImage.pixels; - if (!sptr) - { - result.Release(); - return E_POINTER; - } + const size_t maxOffset = height * width * bytesPerPixel; + const size_t tail = destImage.rowPitch * destImage.height; + if (maxOffset > tail) + return E_UNEXPECTED; - uint8_t* dptr = result.GetPixels(); - if (!dptr) - { - result.Release(); - return E_POINTER; - } - - const int xBytesMask = GetSwizzleMask(bytesPerPixel); - const size_t maxOffset = result.GetPixelsSize(); - - if (toSwizzle) - { - // row-major to z-order curve const size_t rowPitch = srcImage.rowPitch; const uint8_t* endPtr = sptr + (rowPitch * height); for (size_t y = 0; y < height; ++y) { if (sptr >= endPtr) - { - result.Release(); return E_FAIL; - } const uint8_t* sourcePixelPointer = sptr; for (size_t x = 0; x < width; ++x) @@ -157,10 +117,7 @@ HRESULT DirectX::StandardSwizzle( const uint32_t swizzleIndex = deposit_bits(static_cast(x), xBytesMask) + deposit_bits(static_cast(y), ~xBytesMask); const size_t swizzleOffset = swizzleIndex * bytesPerPixel; if (swizzleOffset >= maxOffset) - { - result.Release(); return E_UNEXPECTED; - } uint8_t* destPixelPointer = dptr + swizzleOffset; memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); @@ -170,49 +127,155 @@ HRESULT DirectX::StandardSwizzle( sptr += rowPitch; } + + if (tail > maxOffset) + { + if (isCompressed) + { + // TODO: Pad with copy of last block + } + else + { + // TODO: zero out tail space + } + } + + return S_OK; } - else + + //--------------------------------------------------------------------------------- + // z-order curve to row-major + //--------------------------------------------------------------------------------- + template + HRESULT StandardSwizzleToLinear2D( + const Image& srcImage, + const Image& destImage, + bool isCompressed) noexcept { - // z-order curve to row-major - const size_t rowPitch = result.GetImages()[0].rowPitch; + assert((srcImage.format == destImage.format) || (srcImage.width == destImage.width) || (srcImage.height == destImage.height)); + + const uint8_t* sptr = srcImage.pixels; + if (!sptr) + return E_POINTER; + + uint8_t* dptr = destImage.pixels; + if (!dptr) + return E_POINTER; + + if ((srcImage.rowPitch > UINT32_MAX) || (destImage.rowPitch > UINT32_MAX)) + return HRESULT_E_ARITHMETIC_OVERFLOW; + + const size_t height = isCompressed ? (srcImage.height + 3) / 4 : srcImage.height; + const size_t width = isCompressed ? (srcImage.width + 3) / 4 : srcImage.width; + + const size_t maxOffset = height * width * bytesPerPixel; + const size_t rowPitch = destImage.rowPitch; const uint64_t totalPixels = static_cast(width) * static_cast(height); if (totalPixels > UINT32_MAX) - { - result.Release(); return HRESULT_E_ARITHMETIC_OVERFLOW; - } const uint64_t totalDataSize = totalPixels * static_cast(bytesPerPixel); if (totalDataSize > MAX_TEXTURE_SIZE) - { - result.Release(); return HRESULT_E_ARITHMETIC_OVERFLOW; - } const uint8_t* endPtr = sptr + static_cast(totalDataSize); for (size_t swizzleIndex = 0; swizzleIndex < static_cast(totalPixels); ++swizzleIndex) { if (sptr >= endPtr) - { - result.Release(); return E_FAIL; - } - uint32_t destX = extract_bits(swizzleIndex, xBytesMask); - uint32_t destY = extract_bits(swizzleIndex, ~xBytesMask); + uint32_t destX = extract_bits(static_cast(swizzleIndex), xBytesMask); + uint32_t destY = extract_bits(static_cast(swizzleIndex), ~xBytesMask); size_t rowMajorOffset = destY * rowPitch + destX * bytesPerPixel; if (rowMajorOffset >= maxOffset) - { - result.Release(); return E_UNEXPECTED; - } uint8_t* destPixelPointer = dptr + rowMajorOffset; memcpy(destPixelPointer, sptr, bytesPerPixel); sptr += bytesPerPixel; } + + return S_OK; + } +} + +_Use_decl_annotations_ +HRESULT DirectX::StandardSwizzle( + const Image& srcImage, + bool toSwizzle, + ScratchImage& result) noexcept +{ + if (srcImage.height == 1 + || (srcImage.width > MAX_TEXTURE_DIMENSION) || (srcImage.height > MAX_TEXTURE_DIMENSION)) + { + // Standard Swizzle is not defined for 1D textures or textures larger than 16k + return E_INVALIDARG; + } + + if (IsPlanar(srcImage.format) || IsPalettized(srcImage.format) || (srcImage.format == DXGI_FORMAT_R1_UNORM)) + return HRESULT_E_NOT_SUPPORTED; + + HRESULT hr = result.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const bool isCompressed = IsCompressed(srcImage.format); + const size_t bytesPerPixel = isCompressed ? BytesPerBlock(srcImage.format) : (BitsPerPixel(srcImage.format) / 8); + if (!bytesPerPixel) + { + result.Release(); + return E_FAIL; + } + + if (toSwizzle) + { + switch(bytesPerPixel) + { + case 1: + hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), false); + break; + case 2: + hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), false); + break; + case 8: + hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), isCompressed); + break; + case 16: + hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), isCompressed); + break; + default: + hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), false); + break; + } + } + else + { + switch(bytesPerPixel) + { + case 1: + hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), false); + break; + case 2: + hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), false); + break; + case 8: + hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), isCompressed); + break; + case 16: + hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), isCompressed); + break; + default: + hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), false); + break; + } + } + + if (FAILED(hr)) + { + result.Release(); + return hr; } return S_OK; @@ -226,7 +289,9 @@ HRESULT DirectX::StandardSwizzle( bool toSwizzle, ScratchImage& result) noexcept { - if (!srcImages || !nimages || (metadata.dimension != TEX_DIMENSION_TEXTURE2D)) + if (!srcImages || !nimages + || (metadata.dimension != TEX_DIMENSION_TEXTURE2D) + || (metadata.width > MAX_TEXTURE_DIMENSION) || (metadata.height > MAX_TEXTURE_DIMENSION)) return E_INVALIDARG; if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || (metadata.format == DXGI_FORMAT_R1_UNORM)) @@ -250,60 +315,82 @@ HRESULT DirectX::StandardSwizzle( return E_FAIL; } - const int xBytesMask = GetSwizzleMask(bytesPerPixel); + const Image* dest = result.GetImages(); + if (!dest) + { + result.Release(); + return E_POINTER; + } - for (size_t imageIndex = 0; imageIndex < nimages; ++imageIndex) + for (size_t index = 0; index < nimages; ++index) { - const uint8_t* sptr = srcImages[imageIndex].pixels; - if (!sptr) - return E_POINTER; + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } - uint8_t* dptr = result.GetImages()[imageIndex].pixels; - if (!dptr) - return E_POINTER; + if ((src.width > MAX_TEXTURE_DIMENSION) || (src.height > MAX_TEXTURE_DIMENSION)) + return E_FAIL; - size_t bytesPerPixel = BitsPerPixel(srcImages[imageIndex].format) / 8; + const Image& dst = dest[index]; + assert(dst.format == metadata.format); - uint32_t xBytesMask = 0b1010101010101010; - uint32_t yBytesMask = 0b0101010101010101; + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } if (toSwizzle) { - // row-major to z-order curve - size_t height = - size_t rowPitch = srcImages[imageIndex].rowPitch; - for (size_t y = 0; y < height; y++) + switch(bytesPerPixel) { - for (size_t x = 0; x < width; x++) - { - uint32_t swizzleIndex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask); - size_t swizzleOffset = swizzleIndex * bytesPerPixel; - - size_t rowMajorOffset = y * rowPitch + x * bytesPerPixel; - - const uint8_t* sourcePixelPointer = sptr + rowMajorOffset; - uint8_t* destPixelPointer = dptr + swizzleOffset; - memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); - } + case 1: + hr = LinearToStandardSwizzle2D(src, dst, false); + break; + case 2: + hr = LinearToStandardSwizzle2D(src, dst, false); + break; + case 8: + hr = LinearToStandardSwizzle2D(src, dst, isCompressed); + break; + case 16: + hr = LinearToStandardSwizzle2D(src, dst, isCompressed); + break; + default: + hr = LinearToStandardSwizzle2D(src, dst, false); + break; } } else { - // z-order curve to row-major - size_t rowPitch = result.GetImages()[imageIndex].rowPitch; - for (size_t swizzleIndex = 0; swizzleIndex < (width * height); swizzleIndex++) + switch(bytesPerPixel) { - size_t swizzleOffset = swizzleIndex * bytesPerPixel; - - uint32_t destX = extract_bits(swizzleIndex, xBytesMask); - uint32_t destY = extract_bits(swizzleIndex, yBytesMask); - size_t rowMajorOffset = destY * rowPitch + destX * bytesPerPixel; - - const uint8_t* sourcePixelPointer = sptr + swizzleOffset; - uint8_t* destPixelPointer = dptr + rowMajorOffset; - memcpy(destPixelPointer, sourcePixelPointer, bytesPerPixel); + case 1: + hr = StandardSwizzleToLinear2D(src, dst, false); + break; + case 2: + hr = StandardSwizzleToLinear2D(src, dst, false); + break; + case 8: + hr = StandardSwizzleToLinear2D(src, dst, isCompressed); + break; + case 16: + hr = StandardSwizzleToLinear2D(src, dst, isCompressed); + break; + default: + hr = StandardSwizzleToLinear2D(src, dst, false); + break; } } + + if (FAILED(hr)) + { + result.Release(); + return hr; + } } return S_OK; @@ -420,7 +507,7 @@ HRESULT DirectX::StandardSwizzle3D( { for (size_t x = 0; x < width; x++) { - uint32_t swizzle3Dindex = deposit_bits(x, xBytesMask) + deposit_bits(y, yBytesMask) + deposit_bits(z, zBytesMask); + uint32_t swizzle3Dindex = deposit_bits(static_cast(x), xBytesMask) + deposit_bits(static_cast(y), yBytesMask) + deposit_bits(static_cast(z), zBytesMask); uint32_t swizzle2Dindex = swizzle3Dindex % (metadata.width * metadata.height); uint32_t swizzleSlice = swizzle3Dindex / (metadata.width * metadata.height); size_t swizzleOffset = swizzle2Dindex * bytesPerPixel; From 6f19a5addc6710e5a7911a8b8aee1488b3e946f0 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 24 Sep 2024 18:05:52 -0700 Subject: [PATCH 14/19] Update DirectXTexSwizzle.cpp Code review --- DirectXTex/DirectXTexSwizzle.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index 890ec01c..d2553266 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -229,24 +229,31 @@ HRESULT DirectX::StandardSwizzle( return E_FAIL; } + const auto dstImage = result.GetImage(0, 0, 0); + if (!dstImage) + { + result.Release(); + return E_POINTER; + } + if (toSwizzle) { switch(bytesPerPixel) { case 1: - hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), false); + hr = LinearToStandardSwizzle2D(srcImage, *dstImage, false); break; case 2: - hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), false); + hr = LinearToStandardSwizzle2D(srcImage, *dstImage, false); break; case 8: - hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), isCompressed); + hr = LinearToStandardSwizzle2D(srcImage, *dstImage, isCompressed); break; case 16: - hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), isCompressed); + hr = LinearToStandardSwizzle2D(srcImage, *dstImage, isCompressed); break; default: - hr = LinearToStandardSwizzle2D(srcImage, *result.GetImage(0, 0, 0), false); + hr = LinearToStandardSwizzle2D(srcImage, *dstImage, false); break; } } @@ -255,19 +262,19 @@ HRESULT DirectX::StandardSwizzle( switch(bytesPerPixel) { case 1: - hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), false); + hr = StandardSwizzleToLinear2D(srcImage, *dstImage, false); break; case 2: - hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), false); + hr = StandardSwizzleToLinear2D(srcImage, *dstImage, false); break; case 8: - hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), isCompressed); + hr = StandardSwizzleToLinear2D(srcImage, *dstImage, isCompressed); break; case 16: - hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), isCompressed); + hr = StandardSwizzleToLinear2D(srcImage, *dstImage, isCompressed); break; default: - hr = StandardSwizzleToLinear2D(srcImage, *result.GetImage(0, 0, 0), false); + hr = StandardSwizzleToLinear2D(srcImage, *dstImage, false); break; } } From 93cb5a2404a9a1c236edb69deee5a7bb3bbe6fc8 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 24 Sep 2024 18:08:37 -0700 Subject: [PATCH 15/19] Update CMakeLists.txt Linux filesystem is case sensitive --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d1ba263c..974e2ad9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,7 @@ set(LIBRARY_SOURCES DirectXTex/DirectXTexMipmaps.cpp DirectXTex/DirectXTexMisc.cpp DirectXTex/DirectXTexNormalMaps.cpp - DirectXTex/DirectxTexSwizzle.cpp + DirectXTex/DirectXTexSwizzle.cpp DirectXTex/DirectXTexPMAlpha.cpp DirectXTex/DirectXTexResize.cpp DirectXTex/DirectXTexTGA.cpp From a41c71ed731087c7eeede0a341b937bc36fab5fd Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 25 Sep 2024 09:32:02 -0700 Subject: [PATCH 16/19] Update remaining vcxproj for new file --- DirectXTex/DirectXTex_Desktop_2019.vcxproj | 1 + DirectXTex/DirectXTex_Desktop_2019.vcxproj.filters | 3 +++ DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj | 1 + DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj.filters | 3 +++ DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj | 1 + DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj.filters | 3 +++ DirectXTex/DirectXTex_GDK_2019.vcxproj | 1 + DirectXTex/DirectXTex_GDK_2019.vcxproj.filters | 3 +++ DirectXTex/DirectXTex_GDK_2022.vcxproj | 1 + DirectXTex/DirectXTex_GDK_2022.vcxproj.filters | 3 +++ DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj | 1 + DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj.filters | 3 +++ DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj | 1 + DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj.filters | 3 +++ DirectXTex/DirectXTex_Windows10_2022.vcxproj | 1 + DirectXTex/DirectXTex_Windows10_2022.vcxproj.filters | 3 +++ 16 files changed, 32 insertions(+) diff --git a/DirectXTex/DirectXTex_Desktop_2019.vcxproj b/DirectXTex/DirectXTex_Desktop_2019.vcxproj index 9d7a6f66..1f0b37d5 100644 --- a/DirectXTex/DirectXTex_Desktop_2019.vcxproj +++ b/DirectXTex/DirectXTex_Desktop_2019.vcxproj @@ -318,6 +318,7 @@ + Create diff --git a/DirectXTex/DirectXTex_Desktop_2019.vcxproj.filters b/DirectXTex/DirectXTex_Desktop_2019.vcxproj.filters index 455eddaf..dd897453 100644 --- a/DirectXTex/DirectXTex_Desktop_2019.vcxproj.filters +++ b/DirectXTex/DirectXTex_Desktop_2019.vcxproj.filters @@ -95,6 +95,9 @@ Source Files + + Source Files + diff --git a/DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj b/DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj index 4cdc5fb8..ef433a5e 100644 --- a/DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj +++ b/DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj @@ -464,6 +464,7 @@ + Create diff --git a/DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj.filters b/DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj.filters index 18d2b226..a1bb3630 100644 --- a/DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj.filters +++ b/DirectXTex/DirectXTex_Desktop_2019_Win10.vcxproj.filters @@ -101,6 +101,9 @@ Source Files + + Source Files + diff --git a/DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj b/DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj index 85d2ddc1..707c35c1 100644 --- a/DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj +++ b/DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj @@ -464,6 +464,7 @@ + Create diff --git a/DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj.filters b/DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj.filters index 18d2b226..a1bb3630 100644 --- a/DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj.filters +++ b/DirectXTex/DirectXTex_Desktop_2022_Win10.vcxproj.filters @@ -101,6 +101,9 @@ Source Files + + Source Files + diff --git a/DirectXTex/DirectXTex_GDK_2019.vcxproj b/DirectXTex/DirectXTex_GDK_2019.vcxproj index 814ed5a2..6cead1e4 100644 --- a/DirectXTex/DirectXTex_GDK_2019.vcxproj +++ b/DirectXTex/DirectXTex_GDK_2019.vcxproj @@ -496,6 +496,7 @@ + Create diff --git a/DirectXTex/DirectXTex_GDK_2019.vcxproj.filters b/DirectXTex/DirectXTex_GDK_2019.vcxproj.filters index dea8b959..261f5724 100644 --- a/DirectXTex/DirectXTex_GDK_2019.vcxproj.filters +++ b/DirectXTex/DirectXTex_GDK_2019.vcxproj.filters @@ -127,5 +127,8 @@ Auxiliary + + Source Files + \ No newline at end of file diff --git a/DirectXTex/DirectXTex_GDK_2022.vcxproj b/DirectXTex/DirectXTex_GDK_2022.vcxproj index f9c878df..fe266f0e 100644 --- a/DirectXTex/DirectXTex_GDK_2022.vcxproj +++ b/DirectXTex/DirectXTex_GDK_2022.vcxproj @@ -496,6 +496,7 @@ + Create diff --git a/DirectXTex/DirectXTex_GDK_2022.vcxproj.filters b/DirectXTex/DirectXTex_GDK_2022.vcxproj.filters index dea8b959..261f5724 100644 --- a/DirectXTex/DirectXTex_GDK_2022.vcxproj.filters +++ b/DirectXTex/DirectXTex_GDK_2022.vcxproj.filters @@ -127,5 +127,8 @@ Auxiliary + + Source Files + \ No newline at end of file diff --git a/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj b/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj index 20056345..d4998eb2 100644 --- a/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj +++ b/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj @@ -240,6 +240,7 @@ + Create diff --git a/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj.filters b/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj.filters index e076b712..be934f6a 100644 --- a/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj.filters +++ b/DirectXTex/DirectXTex_GXDK_PC_2019.vcxproj.filters @@ -113,6 +113,9 @@ Auxiliary + + Source Files + diff --git a/DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj b/DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj index 36d69f0f..3cd0907d 100644 --- a/DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj +++ b/DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj @@ -240,6 +240,7 @@ + Create diff --git a/DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj.filters b/DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj.filters index c04634fa..425bb179 100644 --- a/DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj.filters +++ b/DirectXTex/DirectXTex_GXDK_PC_2022.vcxproj.filters @@ -113,6 +113,9 @@ Auxiliary + + Source Files + diff --git a/DirectXTex/DirectXTex_Windows10_2022.vcxproj b/DirectXTex/DirectXTex_Windows10_2022.vcxproj index e985e55e..0d141a75 100644 --- a/DirectXTex/DirectXTex_Windows10_2022.vcxproj +++ b/DirectXTex/DirectXTex_Windows10_2022.vcxproj @@ -45,6 +45,7 @@ + Create diff --git a/DirectXTex/DirectXTex_Windows10_2022.vcxproj.filters b/DirectXTex/DirectXTex_Windows10_2022.vcxproj.filters index d52dd196..e57bbeb5 100644 --- a/DirectXTex/DirectXTex_Windows10_2022.vcxproj.filters +++ b/DirectXTex/DirectXTex_Windows10_2022.vcxproj.filters @@ -92,6 +92,9 @@ Source Files + + Source Files + From 68b9cc748ce88655e0185ccfb3bb36e1ac752e61 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 25 Sep 2024 09:47:13 -0700 Subject: [PATCH 17/19] StandardSwizzle3D merged into main function --- DirectXTex/DirectXTex.h | 10 +- DirectXTex/DirectXTexSwizzle.cpp | 274 +++++++++++++++++-------------- 2 files changed, 155 insertions(+), 129 deletions(-) diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index a2bc4074..ff91b314 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -730,9 +730,13 @@ namespace DirectX _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ size_t item, _In_ float alphaReference, _Inout_ ScratchImage& mipChain) noexcept; - HRESULT __cdecl StandardSwizzle(_In_ const Image& srcImage, _In_ bool toSwizzle, _Out_ ScratchImage& image) noexcept; - HRESULT __cdecl StandardSwizzle(_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ bool toSwizzle, _Out_ ScratchImage& result) noexcept; - HRESULT __cdecl StandardSwizzle3D(_In_reads_(depth) const Image* srcImages, _In_ size_t depth, _In_ const TexMetadata& metadata, _In_ bool toSwizzle, _Out_ ScratchImage& result) noexcept; + HRESULT __cdecl StandardSwizzle( + _In_ const Image& srcImage, _In_ bool toSwizzle, + _Out_ ScratchImage& image) noexcept; + HRESULT __cdecl StandardSwizzle( + _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ bool toSwizzle, + _Out_ ScratchImage& result) noexcept; + // Performs row-major linear <-> z-order curve swizzling enum TEX_PMALPHA_FLAGS : unsigned long { diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index d2553266..c453ff28 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -60,14 +60,10 @@ namespace #else constexpr size_t MAX_TEXTURE_SIZE = UINT32_MAX; #endif -} - //------------------------------------------------------------------------------------- // 2D z-order curve //------------------------------------------------------------------------------------- -namespace -{ constexpr uint16_t STANDARD_SWIZZLE_MASK_8 = 0b1010101000001111; constexpr uint16_t STANDARD_SWIZZLE_MASK_16 = 0b1010101010001111; constexpr uint16_t STANDARD_SWIZZLE_MASK_32 = 0b1010101010001111; @@ -199,24 +195,90 @@ namespace return S_OK; } + + +//------------------------------------------------------------------------------------- +// 3D z-order curve +//------------------------------------------------------------------------------------- + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_8 = 0b1001000000001111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_16 = 0b1001000000001111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_32 = 0b1001001000001111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_64 = 0b1001001100001111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_128 = 0b1001001100001111; + + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_8 = 0b0100101000110000; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_16 = 0b0100101000110001; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_32 = 0b0100100100110011; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_64 = 0b0100100000110111; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_128 = 0b0100100000111111; + + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_8 = 0b0010010111000000; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_16 = 0b0010010111000001; + constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_32 = 0b0010010011000011; + 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; + } + } + + inline int GetSwizzleMask3D_Y(size_t bytesPerPixel) 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; + } + } + + inline int GetSwizzleMask3D_Z(size_t bytesPerPixel) 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; + } + } } + +//===================================================================================== +// Entry points +//===================================================================================== + _Use_decl_annotations_ HRESULT DirectX::StandardSwizzle( const Image& srcImage, bool toSwizzle, ScratchImage& result) noexcept { - if (srcImage.height == 1 + if ((srcImage.height == 1) || (srcImage.width > MAX_TEXTURE_DIMENSION) || (srcImage.height > MAX_TEXTURE_DIMENSION)) { // Standard Swizzle is not defined for 1D textures or textures larger than 16k - return E_INVALIDARG; + return HRESULT_E_NOT_SUPPORTED; } if (IsPlanar(srcImage.format) || IsPalettized(srcImage.format) || (srcImage.format == DXGI_FORMAT_R1_UNORM)) return HRESULT_E_NOT_SUPPORTED; + if (!srcImage.pixels) + return E_POINTER; + HRESULT hr = result.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); if (FAILED(hr)) return hr; @@ -296,11 +358,16 @@ HRESULT DirectX::StandardSwizzle( bool toSwizzle, ScratchImage& result) noexcept { - if (!srcImages || !nimages - || (metadata.dimension != TEX_DIMENSION_TEXTURE2D) - || (metadata.width > MAX_TEXTURE_DIMENSION) || (metadata.height > MAX_TEXTURE_DIMENSION)) + if (!srcImages || !nimages) return E_INVALIDARG; + if (((metadata.dimension != TEX_DIMENSION_TEXTURE2D) && (metadata.dimension != TEX_DIMENSION_TEXTURE3D)) + || (metadata.width > MAX_TEXTURE_DIMENSION) || (metadata.height > MAX_TEXTURE_DIMENSION)) + { + // Standard Swizzle is not defined for 1D textures or textures larger than 16k + return HRESULT_E_NOT_SUPPORTED; + } + if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || (metadata.format == DXGI_FORMAT_R1_UNORM)) return HRESULT_E_NOT_SUPPORTED; @@ -329,74 +396,86 @@ HRESULT DirectX::StandardSwizzle( return E_POINTER; } - for (size_t index = 0; index < nimages; ++index) + if (metadata.dimension == TEX_DIMENSION_TEXTURE3D) + { + // TODO - + return E_NOTIMPL; + } + else { - const Image& src = srcImages[index]; - if (src.format != metadata.format) + // Handle the 2D case for TEX_DIMENSION_TEXTURE2D + for (size_t index = 0; index < nimages; ++index) { - result.Release(); - return E_FAIL; - } + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } - if ((src.width > MAX_TEXTURE_DIMENSION) || (src.height > MAX_TEXTURE_DIMENSION)) - 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); + 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 (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } - if (toSwizzle) - { - switch(bytesPerPixel) + if (toSwizzle) { - case 1: - hr = LinearToStandardSwizzle2D(src, dst, false); - break; - case 2: - hr = LinearToStandardSwizzle2D(src, dst, false); - break; - case 8: - hr = LinearToStandardSwizzle2D(src, dst, isCompressed); - break; - case 16: - hr = LinearToStandardSwizzle2D(src, dst, isCompressed); - break; - default: - hr = LinearToStandardSwizzle2D(src, dst, false); - break; + switch(bytesPerPixel) + { + case 1: + hr = LinearToStandardSwizzle2D(src, dst, false); + break; + case 2: + hr = LinearToStandardSwizzle2D(src, dst, false); + break; + case 8: + hr = LinearToStandardSwizzle2D(src, dst, isCompressed); + break; + case 16: + hr = LinearToStandardSwizzle2D(src, dst, isCompressed); + break; + default: + hr = LinearToStandardSwizzle2D(src, dst, false); + break; + } } - } - else - { - switch(bytesPerPixel) + else { - case 1: - hr = StandardSwizzleToLinear2D(src, dst, false); - break; - case 2: - hr = StandardSwizzleToLinear2D(src, dst, false); - break; - case 8: - hr = StandardSwizzleToLinear2D(src, dst, isCompressed); - break; - case 16: - hr = StandardSwizzleToLinear2D(src, dst, isCompressed); - break; - default: - hr = StandardSwizzleToLinear2D(src, dst, false); - break; + switch(bytesPerPixel) + { + case 1: + hr = StandardSwizzleToLinear2D(src, dst, false); + break; + case 2: + hr = StandardSwizzleToLinear2D(src, dst, false); + break; + case 8: + hr = StandardSwizzleToLinear2D(src, dst, isCompressed); + break; + case 16: + hr = StandardSwizzleToLinear2D(src, dst, isCompressed); + break; + default: + hr = StandardSwizzleToLinear2D(src, dst, false); + break; + } } - } - if (FAILED(hr)) - { - result.Release(); - return hr; + if (FAILED(hr)) + { + result.Release(); + return hr; + } } } @@ -404,66 +483,8 @@ HRESULT DirectX::StandardSwizzle( } -//------------------------------------------------------------------------------------- -// 3D z-order curve -//------------------------------------------------------------------------------------- -namespace -{ - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_8 = 0b1001000000001111; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_16 = 0b1001000000001111; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_32 = 0b1001001000001111; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_64 = 0b1001001100001111; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_X_128 = 0b1001001100001111; - - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_8 = 0b0100101000110000; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_16 = 0b0100101000110001; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_32 = 0b0100100100110011; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_64 = 0b0100100000110111; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Y_128 = 0b0100100000111111; - - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_8 = 0b0010010111000000; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_16 = 0b0010010111000001; - constexpr uint16_t VOLUME_STANDARD_SWIZZLE_Z_32 = 0b0010010011000011; - 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; - } - } - - inline int GetSwizzleMask3D_Y(size_t bytesPerPixel) 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; - } - } - - inline int GetSwizzleMask3D_Z(size_t bytesPerPixel) 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 0 +// TODO: merging into main based on metadata _Use_decl_annotations_ HRESULT DirectX::StandardSwizzle3D( const Image* srcImages, @@ -566,3 +587,4 @@ HRESULT DirectX::StandardSwizzle3D( return S_OK; } +#endif \ No newline at end of file From 94fc4373d284944f6b06439f19234efd630e7d6a Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 26 Sep 2024 11:03:03 -0700 Subject: [PATCH 18/19] More work on 3D swizzle --- DirectXTex/DirectXTexSwizzle.cpp | 279 ++++++++++++++++++++++--------- 1 file changed, 204 insertions(+), 75 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index c453ff28..db515c2f 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -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) @@ -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) @@ -61,6 +61,64 @@ namespace constexpr size_t MAX_TEXTURE_SIZE = UINT32_MAX; #endif + // Standard Swizzle is not defined for these formats. + bool IsExcludedFormat(DXGI_FORMAT fmt) noexcept + { + switch(static_cast(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 //------------------------------------------------------------------------------------- @@ -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 + 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 + 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; } } @@ -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) @@ -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); @@ -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(srcBase, destBase, depth, false); + break; + case 2: + hr = LinearToStandardSwizzle3D(srcBase, destBase, depth, false); + break; + case 8: + hr = LinearToStandardSwizzle3D(srcBase, destBase, depth, isCompressed); + break; + case 16: + hr = LinearToStandardSwizzle3D(srcBase, destBase, depth, isCompressed); + break; + default: + hr = LinearToStandardSwizzle3D(srcBase, destBase, depth, false); + break; + } + } + else + { + switch(bytesPerPixel) + { + case 1: + hr = StandardSwizzleToLinear3D(srcBase, destBase, depth, false); + break; + case 2: + hr = StandardSwizzleToLinear3D(srcBase, destBase, depth, false); + break; + case 8: + hr = StandardSwizzleToLinear3D(srcBase, destBase, depth, isCompressed); + break; + case 16: + hr = StandardSwizzleToLinear3D(srcBase, destBase, depth, isCompressed); + break; + default: + hr = StandardSwizzleToLinear3D(srcBase, destBase, depth, false); + break; + } + } + + if (FAILED(hr)) + { + result.Release(); + return hr; + } + + if (depth > 1) + depth >>= 1; + } + + return S_OK; } else { @@ -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 @@ -584,7 +716,4 @@ HRESULT DirectX::StandardSwizzle3D( } } } - - return S_OK; -} #endif \ No newline at end of file From 74f7445974f7699503e062d13987cb960464e696 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 26 Sep 2024 14:52:23 -0700 Subject: [PATCH 19/19] More code review --- DirectXTex/DirectXTexSwizzle.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/DirectXTex/DirectXTexSwizzle.cpp b/DirectXTex/DirectXTexSwizzle.cpp index db515c2f..60fe8ad9 100644 --- a/DirectXTex/DirectXTexSwizzle.cpp +++ b/DirectXTex/DirectXTexSwizzle.cpp @@ -13,7 +13,6 @@ #include "DirectXTexP.h" using namespace DirectX; -using namespace DirectX::Internal; namespace @@ -55,10 +54,10 @@ namespace constexpr size_t MAX_TEXTURE_DIMENSION = 16384u; -#if defined(_M_X64) || defined(_M_ARM64) - constexpr size_t MAX_TEXTURE_SIZE = 16384u * 16384u * 16u; +#if defined(_M_X64) || defined(_M_ARM64) || __x86_64__ || __aarch64__ + constexpr uint64_t MAX_TEXTURE_SIZE = 16384u * 16384u * 16u; #else - constexpr size_t MAX_TEXTURE_SIZE = UINT32_MAX; + constexpr uint64_t MAX_TEXTURE_SIZE = UINT32_MAX; #endif // Standard Swizzle is not defined for these formats. @@ -147,7 +146,7 @@ namespace if (!dptr) return E_POINTER; - if ((srcImage.rowPitch > UINT32_MAX) || (destImage.rowPitch > UINT32_MAX)) + if (srcImage.rowPitch > UINT32_MAX) return HRESULT_E_ARITHMETIC_OVERFLOW; const size_t height = isCompressed ? (srcImage.height + 3) / 4 : srcImage.height; @@ -216,7 +215,7 @@ namespace if (!dptr) return E_POINTER; - if ((srcImage.rowPitch > UINT32_MAX) || (destImage.rowPitch > UINT32_MAX)) + if (srcImage.rowPitch > UINT32_MAX) return HRESULT_E_ARITHMETIC_OVERFLOW; const size_t height = isCompressed ? (srcImage.height + 3) / 4 : srcImage.height; @@ -296,9 +295,6 @@ namespace 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; } @@ -320,9 +316,6 @@ namespace 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; }