diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 2fce943..32d607b 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -482,6 +482,12 @@ namespace DirectX TEX_COMPRESS_UNIFORM = 0x40000, // Uniform color weighting for BC1-3 compression; by default uses perceptual weighting + TEX_COMPRESS_SRGB_IN = 0x1000000, + TEX_COMPRESS_SRGB_OUT = 0x2000000, + TEX_COMPRESS_SRGB = ( TEX_COMPRESS_SRGB_IN | TEX_COMPRESS_SRGB_OUT ), + // if the input format type is IsSRGB(), then SRGB_IN is on by default + // if the output format type is IsSRGB(), then SRGB_OUT is on by default + TEX_COMPRESS_PARALLEL = 0x10000000, // Compress is free to use multithreading to improve performance (by default it does not use multithreading) }; @@ -492,9 +498,10 @@ namespace DirectX _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef, _Out_ ScratchImage& cImages ); // Note that alphaRef is only used by BC1. 0.5f is a typical value to use - HRESULT Compress( _In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image ); + HRESULT Compress( _In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, + _Out_ ScratchImage& image ); HRESULT Compress( _In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, - _In_ DXGI_FORMAT format, _Out_ ScratchImage& cImages ); + _In_ DXGI_FORMAT format, _In_ DWORD compress, _Out_ ScratchImage& cImages ); // DirectCompute-based compression HRESULT Decompress( _In_ const Image& cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image ); diff --git a/DirectXTex/DirectXTexCompress.cpp b/DirectXTex/DirectXTexCompress.cpp index 3a0b9d1..328e6b3 100644 --- a/DirectXTex/DirectXTexCompress.cpp +++ b/DirectXTex/DirectXTexCompress.cpp @@ -35,6 +35,14 @@ inline static DWORD _GetBCFlags( _In_ DWORD compress ) return ( compress & (BC_FLAGS_DITHER_RGB|BC_FLAGS_DITHER_A|BC_FLAGS_UNIFORM) ); } +inline static DWORD _GetSRGBFlags( _In_ DWORD compress ) +{ + static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" ); + static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" ); + static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" ); + return ( compress & TEX_COMPRESS_SRGB ); +} + inline static bool _DetermineEncoderSettings( _In_ DXGI_FORMAT format, _Out_ BC_ENCODE& pfEncode, _Out_ size_t& blocksize, _Out_ DWORD& cflags ) { switch(format) @@ -62,7 +70,7 @@ inline static bool _DetermineEncoderSettings( _In_ DXGI_FORMAT format, _Out_ BC_ //------------------------------------------------------------------------------------- static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags, - _In_ float alphaRef ) + _In_ DWORD srgb, _In_ float alphaRef ) { if ( !image.pixels || !result.pixels ) return E_POINTER; @@ -156,7 +164,7 @@ static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _ } } - _ConvertScanline( temp, 16, result.format, format, cflags ); + _ConvertScanline( temp, 16, result.format, format, cflags | srgb ); if ( pfEncode ) pfEncode( dptr, temp, bcflags ); @@ -178,7 +186,7 @@ static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _ //------------------------------------------------------------------------------------- #ifdef _OPENMP static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags, - _In_ float alphaRef ) + _In_ DWORD srgb, _In_ float alphaRef ) { if ( !image.pixels || !result.pixels ) return E_POINTER; @@ -281,7 +289,7 @@ static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image& } } - _ConvertScanline( temp, 16, result.format, format, cflags ); + _ConvertScanline( temp, 16, result.format, format, cflags | srgb ); if ( pfEncode ) pfEncode( pDest, temp, bcflags ); @@ -574,12 +582,12 @@ HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, flo #ifndef _OPENMP return E_NOTIMPL; #else - hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), alphaRef ); + hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); #endif // _OPENMP } else { - hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), alphaRef ); + hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); } if ( FAILED(hr) ) @@ -638,7 +646,7 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met #else if ( compress & TEX_COMPRESS_PARALLEL ) { - hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), alphaRef ); + hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); if ( FAILED(hr) ) { cImages.Release(); @@ -649,7 +657,7 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met } else { - hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), alphaRef ); + hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); if ( FAILED(hr) ) { cImages.Release(); diff --git a/DirectXTex/DirectXTexCompressGPU.cpp b/DirectXTex/DirectXTexCompressGPU.cpp index e9d2b92..921e3a6 100644 --- a/DirectXTex/DirectXTexCompressGPU.cpp +++ b/DirectXTex/DirectXTexCompressGPU.cpp @@ -20,10 +20,19 @@ namespace DirectX { +inline static DWORD _GetSRGBFlags( _In_ DWORD compress ) +{ + static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" ); + static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" ); + static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" ); + return ( compress & TEX_COMPRESS_SRGB ); +} + + //------------------------------------------------------------------------------------- // Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed //------------------------------------------------------------------------------------- -static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage& image, bool srgb ) +static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage& image, bool srgb, _In_ DWORD filter ) { if ( !srcImage.pixels ) return E_POINTER; @@ -64,7 +73,7 @@ static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage& return E_FAIL; } - _ConvertScanline( scanline.get(), srcImage.width, format, srcImage.format, 0 ); + _ConvertScanline( scanline.get(), srcImage.width, format, srcImage.format, filter ); if ( !_StoreScanline( pDest, img->rowPitch, format, scanline.get(), srcImage.width ) ) { @@ -83,7 +92,7 @@ static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage& //------------------------------------------------------------------------------------- // Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed //------------------------------------------------------------------------------------- -static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image ) +static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image, _In_ DWORD filter ) { if ( !srcImage.pixels ) return E_POINTER; @@ -115,7 +124,7 @@ static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image ) return E_FAIL; } - _ConvertScanline( reinterpret_cast(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, 0 ); + _ConvertScanline( reinterpret_cast(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter ); pSrc += srcImage.rowPitch; pDest += img->rowPitch; @@ -128,7 +137,7 @@ static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image ) //------------------------------------------------------------------------------------- // Compress using GPU, converting to the proper input format for the shader if needed //------------------------------------------------------------------------------------- -inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image& srcImage, _In_ const Image& destImage ) +inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image& srcImage, _In_ const Image& destImage, _In_ DWORD compress ) { if ( !gpubc ) return E_POINTER; @@ -148,18 +157,20 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image& ScratchImage image; HRESULT hr; + DWORD srgb = _GetSRGBFlags( compress ); + switch( format ) { case DXGI_FORMAT_R8G8B8A8_UNORM: - hr = _ConvertToRGBA32( srcImage, image, false ); + hr = _ConvertToRGBA32( srcImage, image, false, srgb ); break; case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - hr = _ConvertToRGBA32( srcImage, image, true ); + hr = _ConvertToRGBA32( srcImage, image, true, srgb ); break; case DXGI_FORMAT_R32G32B32A32_FLOAT: - hr = _ConvertToRGBAF32( srcImage, image ); + hr = _ConvertToRGBAF32( srcImage, image, srgb ); break; default: @@ -187,7 +198,7 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image& // Compression //------------------------------------------------------------------------------------- _Use_decl_annotations_ -HRESULT Compress( ID3D11Device* pDevice, const Image& srcImage, DXGI_FORMAT format, ScratchImage& image ) +HRESULT Compress( ID3D11Device* pDevice, const Image& srcImage, DXGI_FORMAT format, DWORD compress, ScratchImage& image ) { if ( !pDevice || IsCompressed(srcImage.format) || !IsCompressed(format) || IsTypeless(format) ) return E_INVALIDARG; @@ -217,7 +228,7 @@ HRESULT Compress( ID3D11Device* pDevice, const Image& srcImage, DXGI_FORMAT form return E_POINTER; } - hr = _GPUCompress( gpubc.get(), srcImage, *img ); + hr = _GPUCompress( gpubc.get(), srcImage, *img, compress ); if ( FAILED(hr) ) image.Release(); @@ -226,7 +237,7 @@ HRESULT Compress( ID3D11Device* pDevice, const Image& srcImage, DXGI_FORMAT form _Use_decl_annotations_ HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata, - DXGI_FORMAT format, ScratchImage& cImages ) + DXGI_FORMAT format, DWORD compress, ScratchImage& cImages ) { if ( !pDevice || !srcImages || !nimages ) return E_INVALIDARG; @@ -302,7 +313,7 @@ HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, return E_FAIL; } - hr = _GPUCompress( gpubc.get(), src, dest[ index ] ); + hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress ); if ( FAILED(hr) ) { cImages.Release(); @@ -353,7 +364,7 @@ HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, return E_FAIL; } - hr = _GPUCompress( gpubc.get(), src, dest[ index ] ); + hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress ); if ( FAILED(hr) ) { cImages.Release(); diff --git a/Texconv/texconv.cpp b/Texconv/texconv.cpp index 15291e1..c2c6f68 100644 --- a/Texconv/texconv.cpp +++ b/Texconv/texconv.cpp @@ -1336,11 +1336,11 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) if ( bc6hbc7 && pDevice ) { - hr = Compress( pDevice, img, nimg, info, tformat, *timage ); + hr = Compress( pDevice, img, nimg, info, tformat, dwSRGB, *timage ); } else { - hr = Compress( img, nimg, info, tformat, cflags, 0.5f, *timage ); + hr = Compress( img, nimg, info, tformat, cflags | dwSRGB, 0.5f, *timage ); } if ( FAILED(hr) ) {