texconv: Added support for DXT5nm and RXGB DXT5 format variants (#362)
This commit is contained in:
Родитель
2395b804ff
Коммит
a2a4ffd33c
|
@ -221,6 +221,9 @@ namespace DirectX
|
|||
DDS_FLAGS_FORCE_DX9_LEGACY = 0x40000,
|
||||
// Force use of legacy header for DDS writer (will fail if unable to write as such)
|
||||
|
||||
DDS_FLAGS_FORCE_DXT5_RXGB = 0x80000,
|
||||
// Force use of 'RXGB' instead of 'DXT5' for DDS write of BC3_UNORM data
|
||||
|
||||
DDS_FLAGS_ALLOW_LARGE_FILES = 0x1000000,
|
||||
// Enables the loader to read large dimension .dds files (i.e. greater than known hardware requirements)
|
||||
};
|
||||
|
|
|
@ -66,6 +66,19 @@ namespace
|
|||
{ DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_PMALPHA, DDSPF_DXT2 }, // D3DFMT_DXT2
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_PMALPHA, DDSPF_DXT4 }, // D3DFMT_DXT4
|
||||
|
||||
// These DXT5 variants have various swizzled channels. They are returned 'as is' to the client as BC3.
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('A', '2', 'D', '5'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('x', 'G', 'B', 'R'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R', 'x', 'B', 'G'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R', 'B', 'x', 'G'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('x', 'R', 'B', 'G'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R', 'G', 'x', 'B'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('x', 'G', 'x', 'R'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G', 'X', 'R', 'B'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G', 'R', 'X', 'B'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R', 'X', 'G', 'B'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'R', 'G', 'X'), 0, 0, 0, 0, 0 } },
|
||||
|
||||
{ DXGI_FORMAT_BC4_UNORM, CONV_FLAGS_NONE, DDSPF_BC4_UNORM },
|
||||
{ DXGI_FORMAT_BC4_SNORM, CONV_FLAGS_NONE, DDSPF_BC4_SNORM },
|
||||
{ DXGI_FORMAT_BC5_UNORM, CONV_FLAGS_NONE, DDSPF_BC5_UNORM },
|
||||
|
@ -73,6 +86,7 @@ namespace
|
|||
|
||||
{ DXGI_FORMAT_BC4_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('A', 'T', 'I', '1'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC5_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('A', 'T', 'I', '2'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC5_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('A', '2', 'X', 'Y'), 0, 0, 0, 0, 0 } },
|
||||
|
||||
{ DXGI_FORMAT_BC6H_UF16, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '6', 'H'), 0, 0, 0, 0, 0 } },
|
||||
{ DXGI_FORMAT_BC7_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '7', 'L'), 0, 0, 0, 0, 0 } },
|
||||
|
@ -614,7 +628,6 @@ HRESULT DirectX::EncodeDDSHeader(
|
|||
case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy(&ddpf, &DDSPF_G8R8_G8B8, sizeof(DDS_PIXELFORMAT)); break;
|
||||
case DXGI_FORMAT_BC1_UNORM: memcpy(&ddpf, &DDSPF_DXT1, sizeof(DDS_PIXELFORMAT)); break;
|
||||
case DXGI_FORMAT_BC2_UNORM: memcpy(&ddpf, metadata.IsPMAlpha() ? (&DDSPF_DXT2) : (&DDSPF_DXT3), sizeof(DDS_PIXELFORMAT)); break;
|
||||
case DXGI_FORMAT_BC3_UNORM: memcpy(&ddpf, metadata.IsPMAlpha() ? (&DDSPF_DXT4) : (&DDSPF_DXT5), sizeof(DDS_PIXELFORMAT)); break;
|
||||
case DXGI_FORMAT_BC4_SNORM: memcpy(&ddpf, &DDSPF_BC4_SNORM, sizeof(DDS_PIXELFORMAT)); break;
|
||||
case DXGI_FORMAT_BC5_SNORM: memcpy(&ddpf, &DDSPF_BC5_SNORM, sizeof(DDS_PIXELFORMAT)); break;
|
||||
case DXGI_FORMAT_B5G6R5_UNORM: memcpy(&ddpf, &DDSPF_R5G6B5, sizeof(DDS_PIXELFORMAT)); break;
|
||||
|
@ -627,6 +640,14 @@ HRESULT DirectX::EncodeDDSHeader(
|
|||
case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy(&ddpf, &DDSPF_A4R4G4B4, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.2
|
||||
case DXGI_FORMAT_YUY2: memcpy(&ddpf, &DDSPF_YUY2, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.2
|
||||
|
||||
case DXGI_FORMAT_BC3_UNORM:
|
||||
memcpy(&ddpf, metadata.IsPMAlpha() ? (&DDSPF_DXT4) : (&DDSPF_DXT5), sizeof(DDS_PIXELFORMAT));
|
||||
if (flags & DDS_FLAGS_FORCE_DXT5_RXGB)
|
||||
{
|
||||
ddpf.fourCC = MAKEFOURCC('R', 'X', 'G', 'B');
|
||||
}
|
||||
break;
|
||||
|
||||
// Legacy D3DX formats using D3DFMT enum value as FourCC
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
ddpf.size = sizeof(DDS_PIXELFORMAT); ddpf.flags = DDS_FOURCC; ddpf.fourCC = 116; // D3DFMT_A32B32G32R32F
|
||||
|
|
|
@ -147,6 +147,12 @@ namespace
|
|||
ROTATE_P3D65_TO_709,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FORMAT_DXT5_NM = 1,
|
||||
FORMAT_DXT5_RXGB,
|
||||
};
|
||||
|
||||
static_assert(OPT_MAX <= 64, "dwOptions is a unsigned int bitfield");
|
||||
|
||||
struct SConversion
|
||||
|
@ -338,6 +344,15 @@ namespace
|
|||
{ nullptr, DXGI_FORMAT_UNKNOWN }
|
||||
};
|
||||
|
||||
const SValue<uint32_t> g_pSpecialFormats[] =
|
||||
{
|
||||
{ L"BC3n", FORMAT_DXT5_NM },
|
||||
{ L"DXT5nm", FORMAT_DXT5_NM },
|
||||
{ L"RXGB", FORMAT_DXT5_RXGB },
|
||||
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
|
||||
const SValue<uint32_t> g_pReadOnlyFormats[] =
|
||||
{
|
||||
DEFFMT(R32G32B32A32_TYPELESS),
|
||||
|
@ -997,6 +1012,8 @@ namespace
|
|||
PrintList(13, g_pFormats);
|
||||
wprintf(L" ");
|
||||
PrintList(13, g_pFormatAliases);
|
||||
wprintf(L" ");
|
||||
PrintList(13, g_pSpecialFormats);
|
||||
|
||||
wprintf(L"\n <filter>: ");
|
||||
PrintList(13, g_pFilters);
|
||||
|
@ -1428,6 +1445,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||
float paperWhiteNits = 200.f;
|
||||
float preserveAlphaCoverageRef = 0.0f;
|
||||
bool keepRecursiveDirs = false;
|
||||
bool dxt5nm = false;
|
||||
bool dxt5rxgb = false;
|
||||
uint32_t swizzleElements[4] = { 0, 1, 2, 3 };
|
||||
uint32_t zeroElements[4] = {};
|
||||
uint32_t oneElements[4] = {};
|
||||
|
@ -1581,12 +1600,26 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||
format = static_cast<DXGI_FORMAT>(LookupByName(pValue, g_pFormatAliases));
|
||||
if (!format)
|
||||
{
|
||||
switch (LookupByName(pValue, g_pSpecialFormats))
|
||||
{
|
||||
case FORMAT_DXT5_NM:
|
||||
format = DXGI_FORMAT_BC3_UNORM;
|
||||
dxt5nm = true;
|
||||
break;
|
||||
|
||||
case FORMAT_DXT5_RXGB:
|
||||
format = DXGI_FORMAT_BC3_UNORM;
|
||||
dxt5rxgb = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
wprintf(L"Invalid value specified with -f (%ls)\n", pValue);
|
||||
wprintf(L"\n");
|
||||
PrintUsage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_FILTER:
|
||||
|
@ -3454,7 +3487,75 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||
}
|
||||
|
||||
// --- Compress ----------------------------------------------------------------
|
||||
if (IsCompressed(tformat) && (FileType == CODEC_DDS))
|
||||
if (FileType == CODEC_DDS)
|
||||
{
|
||||
if (dxt5nm || dxt5rxgb)
|
||||
{
|
||||
// Prepare for DXT5nm/RXGB
|
||||
assert(tformat == DXGI_FORMAT_BC3_UNORM);
|
||||
|
||||
std::unique_ptr<ScratchImage> timage(new (std::nothrow) ScratchImage);
|
||||
if (!timage)
|
||||
{
|
||||
wprintf(L"\nERROR: Memory allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dxt5nm)
|
||||
{
|
||||
hr = TransformImage(image->GetImages(), image->GetImageCount(), image->GetMetadata(),
|
||||
[=](XMVECTOR* outPixels, const XMVECTOR* inPixels, size_t w, size_t y)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
outPixels[j] = XMVectorPermute<4, 1, 5, 0>(inPixels[j], g_XMIdentityR0);
|
||||
}
|
||||
}, *timage);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED [DXT5nm] (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = TransformImage(image->GetImages(), image->GetImageCount(), image->GetMetadata(),
|
||||
[=](XMVECTOR* outPixels, const XMVECTOR* inPixels, size_t w, size_t y)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
outPixels[j] = XMVectorSwizzle<3, 1, 2, 0>(inPixels[j]);
|
||||
}
|
||||
}, *timage);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED [DXT5 RXGB] (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
auto& tinfo = timage->GetMetadata();
|
||||
#endif
|
||||
|
||||
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.format == tinfo.format);
|
||||
assert(info.dimension == tinfo.dimension);
|
||||
|
||||
image.swap(timage);
|
||||
cimage.reset();
|
||||
}
|
||||
|
||||
if (IsCompressed(tformat))
|
||||
{
|
||||
if (cimage && (cimage->GetMetadata().format == tformat))
|
||||
{
|
||||
|
@ -3569,16 +3670,19 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||
image.swap(timage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cimage.reset();
|
||||
}
|
||||
|
||||
cimage.reset();
|
||||
|
||||
// --- Set alpha mode ----------------------------------------------------------
|
||||
if (HasAlpha(info.format)
|
||||
&& info.format != DXGI_FORMAT_A8_UNORM)
|
||||
{
|
||||
if (image->IsAlphaAllOpaque())
|
||||
if (dxt5nm || dxt5rxgb)
|
||||
{
|
||||
info.SetAlphaMode(TEX_ALPHA_MODE_CUSTOM);
|
||||
}
|
||||
else if (image->IsAlphaAllOpaque())
|
||||
{
|
||||
info.SetAlphaMode(TEX_ALPHA_MODE_OPAQUE);
|
||||
}
|
||||
|
@ -3693,6 +3797,11 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||
}
|
||||
else if (dwOptions & (uint64_t(1) << OPT_USE_DX9))
|
||||
{
|
||||
if (dxt5rxgb)
|
||||
{
|
||||
ddsFlags |= DDS_FLAGS_FORCE_DXT5_RXGB;
|
||||
}
|
||||
|
||||
ddsFlags |= DDS_FLAGS_FORCE_DX9_LEGACY;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче