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 0000000..bc43c1b Binary files /dev/null and b/Texdiag/directx.ico differ diff --git a/Texdiag/texdiag.cpp b/Texdiag/texdiag.cpp new file mode 100644 index 0000000..5861313 --- /dev/null +++ b/Texdiag/texdiag.cpp @@ -0,0 +1,3399 @@ +//-------------------------------------------------------------------------------------- +// File: Texdiag.cpp +// +// DirectX Texture diagnostic tool +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma warning(push) +#pragma warning(disable : 4005) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NODRAWTEXT +#define NOGDI +#define NOBITMAP +#define NOMCX +#define NOSERVICE +#define NOHELP +#pragma warning(pop) + +#include +#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