From d218a9e8200788249cb0aeb7164e1cc0aec3691f Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Sun, 25 Sep 2016 16:04:44 -0700 Subject: [PATCH] texdiag: command-line tool for texture debugging --- DirectXTex_Desktop_2013.sln | 15 + DirectXTex_Desktop_2015.sln | 17 +- Texdiag/directx.ico | Bin 0 -> 25214 bytes Texdiag/texdiag.cpp | 3399 ++++++++++++++++++ Texdiag/texdiag.rc | 76 + Texdiag/texdiag_Desktop_2013.vcxproj | 407 +++ Texdiag/texdiag_Desktop_2013.vcxproj.filters | 17 + Texdiag/texdiag_Desktop_2015.vcxproj | 406 +++ Texdiag/texdiag_Desktop_2015.vcxproj.filters | 17 + 9 files changed, 4353 insertions(+), 1 deletion(-) create mode 100644 Texdiag/directx.ico create mode 100644 Texdiag/texdiag.cpp create mode 100644 Texdiag/texdiag.rc create mode 100644 Texdiag/texdiag_Desktop_2013.vcxproj create mode 100644 Texdiag/texdiag_Desktop_2013.vcxproj.filters create mode 100644 Texdiag/texdiag_Desktop_2015.vcxproj create mode 100644 Texdiag/texdiag_Desktop_2015.vcxproj.filters diff --git a/DirectXTex_Desktop_2013.sln b/DirectXTex_Desktop_2013.sln index 43689fc..3dd5d29 100644 --- a/DirectXTex_Desktop_2013.sln +++ b/DirectXTex_Desktop_2013.sln @@ -14,6 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{988C9BEB EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample", "Sample", "{B66E9586-79BB-4CDB-9547-7857A789D71A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "texdiag", "Texdiag\texdiag_Desktop_2013.vcxproj", "{8E31A619-F4F8-413F-A973-4EE37B1AAA5D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -72,6 +74,18 @@ Global {9D3EDCAD-A800-43F0-B77F-FE6E4DFA3D84}.Release|Win32.Build.0 = Release|Win32 {9D3EDCAD-A800-43F0-B77F-FE6E4DFA3D84}.Release|x64.ActiveCfg = Release|x64 {9D3EDCAD-A800-43F0-B77F-FE6E4DFA3D84}.Release|x64.Build.0 = Release|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Debug|Win32.Build.0 = Debug|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Debug|x64.ActiveCfg = Debug|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Debug|x64.Build.0 = Debug|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Profile|Win32.ActiveCfg = Profile|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Profile|Win32.Build.0 = Profile|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Profile|x64.ActiveCfg = Profile|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Profile|x64.Build.0 = Profile|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Release|Win32.ActiveCfg = Release|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Release|Win32.Build.0 = Release|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Release|x64.ActiveCfg = Release|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -80,5 +94,6 @@ Global {8F18CBD7-4116-4956-BCD8-20D688A4CBD1} = {988C9BEB-76E0-4EFF-AA5F-92750E17C7DC} {C3A65381-8FD3-4F69-B29E-654B4B0ED136} = {988C9BEB-76E0-4EFF-AA5F-92750E17C7DC} {9D3EDCAD-A800-43F0-B77F-FE6E4DFA3D84} = {B66E9586-79BB-4CDB-9547-7857A789D71A} + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D} = {988C9BEB-76E0-4EFF-AA5F-92750E17C7DC} EndGlobalSection EndGlobal diff --git a/DirectXTex_Desktop_2015.sln b/DirectXTex_Desktop_2015.sln index b65c43f..53c5636 100644 --- a/DirectXTex_Desktop_2015.sln +++ b/DirectXTex_Desktop_2015.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTex", "DirectXTex\DirectXTex_Desktop_2015.vcxproj", "{371B9FA9-4C90-4AC6-A123-ACED756D6C77}" EndProject @@ -14,6 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{AEA1D9F7 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample", "Sample", "{E14090F7-2FE9-47EE-A331-14ED71801FDE}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "texdiag", "Texdiag\texdiag_Desktop_2015.vcxproj", "{8E31A619-F4F8-413F-A973-4EE37B1AAA5D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -72,6 +74,18 @@ Global {9D3EDCAD-A800-43F0-B77F-FE6E4DFA3D84}.Release|Win32.Build.0 = Release|Win32 {9D3EDCAD-A800-43F0-B77F-FE6E4DFA3D84}.Release|x64.ActiveCfg = Release|x64 {9D3EDCAD-A800-43F0-B77F-FE6E4DFA3D84}.Release|x64.Build.0 = Release|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Debug|Win32.Build.0 = Debug|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Debug|x64.ActiveCfg = Debug|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Debug|x64.Build.0 = Debug|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Profile|Win32.ActiveCfg = Profile|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Profile|Win32.Build.0 = Profile|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Profile|x64.ActiveCfg = Profile|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Profile|x64.Build.0 = Profile|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Release|Win32.ActiveCfg = Release|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Release|Win32.Build.0 = Release|Win32 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Release|x64.ActiveCfg = Release|x64 + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -80,5 +94,6 @@ Global {8F18CBD7-4116-4956-BCD8-20D688A4CBD1} = {AEA1D9F7-EA95-4BF7-8E6D-0EA068077943} {C3A65381-8FD3-4F69-B29E-654B4B0ED136} = {AEA1D9F7-EA95-4BF7-8E6D-0EA068077943} {9D3EDCAD-A800-43F0-B77F-FE6E4DFA3D84} = {E14090F7-2FE9-47EE-A331-14ED71801FDE} + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D} = {AEA1D9F7-EA95-4BF7-8E6D-0EA068077943} EndGlobalSection EndGlobal diff --git a/Texdiag/directx.ico b/Texdiag/directx.ico new file mode 100644 index 0000000000000000000000000000000000000000..bc43c1b2085df668dffff26d80adcb0ef73f23a9 GIT binary patch literal 25214 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 +#include +#include + +#include +#include +#include + +#include + +#include "directxtex.h" + +using namespace DirectX; + +enum COMMANDS +{ + CMD_INFO = 1, + CMD_ANALYZE, + CMD_COMPARE, + CMD_DUMPBC, + CMD_MAX +}; + +enum OPTIONS +{ + OPT_RECURSIVE = 1, + OPT_FILTER, + OPT_DDS_DWORD_ALIGN, + OPT_DDS_BAD_DXTN_TAILS, + OPT_NOLOGO, + OPT_TYPELESS_UNORM, + OPT_TYPELESS_FLOAT, + OPT_EXPAND_LUMINANCE, + OPT_TARGET_PIXELX, + OPT_TARGET_PIXELY, + OPT_MAX +}; + +static_assert(OPT_MAX <= 32, "dwOptions is a DWORD bitfield"); + +struct SConversion +{ + wchar_t szSrc[MAX_PATH]; +}; + +struct SValue +{ + LPCWSTR pName; + DWORD dwValue; +}; + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +const SValue g_pCommands[] = +{ + { L"info", CMD_INFO }, + { L"analyze", CMD_ANALYZE }, + { L"compare", CMD_COMPARE }, + { L"dumpbc", CMD_DUMPBC }, + { nullptr, 0 } +}; + +const SValue g_pOptions[] = +{ + { L"r", OPT_RECURSIVE }, + { L"if", OPT_FILTER }, + { L"dword", OPT_DDS_DWORD_ALIGN }, + { L"badtails", OPT_DDS_BAD_DXTN_TAILS }, + { L"nologo", OPT_NOLOGO }, + { L"tu", OPT_TYPELESS_UNORM }, + { L"tf", OPT_TYPELESS_FLOAT }, + { L"xlum", OPT_EXPAND_LUMINANCE }, + { L"targetx", OPT_TARGET_PIXELX }, + { L"targety", OPT_TARGET_PIXELY }, + { nullptr, 0 } +}; + +#define DEFFMT(fmt) { L#fmt, DXGI_FORMAT_ ## fmt } + +const SValue g_pFormats[] = +{ + // List does not include _TYPELESS or depth/stencil formats + DEFFMT(R32G32B32A32_FLOAT), + DEFFMT(R32G32B32A32_UINT), + DEFFMT(R32G32B32A32_SINT), + DEFFMT(R32G32B32_FLOAT), + DEFFMT(R32G32B32_UINT), + DEFFMT(R32G32B32_SINT), + DEFFMT(R16G16B16A16_FLOAT), + DEFFMT(R16G16B16A16_UNORM), + DEFFMT(R16G16B16A16_UINT), + DEFFMT(R16G16B16A16_SNORM), + DEFFMT(R16G16B16A16_SINT), + DEFFMT(R32G32_FLOAT), + DEFFMT(R32G32_UINT), + DEFFMT(R32G32_SINT), + DEFFMT(R10G10B10A2_UNORM), + DEFFMT(R10G10B10A2_UINT), + DEFFMT(R11G11B10_FLOAT), + DEFFMT(R8G8B8A8_UNORM), + DEFFMT(R8G8B8A8_UNORM_SRGB), + DEFFMT(R8G8B8A8_UINT), + DEFFMT(R8G8B8A8_SNORM), + DEFFMT(R8G8B8A8_SINT), + DEFFMT(R16G16_FLOAT), + DEFFMT(R16G16_UNORM), + DEFFMT(R16G16_UINT), + DEFFMT(R16G16_SNORM), + DEFFMT(R16G16_SINT), + DEFFMT(R32_FLOAT), + DEFFMT(R32_UINT), + DEFFMT(R32_SINT), + DEFFMT(R8G8_UNORM), + DEFFMT(R8G8_UINT), + DEFFMT(R8G8_SNORM), + DEFFMT(R8G8_SINT), + DEFFMT(R16_FLOAT), + DEFFMT(R16_UNORM), + DEFFMT(R16_UINT), + DEFFMT(R16_SNORM), + DEFFMT(R16_SINT), + DEFFMT(R8_UNORM), + DEFFMT(R8_UINT), + DEFFMT(R8_SNORM), + DEFFMT(R8_SINT), + DEFFMT(A8_UNORM), + //DEFFMT(R1_UNORM) + DEFFMT(R9G9B9E5_SHAREDEXP), + DEFFMT(R8G8_B8G8_UNORM), + DEFFMT(G8R8_G8B8_UNORM), + DEFFMT(BC1_UNORM), + DEFFMT(BC1_UNORM_SRGB), + DEFFMT(BC2_UNORM), + DEFFMT(BC2_UNORM_SRGB), + DEFFMT(BC3_UNORM), + DEFFMT(BC3_UNORM_SRGB), + DEFFMT(BC4_UNORM), + DEFFMT(BC4_SNORM), + DEFFMT(BC5_UNORM), + DEFFMT(BC5_SNORM), + DEFFMT(B5G6R5_UNORM), + DEFFMT(B5G5R5A1_UNORM), + + // DXGI 1.1 formats + DEFFMT(B8G8R8A8_UNORM), + DEFFMT(B8G8R8X8_UNORM), + DEFFMT(R10G10B10_XR_BIAS_A2_UNORM), + DEFFMT(B8G8R8A8_UNORM_SRGB), + DEFFMT(B8G8R8X8_UNORM_SRGB), + DEFFMT(BC6H_UF16), + DEFFMT(BC6H_SF16), + DEFFMT(BC7_UNORM), + DEFFMT(BC7_UNORM_SRGB), + + // DXGI 1.2 formats + DEFFMT(AYUV), + DEFFMT(Y410), + DEFFMT(Y416), + DEFFMT(YUY2), + DEFFMT(Y210), + DEFFMT(Y216), + DEFFMT(AI44), + DEFFMT(IA44), + DEFFMT(P8), + DEFFMT(A8P8), + DEFFMT(B4G4R4A4_UNORM), + + // DXGI 1.3 formats + { L"DXGI_FORMAT_P208", DXGI_FORMAT(130) }, + { L"DXGI_FORMAT_V208", DXGI_FORMAT(131) }, + { L"DXGI_FORMAT_V408", DXGI_FORMAT(132) }, + + // Xbox-specific formats + { L"DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT (Xbox)", DXGI_FORMAT(116) }, + { L"DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT (Xbox)", DXGI_FORMAT(117) }, + { L"DXGI_FORMAT_D16_UNORM_S8_UINT (Xbox)", DXGI_FORMAT(118) }, + { L"DXGI_FORMAT_R16_UNORM_X8_TYPELESS (Xbox)", DXGI_FORMAT(119) }, + { L"DXGI_FORMAT_X16_TYPELESS_G8_UINT (Xbox)", DXGI_FORMAT(120) }, + { L"DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM (Xbox)", DXGI_FORMAT(189) }, + { L"DXGI_FORMAT_R4G4_UNORM (Xbox)", DXGI_FORMAT(190) }, + + { nullptr, DXGI_FORMAT_UNKNOWN } +}; + +const SValue g_pFilters[] = +{ + { L"POINT", TEX_FILTER_POINT }, + { L"LINEAR", TEX_FILTER_LINEAR }, + { L"CUBIC", TEX_FILTER_CUBIC }, + { L"FANT", TEX_FILTER_FANT }, + { L"BOX", TEX_FILTER_BOX }, + { L"TRIANGLE", TEX_FILTER_TRIANGLE }, + { L"POINT_DITHER", TEX_FILTER_POINT | TEX_FILTER_DITHER }, + { L"LINEAR_DITHER", TEX_FILTER_LINEAR | TEX_FILTER_DITHER }, + { L"CUBIC_DITHER", TEX_FILTER_CUBIC | TEX_FILTER_DITHER }, + { L"FANT_DITHER", TEX_FILTER_FANT | TEX_FILTER_DITHER }, + { L"BOX_DITHER", TEX_FILTER_BOX | TEX_FILTER_DITHER }, + { L"TRIANGLE_DITHER", TEX_FILTER_TRIANGLE | TEX_FILTER_DITHER }, + { L"POINT_DITHER_DIFFUSION", TEX_FILTER_POINT | TEX_FILTER_DITHER_DIFFUSION }, + { L"LINEAR_DITHER_DIFFUSION", TEX_FILTER_LINEAR | TEX_FILTER_DITHER_DIFFUSION }, + { L"CUBIC_DITHER_DIFFUSION", TEX_FILTER_CUBIC | TEX_FILTER_DITHER_DIFFUSION }, + { L"FANT_DITHER_DIFFUSION", TEX_FILTER_FANT | TEX_FILTER_DITHER_DIFFUSION }, + { L"BOX_DITHER_DIFFUSION", TEX_FILTER_BOX | TEX_FILTER_DITHER_DIFFUSION }, + { L"TRIANGLE_DITHER_DIFFUSION", TEX_FILTER_TRIANGLE | TEX_FILTER_DITHER_DIFFUSION }, + { nullptr, TEX_FILTER_DEFAULT } +}; + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } + + struct find_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) FindClose(h); } }; + + typedef public std::unique_ptr ScopedFindHandle; + +#pragma prefast(disable : 26018, "Only used with static internal arrays") + + DWORD LookupByName(const wchar_t *pName, const SValue *pArray) + { + while (pArray->pName) + { + if (!_wcsicmp(pName, pArray->pName)) + return pArray->dwValue; + + pArray++; + } + + return 0; + } + + + const wchar_t* LookupByValue(DWORD pValue, const SValue *pArray) + { + while (pArray->pName) + { + if (pValue == pArray->dwValue) + return pArray->pName; + + pArray++; + } + + return L""; + } + + + void SearchForFiles(const wchar_t* path, std::list& files, bool recursive) + { + // Process files + WIN32_FIND_DATA findData = {}; + ScopedFindHandle hFile(safe_handle(FindFirstFileExW(path, + FindExInfoBasic, &findData, + FindExSearchNameMatch, nullptr, + FIND_FIRST_EX_LARGE_FETCH))); + if (hFile) + { + for (;;) + { + if (!(findData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY))) + { + wchar_t drive[_MAX_DRIVE] = {}; + wchar_t dir[_MAX_DIR] = {}; + _wsplitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0); + + SConversion conv; + _wmakepath_s(conv.szSrc, drive, dir, findData.cFileName, nullptr); + files.push_back(conv); + } + + if (!FindNextFile(hFile.get(), &findData)) + break; + } + } + + // Process directories + if (recursive) + { + wchar_t searchDir[MAX_PATH] = {}; + { + wchar_t drive[_MAX_DRIVE] = {}; + wchar_t dir[_MAX_DIR] = {}; + _wsplitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0); + _wmakepath_s(searchDir, drive, dir, L"*", nullptr); + } + + hFile.reset(safe_handle(FindFirstFileExW(searchDir, + FindExInfoBasic, &findData, + FindExSearchLimitToDirectories, nullptr, + FIND_FIRST_EX_LARGE_FETCH))); + if (!hFile) + return; + + for (;;) + { + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (findData.cFileName[0] != L'.') + { + wchar_t subdir[MAX_PATH] = {}; + + { + wchar_t drive[_MAX_DRIVE] = {}; + wchar_t dir[_MAX_DIR] = {}; + wchar_t fname[_MAX_FNAME] = {}; + wchar_t ext[_MAX_FNAME] = {}; + _wsplitpath_s(path, drive, dir, fname, ext); + wcscat_s(dir, findData.cFileName); + _wmakepath_s(subdir, drive, dir, fname, ext); + } + + SearchForFiles(subdir, files, recursive); + } + } + + if (!FindNextFile(hFile.get(), &findData)) + break; + } + } + } + + + void PrintFormat(DXGI_FORMAT Format) + { + for (const SValue *pFormat = g_pFormats; pFormat->pName; pFormat++) + { + if ((DXGI_FORMAT)pFormat->dwValue == Format) + { + wprintf(pFormat->pName); + break; + } + } + } + + + void PrintList(size_t cch, const SValue *pValue) + { + while (pValue->pName) + { + size_t cchName = wcslen(pValue->pName); + + if (cch + cchName + 2 >= 80) + { + wprintf(L"\n "); + cch = 6; + } + + wprintf(L"%ls ", pValue->pName); + cch += cchName + 2; + pValue++; + } + + wprintf(L"\n"); + } + + + void PrintLogo() + { + wprintf(L"Microsoft (R) DirectX Texture Diagnostic Tool\n"); + wprintf(L"Copyright (C) Microsoft Corp. All rights reserved.\n"); +#ifdef _DEBUG + wprintf(L"*** Debug build ***\n"); +#endif + wprintf(L"\n"); + } + + + void PrintUsage() + { + PrintLogo(); + + wprintf(L"Usage: texdiag \n\n"); + wprintf(L" info Output image metadata\n"); + wprintf(L" analyze Analyze and summarize image information\n"); + wprintf(L" compare Compare two images with MSE error metric\n"); + wprintf(L" dumpbc Dump out compressed blocks (DDS BC only)\n\n"); + wprintf(L" -r wildcard filename search is recursive\n"); + wprintf(L" -if image filtering\n"); + wprintf(L"\n (DDS input only)\n"); + wprintf(L" -t{u|f} TYPELESS format is treated as UNORM or FLOAT\n"); + wprintf(L" -dword Use DWORD instead of BYTE alignment\n"); + wprintf(L" -badtails Fix for older DXTn with bad mipchain tails\n"); + wprintf(L" -xlum expand legacy L8, L16, and A8P8 formats\n"); + wprintf(L"\n (dumpbc only)\n"); + wprintf(L" -targetx dump pixels at location x (defaults to all)\n"); + wprintf(L" -targety dump pixels at location y (defaults to all)\n"); + wprintf(L"\n -nologo suppress copyright message\n"); + + wprintf(L"\n : "); + PrintList(13, g_pFilters); + } + + HRESULT LoadImage(const wchar_t *fileName, DWORD dwOptions, DWORD dwFilter, TexMetadata& info, std::unique_ptr& image) + { + if (!fileName) + return E_INVALIDARG; + + image.reset(new (std::nothrow) ScratchImage); + if (!image) + return E_OUTOFMEMORY; + + wchar_t ext[_MAX_EXT]; + _wsplitpath_s(fileName, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT); + + if (_wcsicmp(ext, L".dds") == 0) + { + DWORD ddsFlags = DDS_FLAGS_NONE; + if (dwOptions & (1 << OPT_DDS_DWORD_ALIGN)) + ddsFlags |= DDS_FLAGS_LEGACY_DWORD; + if (dwOptions & (1 << OPT_EXPAND_LUMINANCE)) + ddsFlags |= DDS_FLAGS_EXPAND_LUMINANCE; + if (dwOptions & (1 << OPT_DDS_BAD_DXTN_TAILS)) + ddsFlags |= DDS_FLAGS_BAD_DXTN_TAILS; + + return LoadFromDDSFile(fileName, ddsFlags, &info, *image.get()); + } + else if (_wcsicmp(ext, L".tga") == 0) + { + return LoadFromTGAFile(fileName, &info, *image.get()); + } + else if (_wcsicmp(ext, L".hdr") == 0) + { + return LoadFromHDRFile(fileName, &info, *image.get()); + } + else + { + // WIC shares the same filter values for mode and dither + static_assert(WIC_FLAGS_DITHER == TEX_FILTER_DITHER, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_DITHER_DIFFUSION == TEX_FILTER_DITHER_DIFFUSION, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_FILTER_POINT == TEX_FILTER_POINT, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_FILTER_LINEAR == TEX_FILTER_LINEAR, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_FILTER_CUBIC == TEX_FILTER_CUBIC, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_FILTER_FANT == TEX_FILTER_FANT, "WIC_FLAGS_* & TEX_FILTER_* should match"); + + return LoadFromWICFile(fileName, dwFilter | WIC_FLAGS_ALL_FRAMES, &info, *image.get()); + } + } + + //-------------------------------------------------------------------------------------- + struct AnalyzeData + { + XMFLOAT4 imageMin; + XMFLOAT4 imageMax; + XMFLOAT4 imageAvg; + XMFLOAT4 imageVariance; + XMFLOAT4 imageStdDev; + size_t specials_x; + size_t specials_y; + size_t specials_z; + size_t specials_w; + + void Print() + { + wprintf(L"\t Minimum - (%f %f %f %f)\n", imageMin.x, imageMin.y, imageMin.z, imageMin.w); + wprintf(L"\t Average - (%f %f %f %f)\n", imageAvg.x, imageAvg.y, imageAvg.z, imageAvg.w); + wprintf(L"\t Maximum - (%f %f %f %f)\n", imageMax.x, imageMax.y, imageMax.z, imageMax.w); + wprintf(L"\tVariance - (%f %f %f %f)\n", imageVariance.x, imageVariance.y, imageVariance.z, imageVariance.w); + wprintf(L"\t Std Dev - (%f %f %f %f)\n", imageStdDev.x, imageStdDev.y, imageStdDev.z, imageStdDev.w); + + if ((specials_x > 0) || (specials_y > 0) || (specials_z > 0) || (specials_w > 0)) + { + wprintf(L" FP specials - (%Iu %Iu %Iu %Iu)\n", specials_x, specials_y, specials_z, specials_w); + } + } + }; + + HRESULT Analyze(const Image& image, _Out_ AnalyzeData& result) + { + memset(&result, 0, sizeof(AnalyzeData)); + + // First pass + XMVECTOR minv = g_XMFltMax; + XMVECTOR maxv = XMVectorNegate(g_XMFltMax); + XMVECTOR acc = g_XMZero; + + size_t totalPixels = 0; + + HRESULT hr = EvaluateImage(image, [&](const XMVECTOR * pixels, size_t width, size_t y) + { + UNREFERENCED_PARAMETER(y); + + for (size_t x = 0; x < width; ++x) + { + XMVECTOR v = *pixels++; + minv = XMVectorMin(minv, v); + maxv = XMVectorMax(maxv, v); + acc = XMVectorAdd(v, acc); + ++totalPixels; + + XMFLOAT4 f; + XMStoreFloat4(&f, v); + if (!_finite(f.x)) + { + ++result.specials_x; + } + + if (!_finite(f.y)) + { + ++result.specials_y; + } + + if (!_finite(f.z)) + { + ++result.specials_z; + } + + if (!_finite(f.w)) + { + ++result.specials_w; + } + } + }); + if (FAILED(hr)) + return hr; + + if (!totalPixels) + return S_FALSE; + + XMStoreFloat4(&result.imageMin, minv); + XMStoreFloat4(&result.imageMax, maxv); + + XMVECTOR pixelv = XMVectorReplicate(float(totalPixels)); + XMVECTOR avgv = XMVectorDivide(acc, pixelv); + XMStoreFloat4(&result.imageAvg, avgv); + + // Second pass + acc = g_XMZero; + + hr = EvaluateImage(image, [&](const XMVECTOR * pixels, size_t width, size_t y) + { + UNREFERENCED_PARAMETER(y); + + for (size_t x = 0; x < width; ++x) + { + XMVECTOR v = *pixels++; + + XMVECTOR diff = XMVectorSubtract(v, avgv); + acc = XMVectorMultiplyAdd(diff, diff, acc); + } + }); + if (FAILED(hr)) + return hr; + + XMStoreFloat4(&result.imageVariance, acc); + + XMVECTOR stddev = XMVectorSqrt(acc); + + XMStoreFloat4(&result.imageStdDev, stddev); + + return S_OK; + } + + + //-------------------------------------------------------------------------------------- + struct AnalyzeBCData + { + size_t blocks; + size_t blockHist[15]; + + void Print(DXGI_FORMAT fmt) + { + wprintf(L"\t Compression - "); + PrintFormat(fmt); + wprintf(L"\n\t Total blocks - %Iu\n", blocks); + + switch (fmt) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + wprintf(L"\t 4 color blocks - %Iu\n", blockHist[0]); + wprintf(L"\t 3 color blocks - %Iu\n", blockHist[1]); + break; + + // BC2 only has a single 'type' of block + + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + wprintf(L"\t 8 alpha blocks - %Iu\n", blockHist[0]); + wprintf(L"\t 6 alpha blocks - %Iu\n", blockHist[1]); + break; + + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + wprintf(L"\t 8 red blocks - %Iu\n", blockHist[0]); + wprintf(L"\t 6 red blocks - %Iu\n", blockHist[1]); + break; + + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + wprintf(L"\t 8 red blocks - %Iu\n", blockHist[0]); + wprintf(L"\t 6 red blocks - %Iu\n", blockHist[1]); + wprintf(L"\t 8 green blocks - %Iu\n", blockHist[2]); + wprintf(L"\t 6 green blocks - %Iu\n", blockHist[3]); + break; + + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + for (size_t j = 1; j <= 14; ++j) + { + if (blockHist[j] > 0) + wprintf(L"\t Mode %02Iu blocks - %Iu\n", j, blockHist[j]); + } + if (blockHist[0] > 0) + wprintf(L"\tReserved mode blcks - %Iu\n", blockHist[0]); + break; + + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + for (size_t j = 0; j <= 7; ++j) + { + if (blockHist[j] > 0) + wprintf(L"\t Mode %02Iu blocks - %Iu\n", j, blockHist[j]); + } + if (blockHist[8] > 0) + wprintf(L"\tReserved mode blcks - %Iu\n", blockHist[8]); + break; + } + } + }; + +#pragma pack(push,1) + struct BC1Block + { + uint16_t rgb[2]; // 565 colors + uint32_t bitmap; // 2bpp rgb bitmap + }; + + struct BC2Block + { + uint32_t bitmap[2]; // 4bpp alpha bitmap + BC1Block bc1; // BC1 rgb data + }; + + struct BC3Block + { + uint8_t alpha[2]; // alpha values + uint8_t bitmap[6]; // 3bpp alpha bitmap + BC1Block bc1; // BC1 rgb data + }; + + struct BC4UBlock + { + uint8_t red_0; + uint8_t red_1; + uint8_t indices[6]; + }; + + struct BC4SBlock + { + int8_t red_0; + int8_t red_1; + uint8_t indices[6]; + }; + + struct BC5UBlock + { + BC4UBlock u; + BC4UBlock v; + }; + + struct BC5SBlock + { + BC4SBlock u; + BC4SBlock v; + }; +#pragma pack(pop) + + HRESULT AnalyzeBC(const Image& image, _Out_ AnalyzeBCData& result) + { + memset(&result, 0, sizeof(AnalyzeBCData)); + + size_t sbpp; + switch (image.format) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + sbpp = 8; + break; + + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + sbpp = 16; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + const uint8_t *pSrc = image.pixels; + const size_t rowPitch = image.rowPitch; + + for (size_t h = 0; h < image.height; h += 4) + { + const uint8_t *sptr = pSrc; + + for (size_t count = 0; count < rowPitch; count += sbpp) + { + switch (image.format) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + auto block = reinterpret_cast(sptr); + + if (block->rgb[0] <= block->rgb[1]) + { + // Transparent block + ++result.blockHist[1]; + } + else + { + // Opaque block + ++result.blockHist[0]; + } + } + break; + + // BC2 only has a single 'type' of block + + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + auto block = reinterpret_cast(sptr); + + if (block->alpha[0] > block->alpha[1]) + { + // 8 alpha block + ++result.blockHist[0]; + } + else + { + // 6 alpha block + ++result.blockHist[1]; + } + } + break; + + case DXGI_FORMAT_BC4_UNORM: + { + auto block = reinterpret_cast(sptr); + + if (block->red_0 > block->red_1) + { + // 8 red block + ++result.blockHist[0]; + } + else + { + // 6 red block + ++result.blockHist[1]; + } + } + break; + + case DXGI_FORMAT_BC4_SNORM: + { + auto block = reinterpret_cast(sptr); + + if (block->red_0 > block->red_1) + { + // 8 red block + ++result.blockHist[0]; + } + else + { + // 6 red block + ++result.blockHist[1]; + } + } + break; + + case DXGI_FORMAT_BC5_UNORM: + { + auto block = reinterpret_cast(sptr); + + if (block->u.red_0 > block->u.red_1) + { + // 8 red block + ++result.blockHist[0]; + } + else + { + // 6 red block + ++result.blockHist[1]; + } + + if (block->v.red_0 > block->v.red_1) + { + // 8 green block + ++result.blockHist[2]; + } + else + { + // 6 green block + ++result.blockHist[3]; + } + } + break; + + case DXGI_FORMAT_BC5_SNORM: + { + auto block = reinterpret_cast(sptr); + + if (block->u.red_0 > block->u.red_1) + { + // 8 red block + ++result.blockHist[0]; + } + else + { + // 6 red block + ++result.blockHist[1]; + } + + if (block->v.red_0 > block->v.red_1) + { + // 8 green block + ++result.blockHist[2]; + } + else + { + // 6 green block + ++result.blockHist[3]; + } + } + break; + + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + switch (*sptr & 0x03) + { + case 0x00: + // Mode 1 (2 bits, 00) + ++result.blockHist[1]; + break; + + case 0x01: + // Mode 2 (2 bits, 01) + ++result.blockHist[2]; + break; + + default: + switch (*sptr & 0x1F) + { + case 0x02: + // Mode 3 (5 bits, 00010) + ++result.blockHist[3]; + break; + + case 0x06: + // Mode 4 (5 bits, 00110) + ++result.blockHist[4]; + break; + + case 0x0A: + // Mode 5 (5 bits, 01010) + ++result.blockHist[5]; + break; + + case 0x0E: + // Mode 6 (5 bits, 01110) + ++result.blockHist[6]; + break; + + case 0x12: + // Mode 7 (5 bits, 10010) + ++result.blockHist[7]; + break; + + case 0x16: + // Mode 8 (5 bits, 10110) + ++result.blockHist[8]; + break; + + case 0x1A: + // Mode 9 (5 bits, 11010) + ++result.blockHist[9]; + break; + + case 0x1E: + // Mode 10 (5 bits, 11110) + ++result.blockHist[10]; + break; + + case 0x03: + // Mode 11 (5 bits, 00011) + ++result.blockHist[11]; + break; + + case 0x07: + // Mode 12 (5 bits, 00111) + ++result.blockHist[12]; + break; + + case 0x0B: + // Mode 13 (5 bits, 01011) + ++result.blockHist[13]; + break; + + case 0x0F: + // Mode 14 (5 bits, 01111) + ++result.blockHist[14]; + break; + + case 0x13: // Reserved mode (5 bits, 10011) + case 0x17: // Reserved mode (5 bits, 10111) + case 0x1B: // Reserved mode (5 bits, 11011) + case 0x1F: // Reserved mode (5 bits, 11111) + default: + ++result.blockHist[0]; + break; + } + break; + } + break; + + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + if (*sptr & 0x01) + { + // Mode 0 (1) + ++result.blockHist[0]; + } + else if (*sptr & 0x02) + { + // Mode 1 (01) + ++result.blockHist[1]; + } + else if (*sptr & 0x04) + { + // Mode 2 (001) + ++result.blockHist[2]; + } + else if (*sptr & 0x08) + { + // Mode 3 (0001) + ++result.blockHist[3]; + } + else if (*sptr & 0x10) + { + // Mode 4 (00001) + ++result.blockHist[4]; + } + else if (*sptr & 0x20) + { + // Mode 5 (000001) + ++result.blockHist[5]; + } + else if (*sptr & 0x40) + { + // Mode 6 (0000001) + ++result.blockHist[6]; + } + else if (*sptr & 0x80) + { + // Mode 7 (00000001) + ++result.blockHist[7]; + } + else + { + // Reserved mode 8 (00000000) + ++result.blockHist[8]; + } + break; + } + + sptr += sbpp; + ++result.blocks; + } + + pSrc += rowPitch; + } + + return S_OK; + } + + + //-------------------------------------------------------------------------------------- + // Partition, Shape, Fixup + const uint8_t g_aFixUp[3][64][3] = + { + { // No fix-ups for 1st subset for BC6H or BC7 + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 }, + { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 } + }, + + { // BC6H/BC7 Partition Set Fixups for 2 Subsets + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0, 2, 0 },{ 0, 8, 0 },{ 0, 2, 0 }, + { 0, 2, 0 },{ 0, 8, 0 },{ 0, 8, 0 },{ 0,15, 0 }, + { 0, 2, 0 },{ 0, 8, 0 },{ 0, 2, 0 },{ 0, 2, 0 }, + { 0, 8, 0 },{ 0, 8, 0 },{ 0, 2, 0 },{ 0, 2, 0 }, + + // BC7 Partition Set Fixups for 2 Subsets (second-half) + { 0,15, 0 },{ 0,15, 0 },{ 0, 6, 0 },{ 0, 8, 0 }, + { 0, 2, 0 },{ 0, 8, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0, 2, 0 },{ 0, 8, 0 },{ 0, 2, 0 },{ 0, 2, 0 }, + { 0, 2, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0, 6, 0 }, + { 0, 6, 0 },{ 0, 2, 0 },{ 0, 6, 0 },{ 0, 8, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0, 2, 0 },{ 0, 2, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0, 2, 0 },{ 0, 2, 0 },{ 0,15, 0 } + }, + + { // BC7 Partition Set Fixups for 3 Subsets + { 0, 3,15 },{ 0, 3, 8 },{ 0,15, 8 },{ 0,15, 3 }, + { 0, 8,15 },{ 0, 3,15 },{ 0,15, 3 },{ 0,15, 8 }, + { 0, 8,15 },{ 0, 8,15 },{ 0, 6,15 },{ 0, 6,15 }, + { 0, 6,15 },{ 0, 5,15 },{ 0, 3,15 },{ 0, 3, 8 }, + { 0, 3,15 },{ 0, 3, 8 },{ 0, 8,15 },{ 0,15, 3 }, + { 0, 3,15 },{ 0, 3, 8 },{ 0, 6,15 },{ 0,10, 8 }, + { 0, 5, 3 },{ 0, 8,15 },{ 0, 8, 6 },{ 0, 6,10 }, + { 0, 8,15 },{ 0, 5,15 },{ 0,15,10 },{ 0,15, 8 }, + { 0, 8,15 },{ 0,15, 3 },{ 0, 3,15 },{ 0, 5,10 }, + { 0, 6,10 },{ 0,10, 8 },{ 0, 8, 9 },{ 0,15,10 }, + { 0,15, 6 },{ 0, 3,15 },{ 0,15, 8 },{ 0, 5,15 }, + { 0,15, 3 },{ 0,15, 6 },{ 0,15, 6 },{ 0,15, 8 }, + { 0, 3,15 },{ 0,15, 3 },{ 0, 5,15 },{ 0, 5,15 }, + { 0, 5,15 },{ 0, 8,15 },{ 0, 5,15 },{ 0,10,15 }, + { 0, 5,15 },{ 0,10,15 },{ 0, 8,15 },{ 0,13,15 }, + { 0,15, 3 },{ 0,12,15 },{ 0, 3,15 },{ 0, 3, 8 } + } + }; + + inline static bool IsFixUpOffset(_In_range_(0, 2) size_t uPartitions, _In_range_(0, 63) uint64_t uShape, _In_range_(0, 15) size_t uOffset) + { + for (size_t p = 0; p <= uPartitions; p++) + { + if (uOffset == g_aFixUp[uPartitions][uShape][p]) + { + return true; + } + } + return false; + } + + //-------------------------------------------------------------------------------------- +#define SIGN_EXTEND(x,nb) ((((x)&(1<<((nb)-1)))?((~0)<<(nb)):0)|(x)) + +#define NUM_PIXELS_PER_BLOCK 16 + + void Print565(uint16_t rgb) + { + float r = (float)((rgb >> 11) & 31) * (1.0f / 31.0f); + float g = (float)((rgb >> 5) & 63) * (1.0f / 63.0f); + float b = (float)((rgb >> 0) & 31) * (1.0f / 31.0f); + + wprintf(L"(R: %.3f, G: %.3f, B: %.3f)", r, g, b); + } + + void PrintIndex2bpp(uint32_t bitmap) + { + for (size_t j = 0; j < NUM_PIXELS_PER_BLOCK; ++j, bitmap >>= 2) + { + wprintf(L"%u%ls", bitmap & 0x3, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + } + } + + void PrintIndex2bpp(uint64_t bitmap, size_t parts, uint64_t shape) + { + for (size_t j = 0; j < NUM_PIXELS_PER_BLOCK; ++j) + { + if (IsFixUpOffset(parts, shape, j)) + { + wprintf(L"%I64u%ls", bitmap & 0x1, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + bitmap >>= 1; + } + else + { + wprintf(L"%I64u%ls", bitmap & 0x3, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + bitmap >>= 2; + } + } + } + + void PrintIndex3bpp(uint64_t bitmap, size_t parts, uint64_t shape) + { + for (size_t j = 0; j < NUM_PIXELS_PER_BLOCK; ++j) + { + if (IsFixUpOffset(parts, shape, j)) + { + wprintf(L"%I64u%ls", bitmap & 0x3, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + bitmap >>= 2; + } + else + { + wprintf(L"%I64u%ls", bitmap & 0x7, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + bitmap >>= 3; + } + } + } + + void PrintIndex4bpp(uint64_t bitmap, size_t parts, uint64_t shape) + { + for (size_t j = 0; j < NUM_PIXELS_PER_BLOCK; ++j) + { + if (IsFixUpOffset(parts, shape, j)) + { + wprintf(L"%I64X%ls", bitmap & 0x7, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + bitmap >>= 3; + } + else + { + wprintf(L"%I64X%ls", bitmap & 0xF, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + bitmap >>= 4; + } + } + } + + void PrintIndex3bpp(const uint8_t data[6]) + { + uint32_t bitmap = data[0] | (data[1] << 8) | (data[2] << 16); + + size_t j = 0; + for (; j < (NUM_PIXELS_PER_BLOCK / 2); ++j, bitmap >>= 3) + { + wprintf(L"%u%ls", bitmap & 0x7, ((j % 4) == 3) ? L" | " : L" "); + } + + bitmap = data[3] | (data[4] << 8) | (data[5] << 16); + + for (; j < NUM_PIXELS_PER_BLOCK; ++j, bitmap >>= 3) + { + wprintf(L"%u%ls", bitmap & 0x7, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + } + } + + const wchar_t* GetRotBits(uint64_t rot) + { + switch (rot) + { + case 1: return L" (R<->A)"; + case 2: return L" (G<->A)"; + case 3: return L" (B<->A)"; + default: return L""; + } + } + + HRESULT DumpBCImage(const Image& image, int pixelx, int pixely) + { + size_t sbpp; + switch (image.format) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + sbpp = 8; + break; + + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + sbpp = 16; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + const uint8_t *pSrc = image.pixels; + const size_t rowPitch = image.rowPitch; + + size_t nblock = 0; + for (size_t h = 0; h < image.height; h += 4, pSrc += rowPitch) + { + if (pixely >= 0) + { + if ((pixely < int(h)) || (pixely >= int(h + 4))) + continue; + } + + const uint8_t *sptr = pSrc; + + size_t w = 0; + for (size_t count = 0; count < rowPitch; count += sbpp, w += 4, ++nblock, sptr += sbpp) + { + if (pixelx >= 0) + { + if ((pixelx < int(w)) || (pixelx >= int(w + 4))) + continue; + } + + wprintf(L" Block %Iu (pixel: %Iu x %Iu)\n", nblock, w, h); + switch (image.format) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + auto block = reinterpret_cast(sptr); + + if (block->rgb[0] <= block->rgb[1]) + { + // Transparent block + wprintf(L"\tTransparent - E0: "); + } + else + { + // Opaque block + wprintf(L"\t Opaque - E0: "); + } + + Print565(block->rgb[0]); + wprintf(L"\n\t E1: "); + Print565(block->rgb[1]); + wprintf(L"\n\t Index: "); + PrintIndex2bpp(block->bitmap); + wprintf(L"\n"); + } + break; + + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + { + auto block = reinterpret_cast(sptr); + + wprintf(L"\tColor - E0: "); + Print565(block->bc1.rgb[0]); + wprintf(L"\n\t E1: "); + Print565(block->bc1.rgb[1]); + wprintf(L"\n\t Index: "); + PrintIndex2bpp(block->bc1.bitmap); + wprintf(L"\n"); + + wprintf(L"\tAlpha - "); + + size_t j = 0; + uint32_t bitmap = block->bitmap[0]; + for (; j < (NUM_PIXELS_PER_BLOCK / 2); ++j, bitmap >>= 4) + { + wprintf(L"%X%ls", bitmap & 0xF, ((j % 4) == 3) ? L" | " : L" "); + } + + bitmap = block->bitmap[1]; + for (; j < NUM_PIXELS_PER_BLOCK; ++j, bitmap >>= 4) + { + wprintf(L"%X%ls", bitmap & 0xF, ((j < (NUM_PIXELS_PER_BLOCK - 1)) && ((j % 4) == 3)) ? L" | " : L" "); + } + + wprintf(L"\n"); + } + break; + + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + auto block = reinterpret_cast(sptr); + + wprintf(L"\tColor - E0: "); + Print565(block->bc1.rgb[0]); + wprintf(L"\n\t E1: "); + Print565(block->bc1.rgb[1]); + wprintf(L"\n\t Index: "); + PrintIndex2bpp(block->bc1.bitmap); + wprintf(L"\n"); + + wprintf(L"\tAlpha - E0: %0.3f E1: %0.3f (%u)\n\t Index: ", + float((float)block->alpha[0] / 255.f), + float((float)block->alpha[1] / 255.f), (block->alpha[0] > block->alpha[1]) ? 8 : 6); + + PrintIndex3bpp(block->bitmap); + + wprintf(L"\n"); + } + break; + + case DXGI_FORMAT_BC4_UNORM: + { + auto block = reinterpret_cast(sptr); + + wprintf(L"\t E0: %0.3f E1: %0.3f (%u)\n\tIndex: ", + float((float)block->red_0 / 255.f), + float((float)block->red_1 / 255.f), (block->red_0 > block->red_1) ? 8 : 6); + + PrintIndex3bpp(block->indices); + + wprintf(L"\n"); + } + break; + + case DXGI_FORMAT_BC4_SNORM: + { + auto block = reinterpret_cast(sptr); + + wprintf(L"\t E0: %0.3f E1: %0.3f (%u)\n\tIndex: ", + float((float)block->red_0 / 127.f), + float((float)block->red_1 / 127.f), (block->red_0 > block->red_1) ? 8 : 6); + + PrintIndex3bpp(block->indices); + + wprintf(L"\n"); + } + break; + + case DXGI_FORMAT_BC5_UNORM: + { + auto block = reinterpret_cast(sptr); + + wprintf(L"\tU - E0: %0.3f E1: %0.3f (%u)\n\t Index: ", + float((float)block->u.red_0 / 255.f), + float((float)block->u.red_1 / 255.f), (block->u.red_0 > block->u.red_1) ? 8 : 6); + + PrintIndex3bpp(block->u.indices); + + wprintf(L"\n"); + + wprintf(L"\tV - E0: %0.3f E1: %0.3f (%u)\n\t Index: ", + float((float)block->v.red_0 / 255.f), + float((float)block->v.red_1 / 255.f), (block->v.red_0 > block->v.red_1) ? 8 : 6); + + PrintIndex3bpp(block->v.indices); + + wprintf(L"\n"); + } + break; + + case DXGI_FORMAT_BC5_SNORM: + { + auto block = reinterpret_cast(sptr); + + wprintf(L"\tU - E0: %0.3f E1: %0.3f (%u)\n\t Index: ", + float((float)block->u.red_0 / 127.f), + float((float)block->u.red_1 / 127.f), (block->u.red_0 > block->u.red_1) ? 8 : 6); + + PrintIndex3bpp(block->u.indices); + + wprintf(L"\n"); + + wprintf(L"\tV - E0: %0.3f E1: %0.3f (%u)\n\t Index: ", + float((float)block->v.red_0 / 127.f), + float((float)block->v.red_1 / 127.f), (block->v.red_0 > block->v.red_1) ? 8 : 6); + + PrintIndex3bpp(block->v.indices); + + wprintf(L"\n"); + } + break; + + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + // http://msdn.microsoft.com/en-us/library/windows/desktop/hh308952.aspx#decoding_the_bc6h_format + + switch (*sptr & 0x03) + { + case 0x00: + // Mode 1 (2 bits, 00) + { + struct bc6h_mode1 + { + uint64_t mode : 2; // { M, 0}, { M, 1} + uint64_t gy4 : 1; // {GY, 4} + uint64_t by4 : 1; // {BY, 4} + uint64_t bz4 : 1; // {BZ, 4} + uint64_t rw : 10; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9} + uint64_t gw : 10; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9} + uint64_t bw : 10; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9} + uint64_t rx : 5; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4} + uint64_t gz4 : 1; // {GZ, 4} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 5; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4} + uint64_t bz0 : 1; // {BZ, 0}, + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 5; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4} + uint64_t bz1 : 1; // {BZ, 1} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 5; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4} + uint64_t bz2 : 1; // {BZ, 2} + uint64_t rz : 5; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + }; + static_assert(sizeof(bc6h_mode1) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw), int(m->gw), int(m->bw)); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), + int(m->gy | (m->gy4 << 4)), + int(m->by | (m->by3 << 3) | (m->by4 << 4))); + XMINT3 e1_B(int(m->rz), + int(m->gz | (m->gz4 << 4)), + int(m->bz0 | (m->bz1 << 1) | (m->bz2 << 2) | (m->bz3 << 3) | (m->bz4 << 4))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 10); + e0_A.y = SIGN_EXTEND(e0_A.y, 10); + e0_A.z = SIGN_EXTEND(e0_A.z, 10); + + e0_B.x = SIGN_EXTEND(e0_B.x, 5); + e0_B.y = SIGN_EXTEND(e0_B.y, 5); + e0_B.z = SIGN_EXTEND(e0_B.z, 5); + + e1_A.x = SIGN_EXTEND(e1_A.x, 5); + e1_A.y = SIGN_EXTEND(e1_A.y, 5); + e1_A.z = SIGN_EXTEND(e1_A.z, 5); + + e1_B.x = SIGN_EXTEND(e1_B.x, 5); + e1_B.y = SIGN_EXTEND(e1_B.y, 5); + e1_B.z = SIGN_EXTEND(e1_B.z, 5); + } + + wprintf(L"\tMode 1 - [10 5 5 5] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x01: + // Mode 2 (2 bits, 01) + { + struct bc6h_mode2 + { + uint64_t mode : 2; // { M, 0}, { M, 1} + uint64_t gy5 : 1; // {GY, 5} + uint64_t gz45 : 2; // {GZ, 4}, {GZ, 5} + uint64_t rw : 7; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6} + uint64_t bz : 2; // {BZ, 0}, {BZ, 1} + uint64_t by4 : 1; // {BY, 4}, + uint64_t gw : 7; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6} + uint64_t by5 : 1; // {BY, 5} + uint64_t bz2 : 1; // {BZ, 2} + uint64_t gy4 : 1; // {GY, 4} + uint64_t bw : 7; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t bz5 : 1; // {BZ, 5} + uint64_t bz4 : 1; // {BZ, 4} + uint64_t rx : 6; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, {RX, 5} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 6; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, {GX, 5} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 5; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, {BX, 5} + uint64_t by : 4; // {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3} + uint64_t ry : 6; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, {RY, 5} + uint64_t rz : 6; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5}, + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + + }; + static_assert(sizeof(bc6h_mode2) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw), int(m->gw), int(m->bw)); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), + int(m->gy | (m->gy4 << 4) | (m->gy5 << 5)), + int(m->by | (m->by4 << 4) | (m->by5 << 5))); + XMINT3 e1_B(int(m->rz), + int(m->gz | (m->gz45 << 4)), + int(m->bz | (m->bz2 << 2) | (m->bz3 << 3) | (m->bz4 << 4) | (m->bz5 << 5))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 7); + e0_A.y = SIGN_EXTEND(e0_A.y, 7); + e0_A.z = SIGN_EXTEND(e0_A.z, 7); + + e0_B.x = SIGN_EXTEND(e0_B.x, 6); + e0_B.y = SIGN_EXTEND(e0_B.y, 6); + e0_B.z = SIGN_EXTEND(e0_B.z, 6); + + e1_A.x = SIGN_EXTEND(e1_A.x, 6); + e1_A.y = SIGN_EXTEND(e1_A.y, 6); + e1_A.z = SIGN_EXTEND(e1_A.z, 6); + + e1_B.x = SIGN_EXTEND(e1_B.x, 6); + e1_B.y = SIGN_EXTEND(e1_B.y, 6); + e1_B.z = SIGN_EXTEND(e1_B.z, 6); + } + + wprintf(L"\tMode 2 - [7 6 6 6] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + default: + switch (*sptr & 0x1F) + { + case 0x02: + // Mode 3 (5 bits, 00010) + { + struct bc6h_mode3 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 10; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9} + uint64_t gw : 10; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9} + uint64_t bw : 10; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9} + uint64_t rx : 5; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4} + uint64_t rw10 : 1; // {RW,10} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 4; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3} + uint64_t gw10 : 1; // {GW,10} + uint64_t bz0 : 1; // {BZ, 0} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 4; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3} + uint64_t bw10 : 1; // {BW,10} + uint64_t bz1 : 1; // {BZ, 1} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 5; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4} + uint64_t bz2 : 1; // {BZ, 2} + uint64_t rz : 5; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + + }; + static_assert(sizeof(bc6h_mode3) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw | (m->rw10 << 10)), + int(m->gw | (m->gw10 << 10)), + int(m->bw | (m->bw10 << 10))); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), int(m->gy), + int(m->by | (m->by3 << 3))); + XMINT3 e1_B(int(m->rz), + int(m->gz), + int(m->bz0 | (m->bz1 << 1) | (m->bz2 << 2) | (m->bz3 << 3))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 11); + e0_A.y = SIGN_EXTEND(e0_A.y, 11); + e0_A.z = SIGN_EXTEND(e0_A.z, 11); + + e0_B.x = SIGN_EXTEND(e0_B.x, 5); + e0_B.y = SIGN_EXTEND(e0_B.y, 4); + e0_B.z = SIGN_EXTEND(e0_B.z, 4); + + e1_A.x = SIGN_EXTEND(e1_A.x, 5); + e1_A.y = SIGN_EXTEND(e1_A.y, 4); + e1_A.z = SIGN_EXTEND(e1_A.z, 4); + + e1_B.x = SIGN_EXTEND(e1_B.x, 5); + e1_B.y = SIGN_EXTEND(e1_B.y, 4); + e1_B.z = SIGN_EXTEND(e1_B.z, 4); + } + + wprintf(L"\tMode 3 - [11 5 4 4] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x06: + // Mode 4 (5 bits, 00110) + { + struct bc6h_mode4 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 10; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9} + uint64_t gw : 10; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9} + uint64_t bw : 10; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9} + uint64_t rx : 4; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3} + uint64_t rw10 : 1; // {RW,10} + uint64_t gz4 : 1; // {GZ, 4} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 5; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4} + uint64_t gw10 : 1; // {GW,10} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 4; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3} + uint64_t bw10 : 1; // {BW,10} + uint64_t bz1 : 1; // {BZ, 1} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 4; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3} + uint64_t bz0 : 1; // {BZ, 0} + uint64_t bz2 : 1; // {BZ, 2} + uint64_t rz : 4; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3} + uint64_t gy4 : 1; // {GY, 4} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + + }; + static_assert(sizeof(bc6h_mode4) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw | (m->rw10 << 10)), + int(m->gw | (m->gw10 << 10)), + int(m->bw | (m->bw10 << 10))); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), + int(m->gy | (m->gy4 << 4)), + int(m->by | (m->by3 << 3))); + XMINT3 e1_B(int(m->rz), + int(m->gz | (m->gz4 << 4)), + int(m->bz0 | (m->bz1 << 1) | (m->bz2 << 2) | (m->bz3 << 3))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 11); + e0_A.y = SIGN_EXTEND(e0_A.y, 11); + e0_A.z = SIGN_EXTEND(e0_A.z, 11); + + e0_B.x = SIGN_EXTEND(e0_B.x, 4); + e0_B.y = SIGN_EXTEND(e0_B.y, 5); + e0_B.z = SIGN_EXTEND(e0_B.z, 4); + + e1_A.x = SIGN_EXTEND(e1_A.x, 4); + e1_A.y = SIGN_EXTEND(e1_A.y, 5); + e1_A.z = SIGN_EXTEND(e1_A.z, 4); + + e1_B.x = SIGN_EXTEND(e1_B.x, 4); + e1_B.y = SIGN_EXTEND(e1_B.y, 5); + e1_B.z = SIGN_EXTEND(e1_B.z, 4); + } + + wprintf(L"\tMode 4 - [11 4 5 4] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x0A: + // Mode 5 (5 bits, 01010) + { + struct bc6h_mode5 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 10; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9} + uint64_t gw : 10; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9} + uint64_t bw : 10; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9} + uint64_t rx : 4; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3} + uint64_t rw10 : 1; // {RW,10} + uint64_t by4 : 1; // {BY, 4} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 4; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3} + uint64_t gw10 : 1; // {GW,10} + uint64_t bz0 : 1; // {BZ, 0} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 5; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4} + uint64_t bw10 : 1; // {BW,10} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 4; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3} + uint64_t bz12 : 2; // {BZ, 1}, {BZ, 2} + uint64_t rz : 5; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {BZ, 4} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + }; + static_assert(sizeof(bc6h_mode5) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw | (m->rw10 << 10)), + int(m->gw | (m->gw10 << 10)), + int(m->bw | (m->bw10 << 10))); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), int(m->gy), + int(m->by | (m->by3 << 3) | (m->by4 << 4))); + XMINT3 e1_B(int(m->rz), int(m->gz), + int(m->bz0 | (m->bz12 << 1) | (m->bz3 << 3))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 11); + e0_A.y = SIGN_EXTEND(e0_A.y, 11); + e0_A.z = SIGN_EXTEND(e0_A.z, 11); + + e0_B.x = SIGN_EXTEND(e0_B.x, 4); + e0_B.y = SIGN_EXTEND(e0_B.y, 4); + e0_B.z = SIGN_EXTEND(e0_B.z, 5); + + e1_A.x = SIGN_EXTEND(e1_A.x, 4); + e1_A.y = SIGN_EXTEND(e1_A.y, 4); + e1_A.z = SIGN_EXTEND(e1_A.z, 5); + + e1_B.x = SIGN_EXTEND(e1_B.x, 4); + e1_B.y = SIGN_EXTEND(e1_B.y, 4); + e1_B.z = SIGN_EXTEND(e1_B.z, 5); + } + + wprintf(L"\tMode 5 - [11 4 4 5] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x0E: + // Mode 6 (5 bits, 01110) + { + struct bc6h_mode6 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 9; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8} + uint64_t by4 : 1; // {BY, 4} + uint64_t gw : 9; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8} + uint64_t gy4 : 1; // {GY, 4} + uint64_t bw : 9; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8} + uint64_t bz4 : 1; // {BZ, 4} + uint64_t rx : 5; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4} + uint64_t gz4 : 1; // {GZ, 4} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 5; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4} + uint64_t bz0 : 1; // {BZ, 0} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 5; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4} + uint64_t bz1 : 1; // {BZ, 1} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 5; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + uint64_t bz2 : 1; // {BZ, 2} + uint64_t rz : 5; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {BZ, 4} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + }; + static_assert(sizeof(bc6h_mode6) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw), int(m->gw), int(m->bw)); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), + int(m->gy | (m->gy4 << 4)), + int(m->by | (m->by3 << 3) | (m->by4 << 4))); + XMINT3 e1_B(int(m->rz), + int(m->gz | (m->gz4 << 4)), + int(m->bz0 | (m->bz1 << 1) | (m->bz2 << 2) | (m->bz3 << 3) | (m->bz4 << 4))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 9); + e0_A.y = SIGN_EXTEND(e0_A.y, 9); + e0_A.z = SIGN_EXTEND(e0_A.z, 9); + + e0_B.x = SIGN_EXTEND(e0_B.x, 5); + e0_B.y = SIGN_EXTEND(e0_B.y, 5); + e0_B.z = SIGN_EXTEND(e0_B.z, 5); + + e1_A.x = SIGN_EXTEND(e1_A.x, 5); + e1_A.y = SIGN_EXTEND(e1_A.y, 5); + e1_A.z = SIGN_EXTEND(e1_A.z, 5); + + e1_B.x = SIGN_EXTEND(e1_B.x, 5); + e1_B.y = SIGN_EXTEND(e1_B.y, 5); + e1_B.z = SIGN_EXTEND(e1_B.z, 5); + } + + wprintf(L"\tMode 6 - [9 5 5 5] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x12: + // Mode 7 (5 bits, 10010) + { + struct bc6h_mode7 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 8; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7} + uint64_t gz4 : 1; // {GZ, 4} + uint64_t by4 : 1; // {BY, 4} + uint64_t gw : 8; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7} + uint64_t bz2 : 1; // {BZ, 2} + uint64_t gy4 : 1; // {GY, 4} + uint64_t bw : 8; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t bz4 : 1; // {BZ, 4} + uint64_t rx : 6; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, {RX, 5} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 5; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4} + uint64_t bz0 : 1; // {BZ, 0} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 5; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4} + uint64_t bz1 : 1; // {BZ, 1} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 6; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, {RY, 5} + uint64_t rz : 6; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + }; + static_assert(sizeof(bc6h_mode7) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw), int(m->gw), int(m->bw)); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), + int(m->gy | (m->gy4 << 4)), + int(m->by | (m->by3 << 3) | (m->by4 << 4))); + XMINT3 e1_B(int(m->rz), + int(m->gz | (m->gz4 << 4)), + int(m->bz0 | (m->bz1 << 1) | (m->bz2 << 2) | (m->bz3 << 3) | (m->bz4 << 4))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 8); + e0_A.y = SIGN_EXTEND(e0_A.y, 8); + e0_A.z = SIGN_EXTEND(e0_A.z, 8); + + e0_B.x = SIGN_EXTEND(e0_B.x, 6); + e0_B.y = SIGN_EXTEND(e0_B.y, 5); + e0_B.z = SIGN_EXTEND(e0_B.z, 5); + + e1_A.x = SIGN_EXTEND(e1_A.x, 6); + e1_A.y = SIGN_EXTEND(e1_A.y, 5); + e1_A.z = SIGN_EXTEND(e1_A.z, 5); + + e1_B.x = SIGN_EXTEND(e1_B.x, 6); + e1_B.y = SIGN_EXTEND(e1_B.y, 5); + e1_B.z = SIGN_EXTEND(e1_B.z, 5); + } + + wprintf(L"\tMode 7 - [8 6 5 5] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x16: + // Mode 8 (5 bits, 10110) + { + struct bc6h_mode8 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 8; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7} + uint64_t bz0 : 1; // {BZ, 0} + uint64_t by4 : 1; // {BY, 4} + uint64_t gw : 8; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7} + uint64_t gy5 : 1; // {GY, 5} + uint64_t gy4 : 1; // {GY, 4} + uint64_t bw : 8; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7} + uint64_t gz5 : 1; // {GZ, 5} + uint64_t bz4 : 1; // {BZ, 4} + uint64_t rx : 5; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4} + uint64_t gz4 : 1; // {GZ, 4} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 6; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, {GX, 5} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 5; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4} + uint64_t bz1 : 1; // {BZ, 1} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 5; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4} + uint64_t bz2 : 1; // {BZ, 2} + uint64_t rz : 5; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + }; + static_assert(sizeof(bc6h_mode8) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw), int(m->gw), int(m->bw)); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), + int(m->gy | (m->gy4 << 4) | (m->gy5 << 5)), + int(m->by | (m->by3 << 3) | (m->by4 << 4))); + XMINT3 e1_B(int(m->rz), + int(m->gz | (m->gz4 << 4) | (m->gz5 << 5)), + int(m->bz0 | (m->bz1 << 1) | (m->bz2 << 2) | (m->bz3 << 3) | (m->bz4 << 4))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 8); + e0_A.y = SIGN_EXTEND(e0_A.y, 8); + e0_A.z = SIGN_EXTEND(e0_A.z, 8); + + e0_B.x = SIGN_EXTEND(e0_B.x, 5); + e0_B.y = SIGN_EXTEND(e0_B.y, 6); + e0_B.z = SIGN_EXTEND(e0_B.z, 5); + + e1_A.x = SIGN_EXTEND(e1_A.x, 5); + e1_A.y = SIGN_EXTEND(e1_A.y, 6); + e1_A.z = SIGN_EXTEND(e1_A.z, 5); + + e1_B.x = SIGN_EXTEND(e1_B.x, 5); + e1_B.y = SIGN_EXTEND(e1_B.y, 6); + e1_B.z = SIGN_EXTEND(e1_B.z, 5); + } + + wprintf(L"\tMode 8 - [8 5 6 5] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x1A: + // Mode 9 (5 bits, 11010) + { + struct bc6h_mode9 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 8; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7} + uint64_t bz1 : 1; // {BZ, 1} + uint64_t by4 : 1; // {BY, 4} + uint64_t gw : 8; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7} + uint64_t by5 : 1; // {BY, 5} + uint64_t gy4 : 1; // {GY, 4} + uint64_t bw : 8; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7} + uint64_t bz5 : 1; // {BZ, 5} + uint64_t bz4 : 1; // {BZ, 4} + uint64_t rx : 5; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4} + uint64_t gz4 : 1; // {GZ, 4} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 5; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4} + uint64_t bz0 : 1; // {BZ, 0} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 6; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, {BX, 5} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 5; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4} + uint64_t bz2 : 1; // {BZ, 2} + uint64_t rz : 5; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + }; + static_assert(sizeof(bc6h_mode9) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw), int(m->gw), int(m->bw)); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), + int(m->gy | (m->gy4 << 4)), + int(m->by | (m->by3 << 3) | (m->by4 << 4) | (m->by5 << 5))); + XMINT3 e1_B(int(m->rz), + int(m->gz | (m->gz4 << 4)), + int(m->bz0 | (m->bz1 << 1) | (m->bz2 << 2) | (m->bz3 << 3) | (m->bz4 << 4) | (m->bz5 << 5))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 8); + e0_A.y = SIGN_EXTEND(e0_A.y, 8); + e0_A.z = SIGN_EXTEND(e0_A.z, 8); + + e0_B.x = SIGN_EXTEND(e0_B.x, 5); + e0_B.y = SIGN_EXTEND(e0_B.y, 5); + e0_B.z = SIGN_EXTEND(e0_B.z, 6); + + e1_A.x = SIGN_EXTEND(e1_A.x, 5); + e1_A.y = SIGN_EXTEND(e1_A.y, 5); + e1_A.z = SIGN_EXTEND(e1_A.z, 6); + + e1_B.x = SIGN_EXTEND(e1_B.x, 5); + e1_B.y = SIGN_EXTEND(e1_B.y, 5); + e1_B.z = SIGN_EXTEND(e1_B.z, 6); + } + + wprintf(L"\tMode 9 - [8 5 5 6] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x1E: + // Mode 10 (5 bits, 11110) + { + struct bc6h_mode10 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 6; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5} + uint64_t gz4 : 1; // {GZ, 4} + uint64_t bz : 2; // {BZ, 0}, {BZ, 1} + uint64_t by4 : 1; // {BY, 4} + uint64_t gw : 6; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5} + uint64_t gy5 : 1; // {GY, 5} + uint64_t by5 : 1; // {BY, 5} + uint64_t bz2 : 1; // {BZ, 2} + uint64_t gy4 : 1; // {GY, 4} + uint64_t bw : 6; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {GZ, 5} + uint64_t bz3 : 1; // {BZ, 3} + uint64_t bz5 : 1; // {BZ, 5} + uint64_t bz4 : 1; // {BZ, 4} + uint64_t rx : 6; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, {RX, 5} + uint64_t gy : 4; // {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3} + uint64_t gx : 6; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, {GX, 5} + uint64_t gz : 4; // {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3} + uint64_t bx : 6; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, {BX, 5} + uint64_t by : 3; // {BY, 0}, {BY, 1}, {BY, 2} + uint64_t by3 : 1; // {BY, 3} + uint64_t ry : 6; // {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, {RY, 5} + uint64_t rz : 6; // {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5} + uint64_t d : 5; // { D, 0}, { D, 1}, { D, 2}, { D, 3}, { D, 4} + uint64_t indices : 46; + }; + static_assert(sizeof(bc6h_mode10) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw), int(m->gw), int(m->bw)); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + XMINT3 e1_A(int(m->ry), + int(m->gy | (m->gy4 << 4) | (m->gy5 << 5)), + int(m->by | (m->by3 << 3) | (m->by4 << 4) | (m->by5 << 5))); + XMINT3 e1_B(int(m->rz), + int(m->gz | (m->gz4 << 4)), + int(m->bz | (m->bz2 << 2) | (m->bz3 << 3) | (m->bz4 << 4) | (m->bz5 << 5))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 6); + e0_A.y = SIGN_EXTEND(e0_A.y, 6); + e0_A.z = SIGN_EXTEND(e0_A.z, 6); + + e0_B.x = SIGN_EXTEND(e0_B.x, 6); + e0_B.y = SIGN_EXTEND(e0_B.y, 6); + e0_B.z = SIGN_EXTEND(e0_B.z, 6); + + e1_A.x = SIGN_EXTEND(e1_A.x, 6); + e1_A.y = SIGN_EXTEND(e1_A.y, 6); + e1_A.z = SIGN_EXTEND(e1_A.z, 6); + + e1_B.x = SIGN_EXTEND(e1_B.x, 6); + e1_B.y = SIGN_EXTEND(e1_B.y, 6); + e1_B.z = SIGN_EXTEND(e1_B.z, 6); + } + + wprintf(L"\tMode 10 - [6 6 6 6] shape %I64u\n", m->d); + wprintf(L"\t E0(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E0(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t E1(A): (%04X, %04X, %04X)\n", e1_A.x & 0xFFFF, e1_A.y & 0xFFFF, e1_A.z & 0xFFFF); + wprintf(L"\t E1(B): (%04X, %04X, %04X)\n", e1_B.x & 0xFFFF, e1_B.y & 0xFFFF, e1_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->indices, 1, m->d); + wprintf(L"\n"); + } + break; + + case 0x03: + // Mode 11 (5 bits, 00011) + { + struct bc6h_mode11 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 10; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9} + uint64_t gw : 10; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9} + uint64_t bw : 10; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9} + uint64_t rx : 10; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, {RX, 5}, {RX, 6}, {RX, 7}, {RX, 8}, {RX, 9} + uint64_t gx : 10; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, {GX, 5}, {GX, 6}, {GX, 7}, {GX, 8}, {GX, 9} + uint64_t bx : 9; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, {BX, 5}, {BX, 6}, {BX, 7}, {BX, 8} + uint64_t bx9 : 1; // {BX, 9} + uint64_t indices : 63; + }; + static_assert(sizeof(bc6h_mode11) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw), int(m->gw), int(m->bw)); + XMINT3 e0_B(int(m->rx), int(m->gx), + int(m->bx | (m->bx9 << 9))); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 10); + e0_A.y = SIGN_EXTEND(e0_A.y, 10); + e0_A.z = SIGN_EXTEND(e0_A.z, 10); + + e0_B.x = SIGN_EXTEND(e0_B.x, 10); + e0_B.y = SIGN_EXTEND(e0_B.y, 10); + e0_B.z = SIGN_EXTEND(e0_B.z, 10); + } + + wprintf(L"\tMode 11 - [10 10]\n"); + wprintf(L"\t E(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex4bpp(m->indices, 0, 0); + wprintf(L"\n"); + } + break; + + case 0x07: + // Mode 12 (5 bits, 00111) + { + struct bc6h_mode12 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 10; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9} + uint64_t gw : 10; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9} + uint64_t bw : 10; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9} + uint64_t rx : 9; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, {RX, 5}, {RX, 6}, {RX, 7}, {RX, 8} + uint64_t rw10 : 1; // {RW,10} + uint64_t gx : 9; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, {GX, 5}, {GX, 6}, {GX, 7}, {GX, 8} + uint64_t gw10 : 1; // {GW,10} + uint64_t bx : 9; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, {BX, 5}, {BX, 6}, {BX, 7}, {BX, 8} + uint64_t bw10 : 1; // {BW,10} + uint64_t indices : 63; + }; + static_assert(sizeof(bc6h_mode12) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw | (m->rw10 << 10)), + int(m->gw | (m->gw10 << 10)), + int(m->bw | (m->bw10 << 10))); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 11); + e0_A.y = SIGN_EXTEND(e0_A.y, 11); + e0_A.z = SIGN_EXTEND(e0_A.z, 11); + + e0_B.x = SIGN_EXTEND(e0_B.x, 9); + e0_B.y = SIGN_EXTEND(e0_B.y, 9); + e0_B.z = SIGN_EXTEND(e0_B.z, 9); + } + + wprintf(L"\tMode 12 - [11 9]\n"); + wprintf(L"\t E(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex4bpp(m->indices, 0, 0); + wprintf(L"\n"); + } + break; + + case 0x0B: + // Mode 13 (5 bits, 01011) + { + struct bc6h_mode13 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 10; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9} + uint64_t gw : 10; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9} + uint64_t bw : 10; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9} + uint64_t rx : 8; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, {RX, 5}, {RX, 6}, {RX, 7} + uint64_t rw11 : 1; // {RW,11} + uint64_t rw10 : 1; // {RW,10} + uint64_t gx : 8; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, {GX, 5}, {GX, 6}, {GX, 7} + uint64_t gw11 : 1; // {GW,11} + uint64_t gw10 : 1; // {GW,10} + uint64_t bx : 8; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, {BX, 5}, {BX, 6}, {BX, 7} + uint64_t bw11 : 1; // {BW,11} + uint64_t bw10 : 1; // {BW,10} + uint64_t indices : 63; + }; + static_assert(sizeof(bc6h_mode13) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw | (m->rw10 << 10) | (m->rw11 << 11)), + int(m->gw | (m->gw10 << 10) | (m->gw11 << 11)), + int(m->bw | (m->bw10 << 10) | (m->bw11 << 11))); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 12); + e0_A.y = SIGN_EXTEND(e0_A.y, 12); + e0_A.z = SIGN_EXTEND(e0_A.z, 12); + + e0_B.x = SIGN_EXTEND(e0_B.x, 8); + e0_B.y = SIGN_EXTEND(e0_B.y, 8); + e0_B.z = SIGN_EXTEND(e0_B.z, 8); + } + + wprintf(L"\tMode 13 - [12 8]\n"); + wprintf(L"\t E(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex4bpp(m->indices, 0, 0); + wprintf(L"\n"); + } + break; + + case 0x0F: + // Mode 14 (5 bits, 01111) + { + struct bc6h_mode14 + { + uint64_t mode : 5; // { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4} + uint64_t rw : 10; // {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9} + uint64_t gw : 10; // {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9} + uint64_t bw : 10; // {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9} + uint64_t rx : 4; // {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3} + uint64_t rw15 : 1; // {RW,15} + uint64_t rw14 : 1; // {RW,14} + uint64_t rw13 : 1; // {RW,13} + uint64_t rw12 : 1; // {RW,12} + uint64_t rw11 : 1; // {RW,11} + uint64_t rw10 : 1; // {RW,10} + uint64_t gx : 4; // {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3} + uint64_t gw15 : 1; // {GW,15} + uint64_t gw14 : 1; // {GW,14} + uint64_t gw13 : 1; // {GW,13} + uint64_t gw12 : 1; // {GW,12} + uint64_t gw11 : 1; // {GW,11} + uint64_t gw10 : 1; // {GW,10} + uint64_t bx : 4; // {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3} + uint64_t bw15 : 1; // {BW,15} + uint64_t bw14 : 1; // {BW,14} + uint64_t bw13 : 1; // {BW,13} + uint64_t bw12 : 1; // {BW,12} + uint64_t bw11 : 1; // {BW,11} + uint64_t bw10 : 1; // {BW,10} + uint64_t indices : 63; + }; + static_assert(sizeof(bc6h_mode14) == 16, "Block size must be 16 bytes"); + + bool bSigned = (image.format == DXGI_FORMAT_BC6H_SF16) ? true : false; + + auto m = reinterpret_cast(sptr); + + XMINT3 e0_A(int(m->rw | (m->rw10 << 10) | (m->rw11 << 11) | (m->rw12 << 12) | (m->rw13 << 13) | (m->rw14 << 14) | (m->rw15 << 15)), + int(m->gw | (m->gw10 << 10) | (m->gw11 << 11) | (m->gw12 << 12) | (m->gw13 << 13) | (m->gw14 << 14) | (m->gw15 << 15)), + int(m->bw | (m->bw10 << 10) | (m->bw11 << 11) | (m->bw12 << 12) | (m->bw13 << 13) | (m->bw14 << 14) | (m->bw15 << 15))); + XMINT3 e0_B(int(m->rx), int(m->gx), int(m->bx)); + + if (bSigned) + { + e0_A.x = SIGN_EXTEND(e0_A.x, 16); + e0_A.y = SIGN_EXTEND(e0_A.y, 16); + e0_A.z = SIGN_EXTEND(e0_A.z, 16); + + e0_B.x = SIGN_EXTEND(e0_B.x, 4); + e0_B.y = SIGN_EXTEND(e0_B.y, 4); + e0_B.z = SIGN_EXTEND(e0_B.z, 4); + } + + wprintf(L"\tMode 14 - [16 4]\n"); + wprintf(L"\t E(A): (%04X, %04X, %04X)\n", e0_A.x & 0xFFFF, e0_A.y & 0xFFFF, e0_A.z & 0xFFFF); + wprintf(L"\t E(B): (%04X, %04X, %04X)\n", e0_B.x & 0xFFFF, e0_B.y & 0xFFFF, e0_B.z & 0xFFFF); + wprintf(L"\t Index: "); + PrintIndex4bpp(m->indices, 0, 0); + wprintf(L"\n"); + } + break; + + case 0x13: // Reserved mode (5 bits, 10011) + wprintf(L"\tERROR - Reserved mode 10011\n"); + break; + + case 0x17: // Reserved mode (5 bits, 10111) + wprintf(L"\tERROR - Reserved mode 10011\n"); + break; + + case 0x1B: // Reserved mode (5 bits, 11011) + wprintf(L"\tERROR - Reserved mode 11011\n"); + break; + + case 0x1F: // Reserved mode (5 bits, 11111) + wprintf(L"\tERROR - Reserved mode 11111\n"); + break; + } + break; + } + break; + + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + // http://msdn.microsoft.com/en-us/library/windows/desktop/hh308954.aspx + + if (*sptr & 0x01) + { + // Mode 0 (1) + struct bc7_mode0 + { + uint64_t mode : 1; + uint64_t part : 4; + uint64_t r0 : 4; + uint64_t r1 : 4; + uint64_t r2 : 4; + uint64_t r3 : 4; + uint64_t r4 : 4; + uint64_t r5 : 4; + uint64_t g0 : 4; + uint64_t g1 : 4; + uint64_t g2 : 4; + uint64_t g3 : 4; + uint64_t g4 : 4; + uint64_t g5 : 4; + uint64_t b0 : 4; + uint64_t b1 : 4; + uint64_t b2 : 3; + uint64_t b2n : 1; + uint64_t b3 : 4; + uint64_t b4 : 4; + uint64_t b5 : 4; + uint64_t P0 : 1; + uint64_t P1 : 1; + uint64_t P2 : 1; + uint64_t P3 : 1; + uint64_t P4 : 1; + uint64_t P5 : 1; + uint64_t index : 45; + }; + static_assert(sizeof(bc7_mode0) == 16, "Block size must be 16 bytes"); + + auto m = reinterpret_cast(sptr); + + wprintf(L"\tMode 0 - [4 4 4] partition %I64u\n", m->part); + wprintf(L"\t E0:(%0.3f, %0.3f, %0.3f)\n", float((m->r0 << 1) | m->P0) / 31.f, float((m->g0 << 1) | m->P0) / 31.f, float((m->b0 << 1) | m->P0) / 31.f); + wprintf(L"\t E1:(%0.3f, %0.3f, %0.3f)\n", float((m->r1 << 1) | m->P1) / 31.f, float((m->g1 << 1) | m->P1) / 31.f, float((m->b1 << 1) | m->P1) / 31.f); + wprintf(L"\t E2:(%0.3f, %0.3f, %0.3f)\n", float((m->r2 << 1) | m->P2) / 31.f, float((m->g2 << 1) | m->P2) / 31.f, float(((m->b2 | (m->b2n << 3)) << 1) | m->P2) / 31.f); + wprintf(L"\t E3:(%0.3f, %0.3f, %0.3f)\n", float((m->r3 << 1) | m->P3) / 31.f, float((m->g3 << 1) | m->P3) / 31.f, float((m->b3 << 1) | m->P3) / 31.f); + wprintf(L"\t E4:(%0.3f, %0.3f, %0.3f)\n", float((m->r4 << 1) | m->P4) / 31.f, float((m->g4 << 1) | m->P4) / 31.f, float((m->b4 << 1) | m->P4) / 31.f); + wprintf(L"\t E5:(%0.3f, %0.3f, %0.3f)\n", float((m->r5 << 1) | m->P5) / 31.f, float((m->g5 << 1) | m->P5) / 31.f, float((m->b5 << 1) | m->P5) / 31.f); + wprintf(L"\t Index: "); + PrintIndex2bpp(m->index, 2, m->part); + wprintf(L"\n"); + } + else if (*sptr & 0x02) + { + // Mode 1 (01) + struct bc7_mode1 + { + uint64_t mode : 2; + uint64_t part : 6; + uint64_t r0 : 6; + uint64_t r1 : 6; + uint64_t r2 : 6; + uint64_t r3 : 6; + uint64_t g0 : 6; + uint64_t g1 : 6; + uint64_t g2 : 6; + uint64_t g3 : 6; + uint64_t b0 : 6; + uint64_t b1 : 2; + uint64_t b1n : 4; + uint64_t b2 : 6; + uint64_t b3 : 6; + uint64_t P0 : 1; + uint64_t P1 : 1; + uint64_t index : 46; + }; + static_assert(sizeof(bc7_mode1) == 16, "Block size must be 16 bytes"); + + auto m = reinterpret_cast(sptr); + + wprintf(L"\tMode 1 - [6 6 6] partition %I64u\n", m->part); + wprintf(L"\t E0:(%0.3f, %0.3f, %0.3f)\n", float((m->r0 << 1) | m->P0) / 127.f, float((m->g0 << 1) | m->P0) / 127.f, float((m->b0 << 1) | m->P0) / 127.f); + wprintf(L"\t E1:(%0.3f, %0.3f, %0.3f)\n", float((m->r1 << 1) | m->P0) / 127.f, float((m->g1 << 1) | m->P0) / 127.f, float(((m->b1 | (m->b1n << 2)) << 1) | m->P0) / 127.f); + wprintf(L"\t E2:(%0.3f, %0.3f, %0.3f)\n", float((m->r2 << 1) | m->P1) / 127.f, float((m->g2 << 1) | m->P1) / 127.f, float((m->b2 << 1) | m->P1) / 127.f); + wprintf(L"\t E3:(%0.3f, %0.3f, %0.3f)\n", float((m->r3 << 1) | m->P1) / 127.f, float((m->g3 << 1) | m->P1) / 127.f, float((m->b3 << 1) | m->P1) / 127.f); + wprintf(L"\t Index: "); + PrintIndex3bpp(m->index, 1, m->part); + wprintf(L"\n"); + } + else if (*sptr & 0x04) + { + // Mode 2 (001) + struct bc7_mode2 + { + uint64_t mode : 3; + uint64_t part : 6; + uint64_t r0 : 5; + uint64_t r1 : 5; + uint64_t r2 : 5; + uint64_t r3 : 5; + uint64_t r4 : 5; + uint64_t r5 : 5; + uint64_t g0 : 5; + uint64_t g1 : 5; + uint64_t g2 : 5; + uint64_t g3 : 5; + uint64_t g4 : 5; + uint64_t g5 : 5; + uint64_t b0 : 5; + uint64_t b1 : 5; + uint64_t b2 : 5; + uint64_t b3 : 5; + uint64_t b4 : 5; + uint64_t b5 : 5; + uint64_t index : 29; + }; + static_assert(sizeof(bc7_mode2) == 16, "Block size must be 16 bytes"); + + auto m = reinterpret_cast(sptr); + + wprintf(L"\tMode 2 - [5 5 5] partition %I64u\n", m->part); + wprintf(L"\t E0:(%0.3f, %0.3f, %0.3f)\n", float(m->r0) / 31.f, float(m->g0) / 31.f, float(m->b0) / 31.f); + wprintf(L"\t E1:(%0.3f, %0.3f, %0.3f)\n", float(m->r1) / 31.f, float(m->g1) / 31.f, float(m->b1) / 31.f); + wprintf(L"\t E2:(%0.3f, %0.3f, %0.3f)\n", float(m->r2) / 31.f, float(m->g2) / 31.f, float(m->b2) / 31.f); + wprintf(L"\t E3:(%0.3f, %0.3f, %0.3f)\n", float(m->r3) / 31.f, float(m->g3) / 31.f, float(m->b3) / 31.f); + wprintf(L"\t E4:(%0.3f, %0.3f, %0.3f)\n", float(m->r4) / 31.f, float(m->g4) / 31.f, float(m->b4) / 31.f); + wprintf(L"\t E5:(%0.3f, %0.3f, %0.3f)\n", float(m->r5) / 31.f, float(m->g5) / 31.f, float(m->b5) / 31.f); + wprintf(L"\t Index: "); + PrintIndex2bpp(m->index, 2, m->part); + wprintf(L"\n"); + } + else if (*sptr & 0x08) + { + // Mode 3 (0001) + struct bc7_mode3 + { + uint64_t mode : 4; + uint64_t part : 6; + uint64_t r0 : 7; + uint64_t r1 : 7; + uint64_t r2 : 7; + uint64_t r3 : 7; + uint64_t g0 : 7; + uint64_t g1 : 7; + uint64_t g2 : 7; + uint64_t g3 : 5; + uint64_t g3n : 2; + uint64_t b0 : 7; + uint64_t b1 : 7; + uint64_t b2 : 7; + uint64_t b3 : 7; + uint64_t P0 : 1; + uint64_t P1 : 1; + uint64_t P2 : 1; + uint64_t P3 : 1; + uint64_t index : 30; + }; + static_assert(sizeof(bc7_mode3) == 16, "Block size must be 16 bytes"); + + auto m = reinterpret_cast(sptr); + + wprintf(L"\tMode 3 - [7 7 7] partition %I64u\n", m->part); + wprintf(L"\t E0:(%0.3f, %0.3f, %0.3f)\n", float((m->r0 << 1) | m->P0) / 255.f, float((m->g0 << 1) | m->P0) / 255.f, float((m->b0 << 1) | m->P0) / 255.f); + wprintf(L"\t E1:(%0.3f, %0.3f, %0.3f)\n", float((m->r1 << 1) | m->P1) / 255.f, float((m->g1 << 1) | m->P1) / 255.f, float((m->b1 << 1) | m->P1) / 255.f); + wprintf(L"\t E2:(%0.3f, %0.3f, %0.3f)\n", float((m->r2 << 1) | m->P2) / 255.f, float((m->g2 << 1) | m->P2) / 255.f, float((m->b2 << 1) | m->P2) / 255.f); + wprintf(L"\t E3:(%0.3f, %0.3f, %0.3f)\n", float((m->r3 << 1) | m->P3) / 255.f, float(((m->g3 | (m->g3n << 5)) << 1) | m->P3) / 255.f, float((m->b3 << 1) | m->P3) / 255.f); + wprintf(L"\t Index: "); + PrintIndex2bpp(m->index, 1, m->part); + wprintf(L"\n"); + } + else if (*sptr & 0x10) + { + // Mode 4 (00001) + struct bc7_mode4 + { + uint64_t mode : 5; + uint64_t rot : 2; + uint64_t idx : 1; + uint64_t r0 : 5; + uint64_t r1 : 5; + uint64_t g0 : 5; + uint64_t g1 : 5; + uint64_t b0 : 5; + uint64_t b1 : 5; + uint64_t a0 : 6; + uint64_t a1 : 6; + uint64_t color_index : 14; + uint64_t color_indexn : 17; + uint64_t alpha_index : 47; + }; + static_assert(sizeof(bc7_mode4) == 16, "Block size must be 16 bytes"); + + auto m = reinterpret_cast(sptr); + + wprintf(L"\tMode 4 - [5 5 5 A6] indx mode %ls, rot-bits %I64u%ls\n", m->idx ? L"3-bit" : L"2-bit", m->rot, GetRotBits(m->rot)); + wprintf(L"\t C0:(%0.3f, %0.3f, %0.3f)\n", float(m->r0) / 31.f, float(m->g0) / 31.f, float(m->b0) / 31.f); + wprintf(L"\t C1:(%0.3f, %0.3f, %0.3f)\n", float(m->r1) / 31.f, float(m->g1) / 31.f, float(m->b1) / 31.f); + wprintf(L"\t A0:(%0.3f)\n", float(m->a0) / 63.f); + wprintf(L"\t A1:(%0.3f)\n", float(m->a1) / 63.f); + wprintf(L"\t Colors: "); + + uint64_t color_index = m->color_index | (m->color_indexn << 14); + if (m->idx) + PrintIndex3bpp(color_index, 0, 0); + else + PrintIndex2bpp(color_index, 0, 0); + wprintf(L"\n"); + wprintf(L"\t Alpha: "); + PrintIndex3bpp(m->alpha_index, 0, 0); + wprintf(L"\n"); + } + else if (*sptr & 0x20) + { + // Mode 5 (000001) + struct bc7_mode5 + { + uint64_t mode : 6; + uint64_t rot : 2; + uint64_t r0 : 7; + uint64_t r1 : 7; + uint64_t g0 : 7; + uint64_t g1 : 7; + uint64_t b0 : 7; + uint64_t b1 : 7; + uint64_t a0 : 8; + uint64_t a1 : 6; + uint64_t a1n : 2; + uint64_t color_index : 31; + uint64_t alpha_index : 31; + }; + static_assert(sizeof(bc7_mode5) == 16, "Block size must be 16 bytes"); + + auto m = reinterpret_cast(sptr); + + wprintf(L"\tMode 5 - [7 7 7 A8] rot-bits %I64u%ls\n", m->rot, GetRotBits(m->rot)); + wprintf(L"\t C0:(%0.3f, %0.3f, %0.3f)\n", float(m->r0) / 127.f, float(m->g0) / 127.f, float(m->b0) / 127.f); + wprintf(L"\t C1:(%0.3f, %0.3f, %0.3f)\n", float(m->r1) / 127.f, float(m->g1) / 127.f, float(m->b1) / 127.f); + wprintf(L"\t A0:(%0.3f)\n", float(m->a0) / 255.f); + wprintf(L"\t A1:(%0.3f)\n", float(m->a1 | (m->a1n << 6)) / 255.f); + wprintf(L"\t Colors: "); + PrintIndex2bpp(m->color_index, 0, 0); + wprintf(L"\n"); + wprintf(L"\t Alpha: "); + PrintIndex2bpp(m->alpha_index, 0, 0); + wprintf(L"\n"); + } + else if (*sptr & 0x40) + { + // Mode 6 (0000001) + struct bc7_mode6 + { + uint64_t mode : 7; + uint64_t r0 : 7; + uint64_t r1 : 7; + uint64_t g0 : 7; + uint64_t g1 : 7; + uint64_t b0 : 7; + uint64_t b1 : 7; + uint64_t a0 : 7; + uint64_t a1 : 7; + uint64_t P0 : 1; + uint64_t P1 : 1; + uint64_t index : 63; + + }; + static_assert(sizeof(bc7_mode6) == 16, "Block size must be 16 bytes"); + + auto m = reinterpret_cast(sptr); + + wprintf(L"\tMode 6 - [7 7 7 A7]\n"); + wprintf(L"\t C0:(%0.3f, %0.3f, %0.3f)\n", float((m->r0 << 1) | m->P0) / 255.f, float((m->g0 << 1) | m->P0) / 255.f, float((m->b0 << 1) | m->P0) / 255.f); + wprintf(L"\t C1:(%0.3f, %0.3f, %0.3f)\n", float((m->r1 << 1) | m->P1) / 255.f, float((m->g1 << 1) | m->P1) / 255.f, float((m->b1 << 1) | m->P1) / 255.f); + wprintf(L"\t A0:(%0.3f)\n", float((m->a0 << 1) | m->P0) / 255.f); + wprintf(L"\t A1:(%0.3f)\n", float((m->a1 << 1) | m->P1) / 255.f); + wprintf(L"\t Index: "); + PrintIndex4bpp(m->index, 0, 0); + wprintf(L"\n"); + } + else if (*sptr & 0x80) + { + // Mode 7 (00000001) + struct bc7_mode7 + { + uint64_t mode : 8; + uint64_t part : 6; + uint64_t r0 : 5; + uint64_t r1 : 5; + uint64_t r2 : 5; + uint64_t r3 : 5; + uint64_t g0 : 5; + uint64_t g1 : 5; + uint64_t g2 : 5; + uint64_t g3 : 5; + uint64_t b0 : 5; + uint64_t b1 : 5; + uint64_t b2 : 5; + uint64_t b3 : 5; + uint64_t a0 : 5; + uint64_t a1 : 5; + uint64_t a2 : 5; + uint64_t a3 : 5; + uint64_t P0 : 1; + uint64_t P1 : 1; + uint64_t P2 : 1; + uint64_t P3 : 1; + uint64_t index : 30; + + }; + static_assert(sizeof(bc7_mode7) == 16, "Block size must be 16 bytes"); + + auto m = reinterpret_cast(sptr); + + wprintf(L"\tMode 7 - [5 5 5 A5] partition %I64u\n", m->part); + wprintf(L"\t C0:(%0.3f, %0.3f, %0.3f)\n", float((m->r0 << 1) | m->P0) / 63.f, float((m->g0 << 1) | m->P0) / 63.f, float((m->b0 << 1) | m->P0) / 63.f); + wprintf(L"\t C1:(%0.3f, %0.3f, %0.3f)\n", float((m->r1 << 1) | m->P1) / 63.f, float((m->g1 << 1) | m->P1) / 63.f, float((m->b1 << 1) | m->P1) / 63.f); + wprintf(L"\t C2:(%0.3f, %0.3f, %0.3f)\n", float((m->r2 << 1) | m->P2) / 63.f, float((m->g2 << 1) | m->P2) / 63.f, float((m->b2 << 1) | m->P2) / 63.f); + wprintf(L"\t C3:(%0.3f, %0.3f, %0.3f)\n", float((m->r3 << 1) | m->P3) / 63.f, float((m->g3 << 1) | m->P3) / 63.f, float((m->b3 << 1) | m->P3) / 63.f); + wprintf(L"\t A0:(%0.3f)\n", float((m->a0 << 1) | m->P0) / 63.f); + wprintf(L"\t A1:(%0.3f)\n", float((m->a1 << 1) | m->P1) / 63.f); + wprintf(L"\t A2:(%0.3f)\n", float((m->a2 << 1) | m->P2) / 63.f); + wprintf(L"\t A3:(%0.3f)\n", float((m->a3 << 1) | m->P3) / 63.f); + wprintf(L"\t Index: "); + PrintIndex4bpp(m->index, 1, m->part); + wprintf(L"\n"); + } + else + { + // Reserved mode 8 (00000000) + wprintf(L"\tERROR - Reserved mode 8\n"); + } + break; + } + } + } + + return S_OK; + } +} + + +//-------------------------------------------------------------------------------------- +// Entry-point +//-------------------------------------------------------------------------------------- +#pragma prefast(disable : 28198, "Command-line tool, frees all memory on exit") + +int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) +{ + // Parameters and defaults + DWORD dwFilter = TEX_FILTER_DEFAULT; + int pixelx = -1; + int pixely = -1; + + // Initialize COM (needed for WIC) + HRESULT hr = hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + if (FAILED(hr)) + { + wprintf(L"Failed to initialize COM (%08X)\n", hr); + return 1; + } + + // Process command line + if (argc < 2) + { + PrintUsage(); + return 0; + } + + DWORD dwCommand = LookupByName(argv[1], g_pCommands); + switch (dwCommand) + { + case CMD_INFO: + case CMD_ANALYZE: + case CMD_COMPARE: + case CMD_DUMPBC: + break; + + default: + wprintf(L"Must use one of: info, analyze, compare, or dumpbc\n\n"); + return 1; + } + + DWORD dwOptions = 0; + std::list conversion; + + for (int iArg = 2; iArg < argc; iArg++) + { + PWSTR pArg = argv[iArg]; + + if (('-' == pArg[0]) || ('/' == pArg[0])) + { + pArg++; + PWSTR pValue; + + for (pValue = pArg; *pValue && (':' != *pValue); pValue++); + + if (*pValue) + *pValue++ = 0; + + DWORD dwOption = LookupByName(pArg, g_pOptions); + + if (!dwOption || (dwOptions & (1 << dwOption))) + { + PrintUsage(); + return 1; + } + + dwOptions |= 1 << dwOption; + + // Handle options with additional value parameter + switch (dwOption) + { + case OPT_FILTER: + case OPT_TARGET_PIXELX: + case OPT_TARGET_PIXELY: + if (!*pValue) + { + if ((iArg + 1 >= argc)) + { + PrintUsage(); + return 1; + } + + iArg++; + pValue = argv[iArg]; + } + break; + } + + switch (dwOption) + { + case OPT_FILTER: + dwFilter = LookupByName(pValue, g_pFilters); + if (!dwFilter) + { + wprintf(L"Invalid value specified with -if (%ls)\n", pValue); + return 1; + } + break; + + case OPT_TARGET_PIXELX: + if (swscanf_s(pValue, L"%d", &pixelx) != 1) + { + wprintf(L"Invalid value for pixel x location (%ls)\n", pValue); + return 1; + } + break; + + case OPT_TARGET_PIXELY: + if (swscanf_s(pValue, L"%d", &pixely) != 1) + { + wprintf(L"Invalid value for pixel y location (%ls)\n", pValue); + return 1; + } + break; + } + } + else if (wcspbrk(pArg, L"?*") != nullptr) + { + size_t count = conversion.size(); + SearchForFiles(pArg, conversion, (dwOptions & (1 << OPT_RECURSIVE)) != 0); + if (conversion.size() <= count) + { + wprintf(L"No matching files found for %ls\n", pArg); + return 1; + } + } + else + { + SConversion conv; + wcscpy_s(conv.szSrc, MAX_PATH, pArg); + + conversion.push_back(conv); + } + } + + if (conversion.empty()) + { + PrintUsage(); + return 0; + } + + if (~dwOptions & (1 << OPT_NOLOGO)) + PrintLogo(); + + switch (dwCommand) + { + case CMD_COMPARE: + // --- Compare ----------------------------------------------------------------- + if (conversion.size() != 2) + { + wprintf(L"ERROR: compare needs excatly two images\n"); + return 1; + } + else + { + auto pImage1 = conversion.cbegin(); + + wprintf(L"1: %ls", pImage1->szSrc); + fflush(stdout); + + TexMetadata info1; + std::unique_ptr image1; + hr = LoadImage(pImage1->szSrc, dwOptions, dwFilter, info1, image1); + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + return 1; + } + + auto pImage2 = conversion.cbegin(); + std::advance(pImage2, 1); + + wprintf(L"\n2: %ls", pImage2->szSrc); + fflush(stdout); + + TexMetadata info2; + std::unique_ptr image2; + hr = LoadImage(pImage2->szSrc, dwOptions, dwFilter, info2, image2); + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + return 1; + } + + wprintf(L"\n"); + fflush(stdout); + + if (info1.height != info2.height + || info1.width != info2.width) + { + wprintf(L"ERROR: Can only compare images of the same width & height\n"); + return 1; + } + + if ((info1.depth == 1 + && info1.arraySize == 1 + && info1.mipLevels == 1) + || info1.depth != info2.depth + || info1.arraySize != info2.arraySize + || info1.mipLevels != info2.mipLevels + || image1->GetImageCount() != image2->GetImageCount()) + { + // Compare single image + if (image1->GetImageCount() > 1 || image2->GetImageCount() > 1) + wprintf(L"WARNING: ignoring all images but first one in each file\n"); + + float mse, mseV[4]; + hr = ComputeMSE(*image1->GetImage(0, 0, 0), *image2->GetImage(0, 0, 0), mse, mseV); + if (FAILED(hr)) + { + wprintf(L"Failed comparing images (%08X)\n", hr); + return 1; + } + + wprintf(L"Result: %f (%f %f %f %f) PSNR %f dB\n", mse, mseV[0], mseV[1], mseV[2], mseV[3], + 10.f * log10f(3.f / (mseV[0] + mseV[1] + mseV[2]))); + } + else + { + // Compare all images + float min_mse = FLT_MAX; + float min_mseV[4] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX }; + + float max_mse = -FLT_MAX; + float max_mseV[4] = { -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX }; + + double sum_mse = 0; + double sum_mseV[4] = { 0, 0, 0, 0 }; + + size_t total_images = 0; + + if (info1.depth > 1) + { + wprintf(L"Results by mip (%3Iu) and slice (%3Iu)\n\n", info1.mipLevels, info1.depth); + + size_t depth = info1.depth; + for (size_t mip = 0; mip < info1.mipLevels; ++mip) + { + for (size_t slice = 0; slice < depth; ++slice) + { + const Image* img1 = image1->GetImage(mip, 0, slice); + const Image* img2 = image2->GetImage(mip, 0, slice); + + if (!img1 + || !img2 + || img1->height != img2->height + || img1->width != img2->width) + { + wprintf(L"ERROR: Unexpected mismatch at slice %3Iu, mip %3Iu\n", slice, mip); + return 1; + } + else + { + float mse, mseV[4]; + hr = ComputeMSE(*img1, *img2, mse, mseV); + if (FAILED(hr)) + { + wprintf(L"Failed comparing images at slice %3Iu, mip %3Iu (%08X)\n", slice, mip, hr); + return 1; + } + + min_mse = std::min(min_mse, mse); + max_mse = std::max(max_mse, mse); + sum_mse += mse; + + for (size_t j = 0; j < 4; ++j) + { + min_mseV[j] = std::min(min_mseV[j], mseV[j]); + max_mseV[j] = std::max(max_mseV[j], mseV[j]); + sum_mseV[j] += mseV[j]; + } + + ++total_images; + + wprintf(L"[%3Iu,%3Iu]: %f (%f %f %f %f) PSNR %f dB\n", mip, slice, mse, mseV[0], mseV[1], mseV[2], mseV[3], + 10.f * log10f(3.f / (mseV[0] + mseV[1] + mseV[2]))); + } + } + + if (depth > 1) + depth >>= 1; + } + } + else + { + wprintf(L"Results by item (%3Iu) and mip (%3Iu)\n\n", info1.arraySize, info1.mipLevels); + + for (size_t item = 0; item < info1.arraySize; ++item) + { + for (size_t mip = 0; mip < info1.mipLevels; ++mip) + { + const Image* img1 = image1->GetImage(mip, item, 0); + const Image* img2 = image2->GetImage(mip, item, 0); + + if (!img1 + || !img2 + || img1->height != img2->height + || img1->width != img2->width) + { + wprintf(L"ERROR: Unexpected mismatch at item %3Iu, mip %3Iu\n", item, mip); + return 1; + } + else + { + float mse, mseV[4]; + hr = ComputeMSE(*img1, *img2, mse, mseV); + if (FAILED(hr)) + { + wprintf(L"Failed comparing images at item %3Iu, mip %3Iu (%08X)\n", item, mip, hr); + return 1; + } + + min_mse = std::min(min_mse, mse); + max_mse = std::max(max_mse, mse); + sum_mse += mse; + + for (size_t j = 0; j < 4; ++j) + { + min_mseV[j] = std::min(min_mseV[j], mseV[j]); + max_mseV[j] = std::max(max_mseV[j], mseV[j]); + sum_mseV[j] += mseV[j]; + } + + ++total_images; + + wprintf(L"[%3Iu,%3Iu]: %f (%f %f %f %f) PSNR %f dB\n", item, mip, mse, mseV[0], mseV[1], mseV[2], mseV[3], + 10.f * log10f(3.f / (mseV[0] + mseV[1] + mseV[2]))); + } + } + } + } + + // Output multi-image stats + if (total_images > 1) + { + wprintf(L"\n Minimum MSE: %f (%f %f %f %f) PSNR %f dB\n", min_mse, min_mseV[0], min_mseV[1], min_mseV[2], min_mseV[3], + 10.f * log10f(3.f / (min_mseV[0] + min_mseV[1] + min_mseV[2]))); + double total_mseV0 = sum_mseV[0] / double(total_images); + double total_mseV1 = sum_mseV[1] / double(total_images); + double total_mseV2 = max_mseV[2] / double(total_images); + wprintf(L" Average MSE: %f (%f %f %f %f) PSNR %f dB\n", sum_mse / double(total_images), + total_mseV0, + total_mseV1, + total_mseV2, + sum_mseV[3] / double(total_images), + 10.0 * log10(3.0 / (total_mseV0 + total_mseV1 + total_mseV2))); + wprintf(L" Maximum MSE: %f (%f %f %f %f) PSNR %f dB\n", max_mse, max_mseV[0], max_mseV[1], max_mseV[2], max_mseV[3], + 10.f * log10f(3.f / (max_mseV[0] + max_mseV[1] + max_mseV[2]))); + } + } + } + break; + + default: + for (auto pConv = conversion.cbegin(); pConv != conversion.cend(); ++pConv) + { + // Load source image + if (pConv != conversion.begin()) + wprintf(L"\n"); + + wprintf(L"%ls", pConv->szSrc); + fflush(stdout); + + TexMetadata info; + std::unique_ptr image; + hr = LoadImage(pConv->szSrc, dwOptions, dwFilter, info, image); + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + return 1; + } + + wprintf(L"\n"); + fflush(stdout); + + if (dwCommand == CMD_INFO) + { + // --- Info ---------------------------------------------------------------- + wprintf(L" width = %Iu\n", info.width); + wprintf(L" height = %Iu\n", info.height); + wprintf(L" depth = %Iu\n", info.depth); + wprintf(L" mipLevels = %Iu\n", info.mipLevels); + wprintf(L" arraySize = %Iu\n", info.arraySize); + wprintf(L" format = "); + PrintFormat(info.format); + wprintf(L"\n dimension = "); + switch (info.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + wprintf((info.arraySize > 1) ? L"1DArray\n" : L"1D\n"); + break; + + case TEX_DIMENSION_TEXTURE2D: + if (info.IsCubemap()) + { + wprintf((info.arraySize > 6) ? L"CubeArray\n" : L"Cube\n"); + } + else + { + wprintf((info.arraySize > 1) ? L"2DArray\n" : L"2D\n"); + } + break; + + case TEX_DIMENSION_TEXTURE3D: + wprintf(L" 3D"); + break; + } + + wprintf(L" alpha mode = "); + switch (info.GetAlphaMode()) + { + case TEX_ALPHA_MODE_OPAQUE: + wprintf(L"Opaque"); + break; + case TEX_ALPHA_MODE_PREMULTIPLIED: + wprintf(L"Premultiplied"); + break; + case TEX_ALPHA_MODE_STRAIGHT: + wprintf(L"Straight"); + break; + default: + wprintf(L"Unknown"); + break; + } + + wprintf(L"\n images = %Iu\n", image->GetImageCount()); + + auto sizeInKb = static_cast(image->GetPixelsSize() / 1024); + + wprintf(L" pixel size = %Iu (KB)\n\n", sizeInKb); + } + else if (dwCommand == CMD_DUMPBC) + { + // --- Dump BC ------------------------------------------------------------- + if (!IsCompressed(info.format)) + { + wprintf(L"ERROR: dumpbc only operates on BC format DDS files\n"); + return 1; + } + + if (pixelx >= (int)info.width + || pixely >= (int)info.height) + { + wprintf(L"WARNING: Specified pixel location (%d x %d) is out of range for image (%Iu x %Iu)\n", pixelx, pixely, info.width, info.height); + continue; + } + + wprintf(L"Compression: "); + PrintFormat(info.format); + wprintf(L"\n"); + + if (info.depth > 1) + { + wprintf(L"Results by mip (%3Iu) and slice (%3Iu)\n", info.mipLevels, info.depth); + + size_t depth = info.depth; + for (size_t mip = 0; mip < info.mipLevels; ++mip) + { + for (size_t slice = 0; slice < depth; ++slice) + { + const Image* img = image->GetImage(mip, 0, slice); + + if (!img) + { + wprintf(L"ERROR: Unexpected error at slice %3Iu, mip %3Iu\n", slice, mip); + return 1; + } + else + { + wprintf(L"\n[%3Iu, %3Iu]:\n", mip, slice); + + hr = DumpBCImage(*img, pixelx, pixely); + if (FAILED(hr)) + { + wprintf(L"ERROR: Failed dumping image at slice %3Iu, mip %3Iu (%08X)\n", slice, mip, hr); + return 1; + } + } + } + + if (depth > 1) + depth >>= 1; + + if (pixelx > 0) + pixelx >>= 1; + + if (pixely > 0) + pixely >>= 1; + } + } + else + { + wprintf(L"Results by item (%3Iu) and mip (%3Iu)\n", info.arraySize, info.mipLevels); + + for (size_t item = 0; item < info.arraySize; ++item) + { + int tpixelx = pixelx; + int tpixely = pixely; + + for (size_t mip = 0; mip < info.mipLevels; ++mip) + { + const Image* img = image->GetImage(mip, item, 0); + + if (!img) + { + wprintf(L"ERROR: Unexpected error at item %3Iu, mip %3Iu\n", item, mip); + return 1; + } + else + { + if (image->GetImageCount() > 1) + { + wprintf(L"\n[%3Iu, %3Iu]:\n", item, mip); + } + hr = DumpBCImage(*img, tpixelx, tpixely); + if (FAILED(hr)) + { + wprintf(L"ERROR: Failed dumping image at item %3Iu, mip %3Iu (%08X)\n", item, mip, hr); + return 1; + } + } + + if (tpixelx > 0) + tpixelx >>= 1; + + if (tpixely > 0) + tpixely >>= 1; + } + } + } + } + else + { + // --- Analyze ------------------------------------------------------------- + if (IsPlanar(info.format)) + { + auto img = image->GetImage(0, 0, 0); + assert(img); + size_t nimg = image->GetImageCount(); + + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + hr = ConvertToSinglePlane(img, nimg, info, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [converttosingleplane] (%x)\n", hr); + continue; + } + + auto& tinfo = timage->GetMetadata(); + + info.format = tinfo.format; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + } + + if (info.depth > 1) + { + wprintf(L"Results by mip (%3Iu) and slice (%3Iu)\n\n", info.mipLevels, info.depth); + + size_t depth = info.depth; + for (size_t mip = 0; mip < info.mipLevels; ++mip) + { + for (size_t slice = 0; slice < depth; ++slice) + { + const Image* img = image->GetImage(mip, 0, slice); + + if (!img) + { + wprintf(L"ERROR: Unexpected error at slice %3Iu, mip %3Iu\n", slice, mip); + return 1; + } + else + { + AnalyzeData data; + hr = Analyze(*img, data); + if (FAILED(hr)) + { + wprintf(L"ERROR: Failed analyzing image at slice %3Iu, mip %3Iu (%08X)\n", slice, mip, hr); + return 1; + } + + wprintf(L"Result slice %3Iu, mip %3Iu:\n", slice, mip); + data.Print(); + } + + if (IsCompressed(info.format)) + { + AnalyzeBCData data; + hr = AnalyzeBC(*img, data); + if (FAILED(hr)) + { + wprintf(L"ERROR: Failed analyzing BC image at slice %3Iu, mip %3Iu (%08X)\n", slice, mip, hr); + return 1; + } + + data.Print(img->format); + } + wprintf(L"\n"); + } + + if (depth > 1) + depth >>= 1; + } + } + else + { + wprintf(L"Results by item (%3Iu) and mip (%3Iu)\n\n", info.arraySize, info.mipLevels); + + for (size_t item = 0; item < info.arraySize; ++item) + { + for (size_t mip = 0; mip < info.mipLevels; ++mip) + { + const Image* img = image->GetImage(mip, item, 0); + + if (!img) + { + wprintf(L"ERROR: Unexpected error at item %3Iu, mip %3Iu\n", item, mip); + return 1; + } + else + { + AnalyzeData data; + hr = Analyze(*img, data); + if (FAILED(hr)) + { + wprintf(L"ERROR: Failed analyzing image at item %3Iu, mip %3Iu (%08X)\n", item, mip, hr); + return 1; + } + + if (image->GetImageCount() > 1) + { + wprintf(L"Result item %3Iu, mip %3Iu:\n", item, mip); + } + data.Print(); + } + + if (IsCompressed(info.format)) + { + AnalyzeBCData data; + hr = AnalyzeBC(*img, data); + if (FAILED(hr)) + { + wprintf(L"ERROR: Failed analyzing BC image at item %3Iu, mip %3Iu (%08X)\n", item, mip, hr); + return 1; + } + + data.Print(img->format); + } + wprintf(L"\n"); + } + } + } + } + } + break; + } + + return 0; +} diff --git a/Texdiag/texdiag.rc b/Texdiag/texdiag.rc new file mode 100644 index 0000000..5208ce0 --- /dev/null +++ b/Texdiag/texdiag.rc @@ -0,0 +1,76 @@ +// Microsoft Visual C++ generated resource script. +// +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define IDC_STATIC -1 +#include + + + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN_ICON ICON "directx.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define IDC_STATIC -1\r\n" + "#include \r\n" + "\r\n" + "\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Texdiag/texdiag_Desktop_2013.vcxproj b/Texdiag/texdiag_Desktop_2013.vcxproj new file mode 100644 index 0000000..7ef793d --- /dev/null +++ b/Texdiag/texdiag_Desktop_2013.vcxproj @@ -0,0 +1,407 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Profile + Win32 + + + Profile + x64 + + + Release + Win32 + + + Release + x64 + + + + texdiag + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D} + texdiag + Win32Proj + $(VCTargetsPath11) + + + + Application + Unicode + v120 + + + Application + Unicode + v120 + + + Application + true + Unicode + v120 + + + Application + true + Unicode + v120 + + + Application + true + Unicode + v120 + + + Application + true + Unicode + v120 + + + + + + + + + + + + + + + + + + + + + + + + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + texdiag + true + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + texdiag + true + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + texdiag + false + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + texdiag + false + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + texdiag + false + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + Bin\Desktop_2013\$(Platform)\$(Configuration)\ + texdiag + false + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + + Level4 + Disabled + MultiThreadedDebugDLL + false + true + Fast + StreamingSIMDExtensions2 + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;_DEBUG;DEBUG;PROFILE;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + EditAndContinue + EnableFastChecks + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + Console + true + true + true + true + MachineX86 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + Disabled + MultiThreadedDebugDLL + false + true + Fast + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;_DEBUG;DEBUG;PROFILE;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + EnableFastChecks + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + Console + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + MaxSpeed + MultiThreadedDLL + false + true + true + Fast + StreamingSIMDExtensions2 + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;NDEBUG;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + true + Console + true + true + true + true + true + MachineX86 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + MaxSpeed + MultiThreadedDLL + false + true + true + Fast + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;NDEBUG;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + true + Console + true + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + MaxSpeed + MultiThreadedDLL + false + true + true + Fast + StreamingSIMDExtensions2 + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;NDEBUG;PROFILE;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + true + Console + true + true + true + true + true + MachineX86 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + MaxSpeed + MultiThreadedDLL + false + true + true + Fast + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;NDEBUG;PROFILE;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + true + Console + true + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + + + + + + + {371b9fa9-4c90-4ac6-a123-aced756d6c77} + + + + + + + \ No newline at end of file diff --git a/Texdiag/texdiag_Desktop_2013.vcxproj.filters b/Texdiag/texdiag_Desktop_2013.vcxproj.filters new file mode 100644 index 0000000..3a2f907 --- /dev/null +++ b/Texdiag/texdiag_Desktop_2013.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {8e114980-c1a3-4ada-ad7c-83caadf5daeb} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + + + + Resource Files + + + \ No newline at end of file diff --git a/Texdiag/texdiag_Desktop_2015.vcxproj b/Texdiag/texdiag_Desktop_2015.vcxproj new file mode 100644 index 0000000..83e5f78 --- /dev/null +++ b/Texdiag/texdiag_Desktop_2015.vcxproj @@ -0,0 +1,406 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Profile + Win32 + + + Profile + x64 + + + Release + Win32 + + + Release + x64 + + + + texdiag + {8E31A619-F4F8-413F-A973-4EE37B1AAA5D} + texdiag + Win32Proj + + + + Application + Unicode + v140 + + + Application + Unicode + v140 + + + Application + true + Unicode + v140 + + + Application + true + Unicode + v140 + + + Application + true + Unicode + v140 + + + Application + true + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + texdiag + true + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + texdiag + true + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + texdiag + false + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + texdiag + false + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + texdiag + false + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + Bin\Desktop_2015\$(Platform)\$(Configuration)\ + texdiag + false + true + $(ExecutablePath) + $(IncludePath) + $(LibraryPath) + + + + Level4 + Disabled + MultiThreadedDebugDLL + false + true + Fast + StreamingSIMDExtensions2 + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;_DEBUG;DEBUG;PROFILE;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + EditAndContinue + EnableFastChecks + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + Console + true + true + true + true + MachineX86 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + Disabled + MultiThreadedDebugDLL + false + true + Fast + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;_DEBUG;DEBUG;PROFILE;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + EnableFastChecks + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + Console + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + MaxSpeed + MultiThreadedDLL + false + true + true + Fast + StreamingSIMDExtensions2 + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;NDEBUG;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + true + Console + true + true + true + true + true + MachineX86 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + MaxSpeed + MultiThreadedDLL + false + true + true + Fast + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;NDEBUG;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + true + Console + true + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + MaxSpeed + MultiThreadedDLL + false + true + true + Fast + StreamingSIMDExtensions2 + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;NDEBUG;PROFILE;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + true + Console + true + true + true + true + true + MachineX86 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + Level4 + MaxSpeed + MultiThreadedDLL + false + true + true + Fast + Sync + ..\DirectXTex;%(AdditionalIncludeDirectories) + %(AdditionalOptions) + WIN32;NDEBUG;PROFILE;_CONSOLE;D3DXFX_LARGEADDRESS_HANDLE;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + + %(AdditionalOptions) + ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies) + true + Console + true + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + + + + + + + {371b9fa9-4c90-4ac6-a123-aced756d6c77} + + + + + + + \ No newline at end of file diff --git a/Texdiag/texdiag_Desktop_2015.vcxproj.filters b/Texdiag/texdiag_Desktop_2015.vcxproj.filters new file mode 100644 index 0000000..3a2f907 --- /dev/null +++ b/Texdiag/texdiag_Desktop_2015.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {8e114980-c1a3-4ada-ad7c-83caadf5daeb} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + + + + Resource Files + + + \ No newline at end of file