mirror of
https://github.com/microsoft/DirectXTex.git
synced 2025-07-09 11:40:14 +02:00
Add CompressEx and ConvertEx methods that report progress (#375)
This commit is contained in:
parent
7e7b11db04
commit
1d1d4d0134
@ -664,12 +664,26 @@ namespace DirectX
|
|||||||
constexpr float TEX_THRESHOLD_DEFAULT = 0.5f;
|
constexpr float TEX_THRESHOLD_DEFAULT = 0.5f;
|
||||||
// Default value for alpha threshold used when converting to 1-bit alpha
|
// Default value for alpha threshold used when converting to 1-bit alpha
|
||||||
|
|
||||||
|
struct ConvertOptions
|
||||||
|
{
|
||||||
|
TEX_FILTER_FLAGS filter;
|
||||||
|
float threshold;
|
||||||
|
};
|
||||||
|
|
||||||
HRESULT __cdecl Convert(
|
HRESULT __cdecl Convert(
|
||||||
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_FILTER_FLAGS filter, _In_ float threshold,
|
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_FILTER_FLAGS filter, _In_ float threshold,
|
||||||
_Out_ ScratchImage& image) noexcept;
|
_Out_ ScratchImage& image) noexcept;
|
||||||
HRESULT __cdecl Convert(
|
HRESULT __cdecl Convert(
|
||||||
_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||||
_In_ DXGI_FORMAT format, _In_ TEX_FILTER_FLAGS filter, _In_ float threshold, _Out_ ScratchImage& result) noexcept;
|
_In_ DXGI_FORMAT format, _In_ TEX_FILTER_FLAGS filter, _In_ float threshold, _Out_ ScratchImage& result) noexcept;
|
||||||
|
|
||||||
|
HRESULT __cdecl ConvertEx(
|
||||||
|
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ const ConvertOptions& options,
|
||||||
|
_Out_ ScratchImage& image, _In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||||
|
HRESULT __cdecl ConvertEx(
|
||||||
|
_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||||
|
_In_ DXGI_FORMAT format, _In_ const ConvertOptions& options, _Out_ ScratchImage& result,
|
||||||
|
_In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||||
// Convert the image to a new format
|
// Convert the image to a new format
|
||||||
|
|
||||||
HRESULT __cdecl ConvertToSinglePlane(_In_ const Image& srcImage, _Out_ ScratchImage& image) noexcept;
|
HRESULT __cdecl ConvertToSinglePlane(_In_ const Image& srcImage, _Out_ ScratchImage& image) noexcept;
|
||||||
@ -756,6 +770,16 @@ namespace DirectX
|
|||||||
// Compress is free to use multithreading to improve performance (by default it does not use multithreading)
|
// Compress is free to use multithreading to improve performance (by default it does not use multithreading)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr float TEX_ALPHA_WEIGHT_DEFAULT = 1.0f;
|
||||||
|
// Default value for alpha weight used for GPU BC7 compression
|
||||||
|
|
||||||
|
struct CompressOptions
|
||||||
|
{
|
||||||
|
TEX_COMPRESS_FLAGS flags;
|
||||||
|
float threshold;
|
||||||
|
float alphaWeight;
|
||||||
|
};
|
||||||
|
|
||||||
HRESULT __cdecl Compress(
|
HRESULT __cdecl Compress(
|
||||||
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float threshold,
|
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float threshold,
|
||||||
_Out_ ScratchImage& cImage) noexcept;
|
_Out_ ScratchImage& cImage) noexcept;
|
||||||
@ -764,6 +788,14 @@ namespace DirectX
|
|||||||
_In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float threshold, _Out_ ScratchImage& cImages) noexcept;
|
_In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float threshold, _Out_ ScratchImage& cImages) noexcept;
|
||||||
// Note that threshold is only used by BC1. TEX_THRESHOLD_DEFAULT is a typical value to use
|
// Note that threshold is only used by BC1. TEX_THRESHOLD_DEFAULT is a typical value to use
|
||||||
|
|
||||||
|
HRESULT __cdecl CompressEx(
|
||||||
|
_In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ const CompressOptions& options,
|
||||||
|
_Out_ ScratchImage& cImage, _In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||||
|
HRESULT __cdecl CompressEx(
|
||||||
|
_In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||||
|
_In_ DXGI_FORMAT format, _In_ const CompressOptions& options, _Out_ ScratchImage& cImages,
|
||||||
|
_In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||||
|
|
||||||
#if defined(__d3d11_h__) || defined(__d3d11_x_h__)
|
#if defined(__d3d11_h__) || defined(__d3d11_x_h__)
|
||||||
HRESULT __cdecl Compress(
|
HRESULT __cdecl Compress(
|
||||||
_In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress,
|
_In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress,
|
||||||
@ -772,6 +804,14 @@ namespace DirectX
|
|||||||
_In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
_In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||||
_In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float alphaWeight, _Out_ ScratchImage& cImages) noexcept;
|
_In_ DXGI_FORMAT format, _In_ TEX_COMPRESS_FLAGS compress, _In_ float alphaWeight, _Out_ ScratchImage& cImages) noexcept;
|
||||||
// DirectCompute-based compression (alphaWeight is only used by BC7. 1.0 is the typical value to use)
|
// DirectCompute-based compression (alphaWeight is only used by BC7. 1.0 is the typical value to use)
|
||||||
|
|
||||||
|
HRESULT __cdecl CompressEx(
|
||||||
|
_In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ const CompressOptions& options,
|
||||||
|
_Out_ ScratchImage& image, _In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||||
|
HRESULT __cdecl CompressEx(
|
||||||
|
_In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||||
|
_In_ DXGI_FORMAT format, _In_ const CompressOptions& options, _Out_ ScratchImage& cImages,
|
||||||
|
_In_opt_ std::function<bool __cdecl(size_t, size_t)> statusCallBack = nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HRESULT __cdecl Decompress(_In_ const Image& cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image) noexcept;
|
HRESULT __cdecl Decompress(_In_ const Image& cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image) noexcept;
|
||||||
|
@ -74,7 +74,8 @@ namespace
|
|||||||
const Image& result,
|
const Image& result,
|
||||||
uint32_t bcflags,
|
uint32_t bcflags,
|
||||||
TEX_FILTER_FLAGS srgb,
|
TEX_FILTER_FLAGS srgb,
|
||||||
float threshold) noexcept
|
float threshold,
|
||||||
|
const std::function<bool __cdecl(size_t, size_t)>& statusCallback) noexcept
|
||||||
{
|
{
|
||||||
if (!image.pixels || !result.pixels)
|
if (!image.pixels || !result.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
@ -111,6 +112,14 @@ namespace
|
|||||||
const size_t rowPitch = image.rowPitch;
|
const size_t rowPitch = image.rowPitch;
|
||||||
for (size_t h = 0; h < image.height; h += 4)
|
for (size_t h = 0; h < image.height; h += 4)
|
||||||
{
|
{
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(h, image.height))
|
||||||
|
{
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const uint8_t *sptr = pSrc;
|
const uint8_t *sptr = pSrc;
|
||||||
uint8_t* dptr = pDest;
|
uint8_t* dptr = pDest;
|
||||||
const size_t ph = std::min<size_t>(4, image.height - h);
|
const size_t ph = std::min<size_t>(4, image.height - h);
|
||||||
@ -203,7 +212,8 @@ namespace
|
|||||||
const Image& result,
|
const Image& result,
|
||||||
uint32_t bcflags,
|
uint32_t bcflags,
|
||||||
TEX_FILTER_FLAGS srgb,
|
TEX_FILTER_FLAGS srgb,
|
||||||
float threshold) noexcept
|
float threshold,
|
||||||
|
const std::function<bool __cdecl(size_t, size_t)>& statusCallback) noexcept
|
||||||
{
|
{
|
||||||
if (!image.pixels || !result.pixels)
|
if (!image.pixels || !result.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
@ -239,9 +249,22 @@ namespace
|
|||||||
|
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
|
|
||||||
#pragma omp parallel for
|
size_t progress = 0;
|
||||||
|
bool abort = false;
|
||||||
|
|
||||||
|
const size_t progressTotal = std::max<size_t>(1, (image.height + 3) / 4);
|
||||||
|
|
||||||
|
#pragma omp parallel for shared(progress)
|
||||||
for (int nb = 0; nb < static_cast<int>(nBlocks); ++nb)
|
for (int nb = 0; nb < static_cast<int>(nBlocks); ++nb)
|
||||||
{
|
{
|
||||||
|
#pragma omp flush (abort)
|
||||||
|
if (abort)
|
||||||
|
{
|
||||||
|
// Short circuit the loop body if an abort is requested.
|
||||||
|
// OpenMP 2.0 does not support cancellation of a 'parallel for' loop.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const int nbWidth = std::max<int>(1, int((image.width + 3) / 4));
|
const int nbWidth = std::max<int>(1, int((image.width + 3) / 4));
|
||||||
|
|
||||||
int y = nb / nbWidth;
|
int y = nb / nbWidth;
|
||||||
@ -323,9 +346,29 @@ namespace
|
|||||||
pfEncode(pDest, temp, bcflags);
|
pfEncode(pDest, temp, bcflags);
|
||||||
else
|
else
|
||||||
D3DXEncodeBC1(pDest, temp, threshold, bcflags);
|
D3DXEncodeBC1(pDest, temp, threshold, bcflags);
|
||||||
|
|
||||||
|
// Report progress when a new row is reached.
|
||||||
|
if (x == 0 && statusCallback)
|
||||||
|
{
|
||||||
|
#pragma omp atomic
|
||||||
|
progress += 4;
|
||||||
|
|
||||||
|
if (!statusCallback(progress, progressTotal))
|
||||||
|
{
|
||||||
|
abort = true;
|
||||||
|
#pragma omp flush (abort)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (fail) ? E_FAIL : S_OK;
|
if (abort)
|
||||||
|
{
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (fail) ? E_FAIL : S_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // _OPENMP
|
#endif // _OPENMP
|
||||||
|
|
||||||
@ -592,6 +635,38 @@ HRESULT DirectX::Compress(
|
|||||||
TEX_COMPRESS_FLAGS compress,
|
TEX_COMPRESS_FLAGS compress,
|
||||||
float threshold,
|
float threshold,
|
||||||
ScratchImage& image) noexcept
|
ScratchImage& image) noexcept
|
||||||
|
{
|
||||||
|
CompressOptions options = {};
|
||||||
|
options.flags = compress;
|
||||||
|
options.threshold = threshold;
|
||||||
|
|
||||||
|
return CompressEx(srcImage, format, options, image, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
HRESULT DirectX::Compress(
|
||||||
|
const Image* srcImages,
|
||||||
|
size_t nimages,
|
||||||
|
const TexMetadata& metadata,
|
||||||
|
DXGI_FORMAT format,
|
||||||
|
TEX_COMPRESS_FLAGS compress,
|
||||||
|
float threshold,
|
||||||
|
ScratchImage& cImages) noexcept
|
||||||
|
{
|
||||||
|
CompressOptions options = {};
|
||||||
|
options.flags = compress;
|
||||||
|
options.threshold = threshold;
|
||||||
|
|
||||||
|
return CompressEx(srcImages, nimages, metadata, format, options, cImages, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
HRESULT DirectX::CompressEx(
|
||||||
|
const Image& srcImage,
|
||||||
|
DXGI_FORMAT format,
|
||||||
|
const CompressOptions& options,
|
||||||
|
ScratchImage& image,
|
||||||
|
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||||
{
|
{
|
||||||
if (IsCompressed(srcImage.format) || !IsCompressed(format))
|
if (IsCompressed(srcImage.format) || !IsCompressed(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -612,35 +687,56 @@ HRESULT DirectX::Compress(
|
|||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(0, img->height))
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Compress single image
|
// Compress single image
|
||||||
if (compress & TEX_COMPRESS_PARALLEL)
|
if (options.flags & TEX_COMPRESS_PARALLEL)
|
||||||
{
|
{
|
||||||
#ifndef _OPENMP
|
#ifndef _OPENMP
|
||||||
return E_NOTIMPL;
|
hr = E_NOTIMPL;
|
||||||
#else
|
#else
|
||||||
hr = CompressBC_Parallel(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold);
|
hr = CompressBC_Parallel(srcImage, *img, GetBCFlags(options.flags), GetSRGBFlags(options.flags), options.threshold, statusCallback);
|
||||||
#endif // _OPENMP
|
#endif // _OPENMP
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = CompressBC(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold);
|
hr = CompressBC(srcImage, *img, GetBCFlags(options.flags), GetSRGBFlags(options.flags), options.threshold, statusCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
return hr;
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(img->height, img->height))
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT DirectX::Compress(
|
HRESULT DirectX::CompressEx(
|
||||||
const Image* srcImages,
|
const Image* srcImages,
|
||||||
size_t nimages,
|
size_t nimages,
|
||||||
const TexMetadata& metadata,
|
const TexMetadata& metadata,
|
||||||
DXGI_FORMAT format,
|
DXGI_FORMAT format,
|
||||||
TEX_COMPRESS_FLAGS compress,
|
const CompressOptions& options,
|
||||||
float threshold,
|
ScratchImage& cImages,
|
||||||
ScratchImage& cImages) noexcept
|
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||||
{
|
{
|
||||||
if (!srcImages || !nimages)
|
if (!srcImages || !nimages)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -654,6 +750,19 @@ HRESULT DirectX::Compress(
|
|||||||
|
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
|
|
||||||
|
if (statusCallback
|
||||||
|
&& nimages == 1
|
||||||
|
&& !metadata.IsVolumemap()
|
||||||
|
&& metadata.mipLevels == 1
|
||||||
|
&& metadata.arraySize == 1)
|
||||||
|
{
|
||||||
|
// If progress reporting is requested when compressing a single 1D or 2D image, call
|
||||||
|
// the CompressEx overload that takes a single image.
|
||||||
|
// This provides a better user experience as progress will be reported as the image
|
||||||
|
// is being processed, instead of after processing has been completed.
|
||||||
|
return CompressEx(srcImages[0], format, options, cImages, statusCallback);
|
||||||
|
}
|
||||||
|
|
||||||
TexMetadata mdata2 = metadata;
|
TexMetadata mdata2 = metadata;
|
||||||
mdata2.format = format;
|
mdata2.format = format;
|
||||||
HRESULT hr = cImages.Initialize(mdata2);
|
HRESULT hr = cImages.Initialize(mdata2);
|
||||||
@ -673,6 +782,15 @@ HRESULT DirectX::Compress(
|
|||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(0, nimages))
|
||||||
|
{
|
||||||
|
cImages.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t index = 0; index < nimages; ++index)
|
for (size_t index = 0; index < nimages; ++index)
|
||||||
{
|
{
|
||||||
assert(dest[index].format == format);
|
assert(dest[index].format == format);
|
||||||
@ -685,33 +803,44 @@ HRESULT DirectX::Compress(
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((compress & TEX_COMPRESS_PARALLEL))
|
if (options.flags & TEX_COMPRESS_PARALLEL)
|
||||||
{
|
{
|
||||||
#ifndef _OPENMP
|
#ifndef _OPENMP
|
||||||
return E_NOTIMPL;
|
hr = E_NOTIMPL;
|
||||||
#else
|
#else
|
||||||
if (compress & TEX_COMPRESS_PARALLEL)
|
hr = CompressBC_Parallel(src, dest[index], GetBCFlags(options.flags), GetSRGBFlags(options.flags), options.threshold, nullptr);
|
||||||
{
|
|
||||||
hr = CompressBC_Parallel(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), threshold);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
cImages.Release();
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // _OPENMP
|
#endif // _OPENMP
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = CompressBC(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), threshold);
|
hr = CompressBC(src, dest[index], GetBCFlags(options.flags), GetSRGBFlags(options.flags), options.threshold, nullptr);
|
||||||
if (FAILED(hr))
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
cImages.Release();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(index, nimages))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
return E_ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(nimages, nimages))
|
||||||
|
{
|
||||||
|
cImages.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +219,40 @@ HRESULT DirectX::Compress(
|
|||||||
TEX_COMPRESS_FLAGS compress,
|
TEX_COMPRESS_FLAGS compress,
|
||||||
float alphaWeight,
|
float alphaWeight,
|
||||||
ScratchImage& image) noexcept
|
ScratchImage& image) noexcept
|
||||||
|
{
|
||||||
|
CompressOptions options = {};
|
||||||
|
options.flags = compress;
|
||||||
|
options.alphaWeight = alphaWeight;
|
||||||
|
|
||||||
|
return CompressEx(pDevice, srcImage, format, options, image, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
HRESULT DirectX::Compress(
|
||||||
|
ID3D11Device* pDevice,
|
||||||
|
const Image* srcImages,
|
||||||
|
size_t nimages,
|
||||||
|
const TexMetadata& metadata,
|
||||||
|
DXGI_FORMAT format,
|
||||||
|
TEX_COMPRESS_FLAGS compress,
|
||||||
|
float alphaWeight,
|
||||||
|
ScratchImage& cImages) noexcept
|
||||||
|
{
|
||||||
|
CompressOptions options = {};
|
||||||
|
options.flags = compress;
|
||||||
|
options.alphaWeight = alphaWeight;
|
||||||
|
|
||||||
|
return CompressEx(pDevice, srcImages, nimages, metadata, format, options, cImages);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
HRESULT DirectX::CompressEx(
|
||||||
|
ID3D11Device* pDevice,
|
||||||
|
const Image& srcImage,
|
||||||
|
DXGI_FORMAT format,
|
||||||
|
const CompressOptions& options,
|
||||||
|
ScratchImage& image,
|
||||||
|
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||||
{
|
{
|
||||||
if (!pDevice || IsCompressed(srcImage.format) || !IsCompressed(format))
|
if (!pDevice || IsCompressed(srcImage.format) || !IsCompressed(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -236,7 +270,7 @@ HRESULT DirectX::Compress(
|
|||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
hr = gpubc->Prepare(srcImage.width, srcImage.height, compress, format, alphaWeight);
|
hr = gpubc->Prepare(srcImage.width, srcImage.height, options.flags, format, options.alphaWeight);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
@ -252,23 +286,45 @@ HRESULT DirectX::Compress(
|
|||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = GPUCompress(gpubc.get(), srcImage, *img, compress);
|
if (statusCallback)
|
||||||
if (FAILED(hr))
|
{
|
||||||
image.Release();
|
if (!statusCallback(0, 100))
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return hr;
|
hr = GPUCompress(gpubc.get(), srcImage, *img, options.flags);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(100, 100))
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT DirectX::Compress(
|
HRESULT DirectX::CompressEx(
|
||||||
ID3D11Device* pDevice,
|
ID3D11Device* pDevice,
|
||||||
const Image* srcImages,
|
const Image* srcImages,
|
||||||
size_t nimages,
|
size_t nimages,
|
||||||
const TexMetadata& metadata,
|
const TexMetadata& metadata,
|
||||||
DXGI_FORMAT format,
|
DXGI_FORMAT format,
|
||||||
TEX_COMPRESS_FLAGS compress,
|
const CompressOptions& options,
|
||||||
float alphaWeight,
|
ScratchImage& cImages,
|
||||||
ScratchImage& cImages) noexcept
|
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||||
{
|
{
|
||||||
if (!pDevice || !srcImages || !nimages)
|
if (!pDevice || !srcImages || !nimages)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -311,6 +367,15 @@ HRESULT DirectX::Compress(
|
|||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(0, nimages))
|
||||||
|
{
|
||||||
|
cImages.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Process images (ordered by size)
|
// Process images (ordered by size)
|
||||||
switch (metadata.dimension)
|
switch (metadata.dimension)
|
||||||
{
|
{
|
||||||
@ -319,10 +384,11 @@ HRESULT DirectX::Compress(
|
|||||||
{
|
{
|
||||||
size_t w = metadata.width;
|
size_t w = metadata.width;
|
||||||
size_t h = metadata.height;
|
size_t h = metadata.height;
|
||||||
|
size_t progress = 0;
|
||||||
|
|
||||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||||
{
|
{
|
||||||
hr = gpubc->Prepare(w, h, compress, format, alphaWeight);
|
hr = gpubc->Prepare(w, h, options.flags, format, options.alphaWeight);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
@ -348,12 +414,21 @@ HRESULT DirectX::Compress(
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
|
hr = GPUCompress(gpubc.get(), src, dest[index], options.flags);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(progress++, nimages))
|
||||||
|
{
|
||||||
|
cImages.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h > 1)
|
if (h > 1)
|
||||||
@ -370,10 +445,11 @@ HRESULT DirectX::Compress(
|
|||||||
size_t w = metadata.width;
|
size_t w = metadata.width;
|
||||||
size_t h = metadata.height;
|
size_t h = metadata.height;
|
||||||
size_t d = metadata.depth;
|
size_t d = metadata.depth;
|
||||||
|
size_t progress = 0;
|
||||||
|
|
||||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||||
{
|
{
|
||||||
hr = gpubc->Prepare(w, h, compress, format, alphaWeight);
|
hr = gpubc->Prepare(w, h, options.flags, format, options.alphaWeight);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
@ -399,12 +475,21 @@ HRESULT DirectX::Compress(
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
|
hr = GPUCompress(gpubc.get(), src, dest[index], options.flags);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(progress++, nimages))
|
||||||
|
{
|
||||||
|
cImages.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h > 1)
|
if (h > 1)
|
||||||
@ -423,5 +508,14 @@ HRESULT DirectX::Compress(
|
|||||||
return HRESULT_E_NOT_SUPPORTED;
|
return HRESULT_E_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(nimages, nimages))
|
||||||
|
{
|
||||||
|
cImages.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -4798,7 +4798,8 @@ namespace
|
|||||||
_In_ TEX_FILTER_FLAGS filter,
|
_In_ TEX_FILTER_FLAGS filter,
|
||||||
_In_ const Image& destImage,
|
_In_ const Image& destImage,
|
||||||
_In_ float threshold,
|
_In_ float threshold,
|
||||||
size_t z) noexcept
|
size_t z,
|
||||||
|
const std::function<bool __cdecl(size_t, size_t)>& statusCallback) noexcept
|
||||||
{
|
{
|
||||||
assert(srcImage.width == destImage.width);
|
assert(srcImage.width == destImage.width);
|
||||||
assert(srcImage.height == destImage.height);
|
assert(srcImage.height == destImage.height);
|
||||||
@ -4822,6 +4823,14 @@ namespace
|
|||||||
|
|
||||||
for (size_t h = 0; h < srcImage.height; ++h)
|
for (size_t h = 0; h < srcImage.height; ++h)
|
||||||
{
|
{
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(h, srcImage.height))
|
||||||
|
{
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
@ -4845,6 +4854,14 @@ namespace
|
|||||||
// Ordered dithering
|
// Ordered dithering
|
||||||
for (size_t h = 0; h < srcImage.height; ++h)
|
for (size_t h = 0; h < srcImage.height; ++h)
|
||||||
{
|
{
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(h, srcImage.height))
|
||||||
|
{
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
@ -4862,6 +4879,14 @@ namespace
|
|||||||
// No dithering
|
// No dithering
|
||||||
for (size_t h = 0; h < srcImage.height; ++h)
|
for (size_t h = 0; h < srcImage.height; ++h)
|
||||||
{
|
{
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(h, srcImage.height))
|
||||||
|
{
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
if (!LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
@ -5061,6 +5086,21 @@ HRESULT DirectX::Convert(
|
|||||||
TEX_FILTER_FLAGS filter,
|
TEX_FILTER_FLAGS filter,
|
||||||
float threshold,
|
float threshold,
|
||||||
ScratchImage& image) noexcept
|
ScratchImage& image) noexcept
|
||||||
|
{
|
||||||
|
ConvertOptions options = {};
|
||||||
|
options.filter = filter;
|
||||||
|
options.threshold = threshold;
|
||||||
|
|
||||||
|
return ConvertEx(srcImage, format, options, image, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
HRESULT DirectX::ConvertEx(
|
||||||
|
const Image& srcImage,
|
||||||
|
DXGI_FORMAT format,
|
||||||
|
const ConvertOptions& options,
|
||||||
|
ScratchImage& image,
|
||||||
|
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||||
{
|
{
|
||||||
if ((srcImage.format == format) || !IsValid(format))
|
if ((srcImage.format == format) || !IsValid(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -5088,14 +5128,23 @@ HRESULT DirectX::Convert(
|
|||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
WICPixelFormatGUID pfGUID, targetGUID;
|
if (statusCallback)
|
||||||
if (UseWICConversion(filter, srcImage.format, format, pfGUID, targetGUID))
|
|
||||||
{
|
{
|
||||||
hr = ConvertUsingWIC(srcImage, pfGUID, targetGUID, filter, threshold, *rimage);
|
if (!statusCallback(0, rimage->height))
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WICPixelFormatGUID pfGUID, targetGUID;
|
||||||
|
if (UseWICConversion(options.filter, srcImage.format, format, pfGUID, targetGUID))
|
||||||
|
{
|
||||||
|
hr = ConvertUsingWIC(srcImage, pfGUID, targetGUID, options.filter, options.threshold, *rimage);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = ConvertCustom(srcImage, filter, *rimage, threshold, 0);
|
hr = ConvertCustom(srcImage, options.filter, *rimage, options.threshold, 0, statusCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@ -5104,6 +5153,15 @@ HRESULT DirectX::Convert(
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(rimage->height, rimage->height))
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5120,6 +5178,23 @@ HRESULT DirectX::Convert(
|
|||||||
TEX_FILTER_FLAGS filter,
|
TEX_FILTER_FLAGS filter,
|
||||||
float threshold,
|
float threshold,
|
||||||
ScratchImage& result) noexcept
|
ScratchImage& result) noexcept
|
||||||
|
{
|
||||||
|
ConvertOptions options = {};
|
||||||
|
options.filter = filter;
|
||||||
|
options.threshold = threshold;
|
||||||
|
|
||||||
|
return ConvertEx(srcImages, nimages, metadata, format, options, result, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
HRESULT DirectX::ConvertEx(
|
||||||
|
const Image* srcImages,
|
||||||
|
size_t nimages,
|
||||||
|
const TexMetadata& metadata,
|
||||||
|
DXGI_FORMAT format,
|
||||||
|
const ConvertOptions& options,
|
||||||
|
ScratchImage& result,
|
||||||
|
std::function<bool __cdecl(size_t, size_t)> statusCallback)
|
||||||
{
|
{
|
||||||
if (!srcImages || !nimages || (metadata.format == format) || !IsValid(format))
|
if (!srcImages || !nimages || (metadata.format == format) || !IsValid(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -5133,6 +5208,19 @@ HRESULT DirectX::Convert(
|
|||||||
if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX))
|
if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
if (statusCallback
|
||||||
|
&& nimages == 1
|
||||||
|
&& !metadata.IsVolumemap()
|
||||||
|
&& metadata.mipLevels == 1
|
||||||
|
&& metadata.arraySize == 1)
|
||||||
|
{
|
||||||
|
// If progress reporting is requested when converting a single 1D or 2D image, call
|
||||||
|
// the ConvertEx overload that takes a single image.
|
||||||
|
// This provides a better user experience as progress will be reported as the image
|
||||||
|
// is being processed, instead of after processing has been completed.
|
||||||
|
return ConvertEx(srcImages[0], format, options, result, statusCallback);
|
||||||
|
}
|
||||||
|
|
||||||
TexMetadata mdata2 = metadata;
|
TexMetadata mdata2 = metadata;
|
||||||
mdata2.format = format;
|
mdata2.format = format;
|
||||||
HRESULT hr = result.Initialize(mdata2);
|
HRESULT hr = result.Initialize(mdata2);
|
||||||
@ -5152,8 +5240,17 @@ HRESULT DirectX::Convert(
|
|||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(0, nimages))
|
||||||
|
{
|
||||||
|
result.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WICPixelFormatGUID pfGUID, targetGUID;
|
WICPixelFormatGUID pfGUID, targetGUID;
|
||||||
const bool usewic = !metadata.IsPMAlpha() && UseWICConversion(filter, metadata.format, format, pfGUID, targetGUID);
|
const bool usewic = !metadata.IsPMAlpha() && UseWICConversion(options.filter, metadata.format, format, pfGUID, targetGUID);
|
||||||
|
|
||||||
switch (metadata.dimension)
|
switch (metadata.dimension)
|
||||||
{
|
{
|
||||||
@ -5185,11 +5282,11 @@ HRESULT DirectX::Convert(
|
|||||||
|
|
||||||
if (usewic)
|
if (usewic)
|
||||||
{
|
{
|
||||||
hr = ConvertUsingWIC(src, pfGUID, targetGUID, filter, threshold, dst);
|
hr = ConvertUsingWIC(src, pfGUID, targetGUID, options.filter, options.threshold, dst);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = ConvertCustom(src, filter, dst, threshold, 0);
|
hr = ConvertCustom(src, options.filter, dst, options.threshold, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@ -5197,6 +5294,15 @@ HRESULT DirectX::Convert(
|
|||||||
result.Release();
|
result.Release();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(index, nimages))
|
||||||
|
{
|
||||||
|
result.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -5238,11 +5344,11 @@ HRESULT DirectX::Convert(
|
|||||||
|
|
||||||
if (usewic)
|
if (usewic)
|
||||||
{
|
{
|
||||||
hr = ConvertUsingWIC(src, pfGUID, targetGUID, filter, threshold, dst);
|
hr = ConvertUsingWIC(src, pfGUID, targetGUID, options.filter, options.threshold, dst);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = ConvertCustom(src, filter, dst, threshold, slice);
|
hr = ConvertCustom(src, options.filter, dst, options.threshold, slice, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@ -5250,6 +5356,15 @@ HRESULT DirectX::Convert(
|
|||||||
result.Release();
|
result.Release();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(index, nimages))
|
||||||
|
{
|
||||||
|
result.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d > 1)
|
if (d > 1)
|
||||||
@ -5263,6 +5378,15 @@ HRESULT DirectX::Convert(
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (statusCallback)
|
||||||
|
{
|
||||||
|
if (!statusCallback(nimages, nimages))
|
||||||
|
{
|
||||||
|
result.Release();
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user