diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 1886e50..36eb697 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -57,6 +57,9 @@ namespace DirectX size_t ComputeScanlines( _In_ DXGI_FORMAT fmt, _In_ size_t height ); DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT fmt ); + DXGI_FORMAT MakeTypeless( _In_ DXGI_FORMAT fmt ); + DXGI_FORMAT MakeTypelessUNORM( _In_ DXGI_FORMAT fmt ); + DXGI_FORMAT MakeTypelessFLOAT( _In_ DXGI_FORMAT fmt ); //--------------------------------------------------------------------------------- // Texture metadata @@ -191,6 +194,8 @@ namespace DirectX void Release(); + bool OverrideFormat( _In_ DXGI_FORMAT f ); + const TexMetadata& GetMetadata() const { return _metadata; } const Image* GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const; diff --git a/DirectXTex/DirectXTexImage.cpp b/DirectXTex/DirectXTexImage.cpp index f461b0a..ded0362 100644 --- a/DirectXTex/DirectXTexImage.cpp +++ b/DirectXTex/DirectXTexImage.cpp @@ -594,6 +594,32 @@ void ScratchImage::Release() memset(&_metadata, 0, sizeof(_metadata)); } +bool ScratchImage::OverrideFormat( DXGI_FORMAT f ) +{ + if ( !_image ) + return false; + + if ( !IsValid( f ) || IsVideo( f ) ) + return false; + + if ( ( BitsPerPixel( f ) != BitsPerPixel( _metadata.format ) ) + || ( IsCompressed( f ) != IsCompressed( _metadata.format ) ) + || ( IsPacked( f ) != IsPacked( _metadata.format ) ) ) + { + // Can't change the effective pitch of the format this way + return false; + } + + for( size_t index = 0; index < _nimages; ++index ) + { + _image[ index ].format = f; + } + + _metadata.format = f; + + return true; +} + const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const { if ( mip >= _metadata.mipLevels ) diff --git a/DirectXTex/DirectXTexUtil.cpp b/DirectXTex/DirectXTexUtil.cpp index a722353..9486486 100644 --- a/DirectXTex/DirectXTexUtil.cpp +++ b/DirectXTex/DirectXTexUtil.cpp @@ -434,6 +434,214 @@ DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT fmt ) } +//------------------------------------------------------------------------------------- +// Converts to a format to an equivalent TYPELESS format if available +//------------------------------------------------------------------------------------- +DXGI_FORMAT MakeTypeless( _In_ DXGI_FORMAT fmt ) +{ + switch( fmt ) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return DXGI_FORMAT_R32G32B32A32_TYPELESS; + + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return DXGI_FORMAT_R32G32B32_TYPELESS; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + return DXGI_FORMAT_R16G16B16A16_TYPELESS; + + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + return DXGI_FORMAT_R32G32_TYPELESS; + + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + return DXGI_FORMAT_R10G10B10A2_TYPELESS; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + return DXGI_FORMAT_R8G8B8A8_TYPELESS; + + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + return DXGI_FORMAT_R16G16_TYPELESS; + + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + return DXGI_FORMAT_R32_TYPELESS; + + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + return DXGI_FORMAT_R8G8_TYPELESS; + + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + return DXGI_FORMAT_R16_TYPELESS; + + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return DXGI_FORMAT_R8_TYPELESS; + + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + return DXGI_FORMAT_BC1_TYPELESS; + + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + return DXGI_FORMAT_BC2_TYPELESS; + + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + return DXGI_FORMAT_BC3_TYPELESS; + + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return DXGI_FORMAT_BC4_TYPELESS; + + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + return DXGI_FORMAT_BC5_TYPELESS; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8A8_TYPELESS; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8X8_TYPELESS; + + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + return DXGI_FORMAT_BC6H_TYPELESS; + + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return DXGI_FORMAT_BC7_TYPELESS; + + default: + return fmt; + } +} + + +//------------------------------------------------------------------------------------- +// Converts to a TYPELESS format to an equivalent UNORM format if available +//------------------------------------------------------------------------------------- +DXGI_FORMAT MakeTypelessUNORM( _In_ DXGI_FORMAT fmt ) +{ + switch( fmt ) + { + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + return DXGI_FORMAT_R16G16B16A16_UNORM; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + return DXGI_FORMAT_R10G10B10A2_UNORM; + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case DXGI_FORMAT_R16G16_TYPELESS: + return DXGI_FORMAT_R16G16_UNORM; + + case DXGI_FORMAT_R8G8_TYPELESS: + return DXGI_FORMAT_R8G8_UNORM; + + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_R16_UNORM; + + case DXGI_FORMAT_R8_TYPELESS: + return DXGI_FORMAT_R8_UNORM; + + case DXGI_FORMAT_BC1_TYPELESS: + return DXGI_FORMAT_BC1_UNORM; + + case DXGI_FORMAT_BC2_TYPELESS: + return DXGI_FORMAT_BC2_UNORM; + + case DXGI_FORMAT_BC3_TYPELESS: + return DXGI_FORMAT_BC3_UNORM; + + case DXGI_FORMAT_BC4_TYPELESS: + return DXGI_FORMAT_BC4_UNORM; + + case DXGI_FORMAT_BC5_TYPELESS: + return DXGI_FORMAT_BC5_UNORM; + + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return DXGI_FORMAT_B8G8R8A8_UNORM; + + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + return DXGI_FORMAT_B8G8R8X8_UNORM; + + case DXGI_FORMAT_BC7_TYPELESS: + return DXGI_FORMAT_BC7_UNORM; + + default: + return fmt; + } +} + + +//------------------------------------------------------------------------------------- +// Converts to a TYPELESS format to an equivalent FLOAT format if available +//------------------------------------------------------------------------------------- +DXGI_FORMAT MakeTypelessFLOAT( _In_ DXGI_FORMAT fmt ) +{ + switch( fmt ) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + return DXGI_FORMAT_R32G32B32_FLOAT; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + case DXGI_FORMAT_R32G32_TYPELESS: + return DXGI_FORMAT_R32G32_FLOAT; + + case DXGI_FORMAT_R16G16_TYPELESS: + return DXGI_FORMAT_R16G16_FLOAT; + + case DXGI_FORMAT_R32_TYPELESS: + return DXGI_FORMAT_R32_FLOAT; + + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_R16_FLOAT; + + default: + return fmt; + } +} + + //===================================================================================== // TexMetadata //===================================================================================== diff --git a/Texconv/texconv.cpp b/Texconv/texconv.cpp index ae49330..5d7f457 100644 --- a/Texconv/texconv.cpp +++ b/Texconv/texconv.cpp @@ -35,7 +35,9 @@ enum OPTIONS // Note: dwOptions below assumes 32 or less options. OPT_DDS_DWORD_ALIGN, OPT_USE_DX10, OPT_NOLOGO, - OPT_SEPALPHA + OPT_SEPALPHA, + OPT_TYPELESS_UNORM, + OPT_TYPELESS_FLOAT, }; struct SConversion @@ -76,6 +78,8 @@ SValue g_pOptions[] = { L"dx10", OPT_USE_DX10 }, { L"nologo", OPT_NOLOGO }, { L"sepalpha", OPT_SEPALPHA }, + { L"tu", OPT_TYPELESS_UNORM }, + { L"tf", OPT_TYPELESS_FLOAT }, { nullptr, 0 } }; @@ -332,6 +336,7 @@ void PrintUsage() wprintf( L" -hflip horizonal flip of source image\n"); wprintf( L" -vflip vertical flip of source image\n"); wprintf( L" -sepalpha resize/generate mips alpha channel separately from color channels\n"); + wprintf( L" -t{u|f} DDS files with TYPELESS format is treated as UNORM or FLOAT\n"); wprintf( L" -dword Use DWORD instead of BYTE alignment (DDS input only)\n"); wprintf( L" -dx10 Force use of 'DX10' extended header (DDS output only)\n"); wprintf( L" -nologo suppress copyright message\n"); @@ -412,7 +417,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) dwOptions |= 1 << dwOption; - if( (OPT_NOLOGO != dwOption) && (OPT_SEPALPHA != dwOption) + if( (OPT_NOLOGO != dwOption) && (OPT_SEPALPHA != dwOption) && (OPT_TYPELESS_UNORM != dwOption) && (OPT_TYPELESS_FLOAT != dwOption) && (OPT_SRGB != dwOption) && (OPT_SRGBI != dwOption) && (OPT_SRGBO != dwOption) && (OPT_HFLIP != dwOption) && (OPT_VFLIP != dwOption) && (OPT_DDS_DWORD_ALIGN != dwOption) && (OPT_USE_DX10 != dwOption) ) @@ -612,6 +617,27 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) delete image; continue; } + + if ( IsTypeless( info.format ) ) + { + if ( dwOptions & (1 << OPT_TYPELESS_UNORM) ) + { + info.format = MakeTypelessUNORM( info.format ); + } + else if ( dwOptions & (1 << OPT_TYPELESS_FLOAT) ) + { + info.format = MakeTypelessFLOAT( info.format ); + } + + if ( IsTypeless( info.format ) ) + { + wprintf( L" FAILED due to Typeless format %d\n", info.format ); + delete image; + continue; + } + + image->OverrideFormat( info.format ); + } } else if ( _wcsicmp( ext, L".tga" ) == 0 ) { @@ -694,6 +720,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) } // --- Flip/Rotate ------------------------------------------------------------- + // TODO - OPT_ROTATE ? (90, 180, 270) if ( dwOptions & ( (1 << OPT_HFLIP) | (1 << OPT_VFLIP) ) ) { ScratchImage *timage = new ScratchImage;