Resync DDSTextureLoader, WICTextureLoader

This commit is contained in:
Chuck Walbourn 2016-09-22 22:34:50 -07:00
parent d74689c111
commit 2f31eb519c
8 changed files with 1020 additions and 1020 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// File: DDSTextureLoader.h // File: DDSTextureLoader.h
// //
// Functions for loading a DDS texture and creating a Direct3D 11 runtime resource for it // Functions for loading a DDS texture and creating a Direct3D runtime resource for it
// //
// Note these functions are useful as a light-weight runtime loader for DDS files. For // Note these functions are useful as a light-weight runtime loader for DDS files. For
// a full-featured DDS file reader, writer, and texture processing pipeline see // a full-featured DDS file reader, writer, and texture processing pipeline see

View File

@ -1,7 +1,7 @@
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// File: DDSTextureLoader12.cpp // File: DDSTextureLoader12.cpp
// //
// Functions for loading a DDS texture and creating a Direct3D 12 runtime resource for it // Functions for loading a DDS texture and creating a Direct3D runtime resource for it
// //
// Note these functions are useful as a light-weight runtime loader for DDS files. For // Note these functions are useful as a light-weight runtime loader for DDS files. For
// a full-featured DDS file reader, writer, and texture processing pipeline see // a full-featured DDS file reader, writer, and texture processing pipeline see
@ -155,8 +155,8 @@ namespace
HRESULT LoadTextureDataFromFile( HRESULT LoadTextureDataFromFile(
_In_z_ const wchar_t* fileName, _In_z_ const wchar_t* fileName,
std::unique_ptr<uint8_t[]>& ddsData, std::unique_ptr<uint8_t[]>& ddsData,
DDS_HEADER** header, const DDS_HEADER** header,
uint8_t** bitData, const uint8_t** bitData,
size_t* bitSize) size_t* bitSize)
{ {
if (!header || !bitData || !bitSize) if (!header || !bitData || !bitSize)
@ -165,22 +165,22 @@ namespace
} }
// open the file // open the file
ScopedHandle hFile( safe_handle( CreateFile2( fileName, ScopedHandle hFile(safe_handle(CreateFile2(fileName,
GENERIC_READ, GENERIC_READ,
FILE_SHARE_READ, FILE_SHARE_READ,
OPEN_EXISTING, OPEN_EXISTING,
nullptr ) ) ); nullptr)));
if ( !hFile ) if (!hFile)
{ {
return HRESULT_FROM_WIN32( GetLastError() ); return HRESULT_FROM_WIN32(GetLastError());
} }
// Get the file size // Get the file size
FILE_STANDARD_INFO fileInfo; FILE_STANDARD_INFO fileInfo;
if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) ) if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo)))
{ {
return HRESULT_FROM_WIN32( GetLastError() ); return HRESULT_FROM_WIN32(GetLastError());
} }
// File is too big for 32-bit allocation, so reject read // File is too big for 32-bit allocation, so reject read
@ -190,13 +190,13 @@ namespace
} }
// Need at least enough data to fill the header and magic number to be a valid DDS // Need at least enough data to fill the header and magic number to be a valid DDS
if (fileInfo.EndOfFile.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) ) ) if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t)))
{ {
return E_FAIL; return E_FAIL;
} }
// create enough space for the file data // create enough space for the file data
ddsData.reset( new (std::nothrow) uint8_t[fileInfo.EndOfFile.LowPart ] ); ddsData.reset(new (std::nothrow) uint8_t[fileInfo.EndOfFile.LowPart]);
if (!ddsData) if (!ddsData)
{ {
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@ -204,14 +204,14 @@ namespace
// read the data in // read the data in
DWORD BytesRead = 0; DWORD BytesRead = 0;
if (!ReadFile( hFile.get(), if (!ReadFile(hFile.get(),
ddsData.get(), ddsData.get(),
fileInfo.EndOfFile.LowPart, fileInfo.EndOfFile.LowPart,
&BytesRead, &BytesRead,
nullptr nullptr
)) ))
{ {
return HRESULT_FROM_WIN32( GetLastError() ); return HRESULT_FROM_WIN32(GetLastError());
} }
if (BytesRead < fileInfo.EndOfFile.LowPart) if (BytesRead < fileInfo.EndOfFile.LowPart)
@ -220,13 +220,13 @@ namespace
} }
// DDS files always start with the same magic number ("DDS ") // DDS files always start with the same magic number ("DDS ")
uint32_t dwMagicNumber = *( const uint32_t* )( ddsData.get() ); uint32_t dwMagicNumber = *reinterpret_cast<const uint32_t*>(ddsData.get());
if (dwMagicNumber != DDS_MAGIC) if (dwMagicNumber != DDS_MAGIC)
{ {
return E_FAIL; return E_FAIL;
} }
auto hdr = reinterpret_cast<DDS_HEADER*>( ddsData.get() + sizeof( uint32_t ) ); auto hdr = reinterpret_cast<const DDS_HEADER*>(ddsData.get() + sizeof(uint32_t));
// Verify header to validate DDS file // Verify header to validate DDS file
if (hdr->size != sizeof(DDS_HEADER) || if (hdr->size != sizeof(DDS_HEADER) ||
@ -238,10 +238,10 @@ namespace
// Check for DX10 extension // Check for DX10 extension
bool bDXT10Header = false; bool bDXT10Header = false;
if ((hdr->ddspf.flags & DDS_FOURCC) && if ((hdr->ddspf.flags & DDS_FOURCC) &&
(MAKEFOURCC( 'D', 'X', '1', '0' ) == hdr->ddspf.fourCC)) (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC))
{ {
// Must be long enough for both headers and magic value // Must be long enough for both headers and magic value
if (fileInfo.EndOfFile.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10) ) ) if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10)))
{ {
return E_FAIL; return E_FAIL;
} }
@ -251,8 +251,8 @@ namespace
// setup the pointers in the process request // setup the pointers in the process request
*header = hdr; *header = hdr;
ptrdiff_t offset = sizeof( uint32_t ) + sizeof( DDS_HEADER ) ptrdiff_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER)
+ (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0); + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0);
*bitData = ddsData.get() + offset; *bitData = ddsData.get() + offset;
*bitSize = fileInfo.EndOfFile.LowPart - offset; *bitSize = fileInfo.EndOfFile.LowPart - offset;
@ -914,15 +914,15 @@ namespace
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
HRESULT CreateTextureResource( HRESULT CreateTextureResource(
_In_ ID3D12Device* d3dDevice, _In_ ID3D12Device* d3dDevice,
_In_ D3D12_RESOURCE_DIMENSION resDim, D3D12_RESOURCE_DIMENSION resDim,
_In_ size_t width, size_t width,
_In_ size_t height, size_t height,
_In_ size_t depth, size_t depth,
_In_ size_t mipCount, size_t mipCount,
_In_ size_t arraySize, size_t arraySize,
_In_ DXGI_FORMAT format, DXGI_FORMAT format,
_In_ D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
_In_ bool forceSRGB, unsigned int loadFlags,
_Outptr_ ID3D12Resource** texture) _Outptr_ ID3D12Resource** texture)
{ {
if (!d3dDevice) if (!d3dDevice)
@ -930,7 +930,7 @@ namespace
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
if (forceSRGB) if (loadFlags & DDS_LOADER_FORCE_SRGB)
{ {
format = MakeSRGB(format); format = MakeSRGB(format);
} }
@ -941,7 +941,7 @@ namespace
desc.MipLevels = static_cast<UINT16>(mipCount); desc.MipLevels = static_cast<UINT16>(mipCount);
desc.DepthOrArraySize = (resDim == D3D12_RESOURCE_DIMENSION_TEXTURE3D) ? static_cast<UINT16>(depth) : static_cast<UINT16>(arraySize); desc.DepthOrArraySize = (resDim == D3D12_RESOURCE_DIMENSION_TEXTURE3D) ? static_cast<UINT16>(depth) : static_cast<UINT16>(arraySize);
desc.Format = format; desc.Format = format;
desc.Flags = flags; desc.Flags = resFlags;
desc.SampleDesc.Count = 1; desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0; desc.SampleDesc.Quality = 0;
desc.Dimension = resDim; desc.Dimension = resDim;
@ -969,13 +969,12 @@ namespace
HRESULT CreateTextureFromDDS(_In_ ID3D12Device* d3dDevice, HRESULT CreateTextureFromDDS(_In_ ID3D12Device* d3dDevice,
_In_ const DDS_HEADER* header, _In_ const DDS_HEADER* header,
_In_reads_bytes_(bitSize) const uint8_t* bitData, _In_reads_bytes_(bitSize) const uint8_t* bitData,
_In_ size_t bitSize, size_t bitSize,
_In_ size_t maxsize, size_t maxsize,
_In_ D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
_In_ bool forceSRGB, unsigned int loadFlags,
_In_ bool reserveFullMipChain,
_Outptr_ ID3D12Resource** texture, _Outptr_ ID3D12Resource** texture,
_Out_ std::vector<D3D12_SUBRESOURCE_DATA>& subresources, std::vector<D3D12_SUBRESOURCE_DATA>& subresources,
_Out_opt_ bool* outIsCubeMap) _Out_opt_ bool* outIsCubeMap)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
@ -1165,13 +1164,13 @@ namespace
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
size_t reservedMips = mipCount; size_t reservedMips = mipCount;
if (reserveFullMipChain) if (loadFlags & DDS_LOADER_MIP_RESERVE)
{ {
reservedMips = std::min<size_t>(D3D12_REQ_MIP_LEVELS, CountMips(width, height)); reservedMips = std::min<size_t>(D3D12_REQ_MIP_LEVELS, CountMips(width, height));
} }
hr = CreateTextureResource(d3dDevice, resDim, twidth, theight, tdepth, reservedMips - skipMip, arraySize, hr = CreateTextureResource(d3dDevice, resDim, twidth, theight, tdepth, reservedMips - skipMip, arraySize,
format, flags, forceSRGB, texture); format, resFlags, loadFlags, texture);
if (FAILED(hr) && !maxsize && (mipCount > 1)) if (FAILED(hr) && !maxsize && (mipCount > 1))
{ {
@ -1184,7 +1183,7 @@ namespace
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = CreateTextureResource(d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, hr = CreateTextureResource(d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,
format, flags, forceSRGB, texture); format, resFlags, loadFlags, texture);
} }
} }
} }
@ -1224,7 +1223,6 @@ namespace
return DDS_ALPHA_MODE_UNKNOWN; return DDS_ALPHA_MODE_UNKNOWN;
} }
} // anonymous namespace } // anonymous namespace
@ -1246,8 +1244,7 @@ HRESULT DirectX::LoadDDSTextureFromMemory(
ddsDataSize, ddsDataSize,
maxsize, maxsize,
D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_FLAG_NONE,
false, DDS_LOADER_DEFAULT,
false,
texture, texture,
subresources, subresources,
alphaMode, alphaMode,
@ -1261,23 +1258,22 @@ HRESULT DirectX::LoadDDSTextureFromMemoryEx(
const uint8_t* ddsData, const uint8_t* ddsData,
size_t ddsDataSize, size_t ddsDataSize,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
ID3D12Resource** texture, ID3D12Resource** texture,
std::vector<D3D12_SUBRESOURCE_DATA>& subresources, std::vector<D3D12_SUBRESOURCE_DATA>& subresources,
DDS_ALPHA_MODE* alphaMode, DDS_ALPHA_MODE* alphaMode,
bool* isCubeMap ) bool* isCubeMap)
{ {
if ( texture ) if (texture)
{ {
*texture = nullptr; *texture = nullptr;
} }
if ( alphaMode ) if (alphaMode)
{ {
*alphaMode = DDS_ALPHA_MODE_UNKNOWN; *alphaMode = DDS_ALPHA_MODE_UNKNOWN;
} }
if ( isCubeMap ) if (isCubeMap)
{ {
*isCubeMap = false; *isCubeMap = false;
} }
@ -1293,13 +1289,13 @@ HRESULT DirectX::LoadDDSTextureFromMemoryEx(
return E_FAIL; return E_FAIL;
} }
uint32_t dwMagicNumber = *( const uint32_t* )( ddsData ); uint32_t dwMagicNumber = *(const uint32_t*)(ddsData);
if (dwMagicNumber != DDS_MAGIC) if (dwMagicNumber != DDS_MAGIC)
{ {
return E_FAIL; return E_FAIL;
} }
auto header = reinterpret_cast<const DDS_HEADER*>( ddsData + sizeof( uint32_t ) ); auto header = reinterpret_cast<const DDS_HEADER*>(ddsData + sizeof(uint32_t));
// Verify header to validate DDS file // Verify header to validate DDS file
if (header->size != sizeof(DDS_HEADER) || if (header->size != sizeof(DDS_HEADER) ||
@ -1311,7 +1307,7 @@ HRESULT DirectX::LoadDDSTextureFromMemoryEx(
// Check for DX10 extension // Check for DX10 extension
bool bDXT10Header = false; bool bDXT10Header = false;
if ((header->ddspf.flags & DDS_FOURCC) && if ((header->ddspf.flags & DDS_FOURCC) &&
(MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC) ) (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC))
{ {
// Must be long enough for both headers and magic value // Must be long enough for both headers and magic value
if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10))) if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10)))
@ -1322,23 +1318,23 @@ HRESULT DirectX::LoadDDSTextureFromMemoryEx(
bDXT10Header = true; bDXT10Header = true;
} }
ptrdiff_t offset = sizeof( uint32_t ) ptrdiff_t offset = sizeof(uint32_t)
+ sizeof( DDS_HEADER ) + sizeof(DDS_HEADER)
+ (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0); + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0);
HRESULT hr = CreateTextureFromDDS( d3dDevice, HRESULT hr = CreateTextureFromDDS(d3dDevice,
header, ddsData + offset, ddsDataSize - offset, maxsize, header, ddsData + offset, ddsDataSize - offset, maxsize,
flags, forceSRGB, reserveFullMipChain, resFlags, loadFlags,
texture, subresources, isCubeMap ); texture, subresources, isCubeMap);
if ( SUCCEEDED(hr) ) if (SUCCEEDED(hr))
{ {
if (texture != 0 && *texture != 0) if (texture != 0 && *texture != 0)
{ {
SetDebugObjectName(*texture, L"DDSTextureLoader"); SetDebugObjectName(*texture, L"DDSTextureLoader");
} }
if ( alphaMode ) if (alphaMode)
*alphaMode = GetAlphaMode( header ); *alphaMode = GetAlphaMode(header);
} }
return hr; return hr;
@ -1355,20 +1351,19 @@ HRESULT DirectX::LoadDDSTextureFromFile(
std::vector<D3D12_SUBRESOURCE_DATA>& subresources, std::vector<D3D12_SUBRESOURCE_DATA>& subresources,
size_t maxsize, size_t maxsize,
DDS_ALPHA_MODE* alphaMode, DDS_ALPHA_MODE* alphaMode,
bool* isCubeMap ) bool* isCubeMap)
{ {
return LoadDDSTextureFromFileEx( return LoadDDSTextureFromFileEx(
d3dDevice, d3dDevice,
fileName, fileName,
maxsize, maxsize,
D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_FLAG_NONE,
false, DDS_LOADER_DEFAULT,
false,
texture, texture,
ddsData, ddsData,
subresources, subresources,
alphaMode, alphaMode,
isCubeMap ); isCubeMap);
} }
_Use_decl_annotations_ _Use_decl_annotations_
@ -1376,24 +1371,23 @@ HRESULT DirectX::LoadDDSTextureFromFileEx(
ID3D12Device* d3dDevice, ID3D12Device* d3dDevice,
const wchar_t* fileName, const wchar_t* fileName,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
ID3D12Resource** texture, ID3D12Resource** texture,
std::unique_ptr<uint8_t[]>& ddsData, std::unique_ptr<uint8_t[]>& ddsData,
std::vector<D3D12_SUBRESOURCE_DATA>& subresources, std::vector<D3D12_SUBRESOURCE_DATA>& subresources,
DDS_ALPHA_MODE* alphaMode, DDS_ALPHA_MODE* alphaMode,
bool* isCubeMap ) bool* isCubeMap)
{ {
if ( texture ) if (texture)
{ {
*texture = nullptr; *texture = nullptr;
} }
if ( alphaMode ) if (alphaMode)
{ {
*alphaMode = DDS_ALPHA_MODE_UNKNOWN; *alphaMode = DDS_ALPHA_MODE_UNKNOWN;
} }
if ( isCubeMap ) if (isCubeMap)
{ {
*isCubeMap = false; *isCubeMap = false;
} }
@ -1403,11 +1397,11 @@ HRESULT DirectX::LoadDDSTextureFromFileEx(
return E_INVALIDARG; return E_INVALIDARG;
} }
DDS_HEADER* header = nullptr; const DDS_HEADER* header = nullptr;
uint8_t* bitData = nullptr; const uint8_t* bitData = nullptr;
size_t bitSize = 0; size_t bitSize = 0;
HRESULT hr = LoadTextureDataFromFile( fileName, HRESULT hr = LoadTextureDataFromFile(fileName,
ddsData, ddsData,
&header, &header,
&bitData, &bitData,
@ -1418,18 +1412,18 @@ HRESULT DirectX::LoadDDSTextureFromFileEx(
return hr; return hr;
} }
hr = CreateTextureFromDDS( d3dDevice, hr = CreateTextureFromDDS(d3dDevice,
header, bitData, bitSize, maxsize, header, bitData, bitSize, maxsize,
flags, forceSRGB, reserveFullMipChain, resFlags, loadFlags,
texture, subresources, isCubeMap ); texture, subresources, isCubeMap);
if ( SUCCEEDED(hr) ) if (SUCCEEDED(hr))
{ {
#if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) #if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
if (texture != 0) if (texture != 0)
{ {
CHAR strFileA[MAX_PATH]; CHAR strFileA[MAX_PATH];
int result = WideCharToMultiByte( CP_ACP, int result = WideCharToMultiByte(CP_ACP,
WC_NO_BEST_FIT_CHARS, WC_NO_BEST_FIT_CHARS,
fileName, fileName,
-1, -1,
@ -1438,7 +1432,7 @@ HRESULT DirectX::LoadDDSTextureFromFileEx(
nullptr, nullptr,
FALSE FALSE
); );
if ( result > 0 ) if (result > 0)
{ {
const wchar_t* pstrName = wcsrchr(fileName, '\\'); const wchar_t* pstrName = wcsrchr(fileName, '\\');
if (!pstrName) if (!pstrName)
@ -1458,8 +1452,8 @@ HRESULT DirectX::LoadDDSTextureFromFileEx(
} }
#endif #endif
if ( alphaMode ) if (alphaMode)
*alphaMode = GetAlphaMode( header ); *alphaMode = GetAlphaMode(header);
} }
return hr; return hr;

View File

@ -1,7 +1,7 @@
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// File: DDSTextureLoader12.h // File: DDSTextureLoader12.h
// //
// Functions for loading a DDS texture and creating a Direct3D 12 runtime resource for it // Functions for loading a DDS texture and creating a Direct3D runtime resource for it
// //
// Note these functions are useful as a light-weight runtime loader for DDS files. For // Note these functions are useful as a light-weight runtime loader for DDS files. For
// a full-featured DDS file reader, writer, and texture processing pipeline see // a full-featured DDS file reader, writer, and texture processing pipeline see
@ -38,6 +38,13 @@ namespace DirectX
DDS_ALPHA_MODE_CUSTOM = 4, DDS_ALPHA_MODE_CUSTOM = 4,
}; };
enum DDS_LOADER_FLAGS
{
DDS_LOADER_DEFAULT = 0,
DDS_LOADER_FORCE_SRGB = 0x1,
DDS_LOADER_MIP_RESERVE = 0x8,
};
// Standard version // Standard version
HRESULT __cdecl LoadDDSTextureFromMemory( HRESULT __cdecl LoadDDSTextureFromMemory(
_In_ ID3D12Device* d3dDevice, _In_ ID3D12Device* d3dDevice,
@ -65,9 +72,8 @@ namespace DirectX
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
size_t ddsDataSize, size_t ddsDataSize,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
_Outptr_ ID3D12Resource** texture, _Outptr_ ID3D12Resource** texture,
std::vector<D3D12_SUBRESOURCE_DATA>& subresources, std::vector<D3D12_SUBRESOURCE_DATA>& subresources,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr,
@ -77,9 +83,8 @@ namespace DirectX
_In_ ID3D12Device* d3dDevice, _In_ ID3D12Device* d3dDevice,
_In_z_ const wchar_t* szFileName, _In_z_ const wchar_t* szFileName,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
_Outptr_ ID3D12Resource** texture, _Outptr_ ID3D12Resource** texture,
std::unique_ptr<uint8_t[]>& ddsData, std::unique_ptr<uint8_t[]>& ddsData,
std::vector<D3D12_SUBRESOURCE_DATA>& subresources, std::vector<D3D12_SUBRESOURCE_DATA>& subresources,

View File

@ -1,7 +1,7 @@
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// File: WICTextureLoader.cpp // File: WICTextureLoader.cpp
// //
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it // Function for loading a WIC image and creating a Direct3D runtime texture for it
// (auto-generating mipmaps if possible) // (auto-generating mipmaps if possible)
// //
// Note: Assumes application has already called CoInitializeEx // Note: Assumes application has already called CoInitializeEx
@ -43,20 +43,21 @@
#pragma comment(lib,"dxguid.lib") #pragma comment(lib,"dxguid.lib")
#endif #endif
using namespace DirectX;
using Microsoft::WRL::ComPtr; using Microsoft::WRL::ComPtr;
namespace namespace
{ {
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
template<UINT TNameLength> template<UINT TNameLength>
inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char (&name)[TNameLength]) inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char(&name)[TNameLength])
{ {
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) #if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name); resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name);
#else #else
UNREFERENCED_PARAMETER(resource); UNREFERENCED_PARAMETER(resource);
UNREFERENCED_PARAMETER(name); UNREFERENCED_PARAMETER(name);
#endif #endif
} }
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
@ -174,7 +175,7 @@ namespace
InitOnceExecuteOnce(&s_initOnce, InitOnceExecuteOnce(&s_initOnce,
[](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL [](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL
{ {
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance( HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2, CLSID_WICImagingFactory2,
nullptr, nullptr,
@ -183,7 +184,7 @@ namespace
factory factory
); );
if ( SUCCEEDED(hr) ) if (SUCCEEDED(hr))
{ {
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed // WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true; g_WIC2 = true;
@ -200,63 +201,63 @@ namespace
); );
return SUCCEEDED(hr) ? TRUE : FALSE; return SUCCEEDED(hr) ? TRUE : FALSE;
} }
#else #else
return SUCCEEDED( CoCreateInstance( return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory, CLSID_WICImagingFactory,
nullptr, nullptr,
CLSCTX_INPROC_SERVER, CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory), __uuidof(IWICImagingFactory),
factory) ) ? TRUE : FALSE; factory)) ? TRUE : FALSE;
#endif #endif
}, nullptr, reinterpret_cast<LPVOID*>(&factory)); }, nullptr, reinterpret_cast<LPVOID*>(&factory));
return factory; return factory;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
DXGI_FORMAT _WICToDXGI( const GUID& guid ) DXGI_FORMAT _WICToDXGI(const GUID& guid)
{ {
for( size_t i=0; i < _countof(g_WICFormats); ++i ) for (size_t i = 0; i < _countof(g_WICFormats); ++i)
{ {
if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 ) if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0)
return g_WICFormats[i].format; return g_WICFormats[i].format;
} }
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
if ( g_WIC2 ) if (g_WIC2)
{ {
if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 ) if (memcmp(&GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID)) == 0)
return DXGI_FORMAT_R32G32B32_FLOAT; return DXGI_FORMAT_R32G32B32_FLOAT;
} }
#endif #endif
return DXGI_FORMAT_UNKNOWN; return DXGI_FORMAT_UNKNOWN;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
size_t _WICBitsPerPixel( REFGUID targetGuid ) size_t _WICBitsPerPixel(REFGUID targetGuid)
{ {
IWICImagingFactory* pWIC = _GetWIC(); auto pWIC = _GetWIC();
if ( !pWIC ) if (!pWIC)
return 0; return 0;
ComPtr<IWICComponentInfo> cinfo; ComPtr<IWICComponentInfo> cinfo;
if ( FAILED( pWIC->CreateComponentInfo( targetGuid, cinfo.GetAddressOf() ) ) ) if (FAILED(pWIC->CreateComponentInfo(targetGuid, cinfo.GetAddressOf())))
return 0; return 0;
WICComponentType type; WICComponentType type;
if ( FAILED( cinfo->GetComponentType( &type ) ) ) if (FAILED(cinfo->GetComponentType(&type)))
return 0; return 0;
if ( type != WICPixelFormat ) if (type != WICPixelFormat)
return 0; return 0;
ComPtr<IWICPixelFormatInfo> pfinfo; ComPtr<IWICPixelFormatInfo> pfinfo;
if ( FAILED( cinfo.As( &pfinfo ) ) ) if (FAILED(cinfo.As(&pfinfo)))
return 0; return 0;
UINT bpp; UINT bpp;
if ( FAILED( pfinfo->GetBitsPerPixel( &bpp ) ) ) if (FAILED(pfinfo->GetBitsPerPixel(&bpp)))
return 0; return 0;
return bpp; return bpp;
@ -264,9 +265,9 @@ namespace
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT format ) DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format)
{ {
switch( format ) switch (format)
{ {
case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_R8G8B8A8_UNORM:
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
@ -296,8 +297,7 @@ namespace
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
HRESULT CreateTextureFromWIC( HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice,
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext, _In_opt_ ID3D11DeviceContext* d3dContext,
_In_ IWICBitmapFrameDecode *frame, _In_ IWICBitmapFrameDecode *frame,
_In_ size_t maxsize, _In_ size_t maxsize,
@ -305,24 +305,24 @@ namespace
_In_ unsigned int bindFlags, _In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags, _In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags, _In_ unsigned int miscFlags,
_In_ bool forceSRGB, _In_ unsigned int loadFlags,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView ) _Outptr_opt_ ID3D11ShaderResourceView** textureView)
{ {
UINT width, height; UINT width, height;
HRESULT hr = frame->GetSize( &width, &height ); HRESULT hr = frame->GetSize(&width, &height);
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
assert( width > 0 && height > 0 ); assert(width > 0 && height > 0);
if ( !maxsize ) if (!maxsize)
{ {
// This is a bit conservative because the hardware could support larger textures than // This is a bit conservative because the hardware could support larger textures than
// the Feature Level defined minimums, but doing it this way is much easier and more // the Feature Level defined minimums, but doing it this way is much easier and more
// performant for WIC than the 'fail and retry' model used by DDSTextureLoader // performant for WIC than the 'fail and retry' model used by DDSTextureLoader
switch( d3dDevice->GetFeatureLevel() ) switch (d3dDevice->GetFeatureLevel())
{ {
case D3D_FEATURE_LEVEL_9_1: case D3D_FEATURE_LEVEL_9_1:
case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_2:
@ -344,23 +344,23 @@ namespace
} }
} }
assert( maxsize > 0 ); assert(maxsize > 0);
UINT twidth, theight; UINT twidth, theight;
if ( width > maxsize || height > maxsize ) if (width > maxsize || height > maxsize)
{ {
float ar = static_cast<float>(height) / static_cast<float>(width); float ar = static_cast<float>(height) / static_cast<float>(width);
if ( width > height ) if (width > height)
{ {
twidth = static_cast<UINT>( maxsize ); twidth = static_cast<UINT>(maxsize);
theight = static_cast<UINT>( static_cast<float>(maxsize) * ar ); theight = static_cast<UINT>(static_cast<float>(maxsize) * ar);
} }
else else
{ {
theight = static_cast<UINT>( maxsize ); theight = static_cast<UINT>(maxsize);
twidth = static_cast<UINT>( static_cast<float>(maxsize) / ar ); twidth = static_cast<UINT>(static_cast<float>(maxsize) / ar);
} }
assert( twidth <= maxsize && theight <= maxsize ); assert(twidth <= maxsize && theight <= maxsize);
} }
else else
{ {
@ -370,112 +370,112 @@ namespace
// Determine format // Determine format
WICPixelFormatGUID pixelFormat; WICPixelFormatGUID pixelFormat;
hr = frame->GetPixelFormat( &pixelFormat ); hr = frame->GetPixelFormat(&pixelFormat);
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
WICPixelFormatGUID convertGUID; WICPixelFormatGUID convertGUID;
memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) ); memcpy(&convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID));
size_t bpp = 0; size_t bpp = 0;
DXGI_FORMAT format = _WICToDXGI( pixelFormat ); DXGI_FORMAT format = _WICToDXGI(pixelFormat);
if ( format == DXGI_FORMAT_UNKNOWN ) if (format == DXGI_FORMAT_UNKNOWN)
{ {
if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) if (memcmp(&GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
{ {
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
if ( g_WIC2 ) if (g_WIC2)
{ {
memcpy( &convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) ); memcpy(&convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID));
format = DXGI_FORMAT_R32G32B32_FLOAT; format = DXGI_FORMAT_R32G32B32_FLOAT;
} }
else else
#endif #endif
{ {
memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); memcpy(&convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID));
format = DXGI_FORMAT_R32G32B32A32_FLOAT; format = DXGI_FORMAT_R32G32B32A32_FLOAT;
} }
} }
else else
{ {
for( size_t i=0; i < _countof(g_WICConvert); ++i ) for (size_t i = 0; i < _countof(g_WICConvert); ++i)
{ {
if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
{ {
memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) ); memcpy(&convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID));
format = _WICToDXGI( g_WICConvert[i].target ); format = _WICToDXGI(g_WICConvert[i].target);
assert( format != DXGI_FORMAT_UNKNOWN ); assert(format != DXGI_FORMAT_UNKNOWN);
bpp = _WICBitsPerPixel( convertGUID ); bpp = _WICBitsPerPixel(convertGUID);
break; break;
} }
} }
} }
if ( format == DXGI_FORMAT_UNKNOWN ) if (format == DXGI_FORMAT_UNKNOWN)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
} }
else else
{ {
bpp = _WICBitsPerPixel( pixelFormat ); bpp = _WICBitsPerPixel(pixelFormat);
} }
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
if ( (format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0 ) if ((format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0)
{ {
// Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT // Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT
UINT fmtSupport = 0; UINT fmtSupport = 0;
hr = d3dDevice->CheckFormatSupport( DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport ); hr = d3dDevice->CheckFormatSupport(DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport);
if ( FAILED(hr) || !( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) if (FAILED(hr) || !(fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
{ {
// Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up // Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up
memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); memcpy(&convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID));
format = DXGI_FORMAT_R32G32B32A32_FLOAT; format = DXGI_FORMAT_R32G32B32A32_FLOAT;
bpp = 128; bpp = 128;
} }
} }
#endif #endif
if ( !bpp ) if (!bpp)
return E_FAIL; return E_FAIL;
// Handle sRGB formats // Handle sRGB formats
if ( forceSRGB ) if (loadFlags & WIC_LOADER_FORCE_SRGB)
{ {
format = MakeSRGB( format ); format = MakeSRGB(format);
} }
else else if (!(loadFlags & WIC_LOADER_IGNORE_SRGB))
{ {
ComPtr<IWICMetadataQueryReader> metareader; ComPtr<IWICMetadataQueryReader> metareader;
if ( SUCCEEDED( frame->GetMetadataQueryReader( metareader.GetAddressOf() ) ) ) if (SUCCEEDED(frame->GetMetadataQueryReader(metareader.GetAddressOf())))
{ {
GUID containerFormat; GUID containerFormat;
if ( SUCCEEDED( metareader->GetContainerFormat( &containerFormat ) ) ) if (SUCCEEDED(metareader->GetContainerFormat(&containerFormat)))
{ {
// Check for sRGB colorspace metadata // Check for sRGB colorspace metadata
bool sRGB = false; bool sRGB = false;
PROPVARIANT value; PROPVARIANT value;
PropVariantInit( &value ); PropVariantInit(&value);
if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 ) if (memcmp(&containerFormat, &GUID_ContainerFormatPng, sizeof(GUID)) == 0)
{ {
// Check for sRGB chunk // Check for sRGB chunk
if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 ) if (SUCCEEDED(metareader->GetMetadataByName(L"/sRGB/RenderingIntent", &value)) && value.vt == VT_UI1)
{ {
sRGB = true; sRGB = true;
} }
} }
else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 ) else if (SUCCEEDED(metareader->GetMetadataByName(L"System.Image.ColorSpace", &value)) && value.vt == VT_UI2 && value.uiVal == 1)
{ {
sRGB = true; sRGB = true;
} }
PropVariantClear( &value ); PropVariantClear(&value);
if ( sRGB ) if (sRGB)
format = MakeSRGB( format ); format = MakeSRGB(format);
} }
} }
} }
@ -483,119 +483,119 @@ namespace
// Verify our target format is supported by the current device // Verify our target format is supported by the current device
// (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
UINT support = 0; UINT support = 0;
hr = d3dDevice->CheckFormatSupport( format, &support ); hr = d3dDevice->CheckFormatSupport(format, &support);
if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) if (FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
{ {
// Fallback to RGBA 32-bit format which is supported by all devices // Fallback to RGBA 32-bit format which is supported by all devices
memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) ); memcpy(&convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID));
format = DXGI_FORMAT_R8G8B8A8_UNORM; format = DXGI_FORMAT_R8G8B8A8_UNORM;
bpp = 32; bpp = 32;
} }
// Allocate temporary memory for image // Allocate temporary memory for image
size_t rowPitch = ( twidth * bpp + 7 ) / 8; size_t rowPitch = (twidth * bpp + 7) / 8;
size_t imageSize = rowPitch * theight; size_t imageSize = rowPitch * theight;
std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ imageSize ] ); std::unique_ptr<uint8_t[]> temp(new (std::nothrow) uint8_t[imageSize]);
if (!temp) if (!temp)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
// Load image data // Load image data
if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0 if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0
&& twidth == width && twidth == width
&& theight == height ) && theight == height)
{ {
// No format conversion or resize needed // No format conversion or resize needed
hr = frame->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); hr = frame->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
} }
else if ( twidth != width || theight != height ) else if (twidth != width || theight != height)
{ {
// Resize // Resize
IWICImagingFactory* pWIC = _GetWIC(); auto pWIC = _GetWIC();
if ( !pWIC ) if (!pWIC)
return E_NOINTERFACE; return E_NOINTERFACE;
ComPtr<IWICBitmapScaler> scaler; ComPtr<IWICBitmapScaler> scaler;
hr = pWIC->CreateBitmapScaler( scaler.GetAddressOf() ); hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant ); hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant);
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
WICPixelFormatGUID pfScaler; WICPixelFormatGUID pfScaler;
hr = scaler->GetPixelFormat( &pfScaler ); hr = scaler->GetPixelFormat(&pfScaler);
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 ) if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0)
{ {
// No format conversion needed // No format conversion needed
hr = scaler->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); hr = scaler->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
} }
else else
{ {
ComPtr<IWICFormatConverter> FC; ComPtr<IWICFormatConverter> FC;
hr = pWIC->CreateFormatConverter( FC.GetAddressOf() ); hr = pWIC->CreateFormatConverter(FC.GetAddressOf());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
BOOL canConvert = FALSE; BOOL canConvert = FALSE;
hr = FC->CanConvert( pfScaler, convertGUID, &canConvert ); hr = FC->CanConvert(pfScaler, convertGUID, &canConvert);
if ( FAILED(hr) || !canConvert ) if (FAILED(hr) || !canConvert)
{ {
return E_UNEXPECTED; return E_UNEXPECTED;
} }
hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
} }
} }
else else
{ {
// Format conversion but no resize // Format conversion but no resize
IWICImagingFactory* pWIC = _GetWIC(); auto pWIC = _GetWIC();
if ( !pWIC ) if (!pWIC)
return E_NOINTERFACE; return E_NOINTERFACE;
ComPtr<IWICFormatConverter> FC; ComPtr<IWICFormatConverter> FC;
hr = pWIC->CreateFormatConverter( FC.GetAddressOf() ); hr = pWIC->CreateFormatConverter(FC.GetAddressOf());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
BOOL canConvert = FALSE; BOOL canConvert = FALSE;
hr = FC->CanConvert( pixelFormat, convertGUID, &canConvert ); hr = FC->CanConvert(pixelFormat, convertGUID, &canConvert);
if ( FAILED(hr) || !canConvert ) if (FAILED(hr) || !canConvert)
{ {
return E_UNEXPECTED; return E_UNEXPECTED;
} }
hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
} }
// See if format is supported for auto-gen mipmaps (varies by feature level) // See if format is supported for auto-gen mipmaps (varies by feature level)
bool autogen = false; bool autogen = false;
if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps if (d3dContext != 0 && textureView != 0) // Must have context and shader-view to auto generate mipmaps
{ {
UINT fmtSupport = 0; UINT fmtSupport = 0;
hr = d3dDevice->CheckFormatSupport( format, &fmtSupport ); hr = d3dDevice->CheckFormatSupport(format, &fmtSupport);
if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) if (SUCCEEDED(hr) && (fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
{ {
autogen = true; autogen = true;
} }
@ -613,7 +613,7 @@ namespace
desc.Usage = usage; desc.Usage = usage;
desc.CPUAccessFlags = cpuAccessFlags; desc.CPUAccessFlags = cpuAccessFlags;
if ( autogen ) if (autogen)
{ {
desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET; desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET;
desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS; desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS;
@ -626,12 +626,12 @@ namespace
D3D11_SUBRESOURCE_DATA initData; D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = temp.get(); initData.pSysMem = temp.get();
initData.SysMemPitch = static_cast<UINT>( rowPitch ); initData.SysMemPitch = static_cast<UINT>(rowPitch);
initData.SysMemSlicePitch = static_cast<UINT>( imageSize ); initData.SysMemSlicePitch = static_cast<UINT>(imageSize);
ID3D11Texture2D* tex = nullptr; ID3D11Texture2D* tex = nullptr;
hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex ); hr = d3dDevice->CreateTexture2D(&desc, (autogen) ? nullptr : &initData, &tex);
if ( SUCCEEDED(hr) && tex != 0 ) if (SUCCEEDED(hr) && tex != 0)
{ {
if (textureView != 0) if (textureView != 0)
{ {
@ -641,18 +641,18 @@ namespace
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;
hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView ); hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
if ( FAILED(hr) ) if (FAILED(hr))
{ {
tex->Release(); tex->Release();
return hr; return hr;
} }
if ( autogen ) if (autogen)
{ {
assert( d3dContext != 0 ); assert(d3dContext != 0);
d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) ); d3dContext->UpdateSubresource(tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize));
d3dContext->GenerateMips( *textureView ); d3dContext->GenerateMips(*textureView);
} }
} }
@ -673,34 +673,34 @@ namespace
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
_Use_decl_annotations_ _Use_decl_annotations_
HRESULT DirectX::CreateWICTextureFromMemory( ID3D11Device* d3dDevice, HRESULT DirectX::CreateWICTextureFromMemory(ID3D11Device* d3dDevice,
const uint8_t* wicData, const uint8_t* wicData,
size_t wicDataSize, size_t wicDataSize,
ID3D11Resource** texture, ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView, ID3D11ShaderResourceView** textureView,
size_t maxsize ) size_t maxsize)
{ {
return CreateWICTextureFromMemoryEx( d3dDevice, nullptr, wicData, wicDataSize, maxsize, return CreateWICTextureFromMemoryEx(d3dDevice, nullptr, wicData, wicDataSize, maxsize,
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, WIC_LOADER_DEFAULT,
texture, textureView ); texture, textureView);
} }
_Use_decl_annotations_ _Use_decl_annotations_
HRESULT DirectX::CreateWICTextureFromMemory( ID3D11Device* d3dDevice, HRESULT DirectX::CreateWICTextureFromMemory(ID3D11Device* d3dDevice,
ID3D11DeviceContext* d3dContext, ID3D11DeviceContext* d3dContext,
const uint8_t* wicData, const uint8_t* wicData,
size_t wicDataSize, size_t wicDataSize,
ID3D11Resource** texture, ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView, ID3D11ShaderResourceView** textureView,
size_t maxsize ) size_t maxsize)
{ {
return CreateWICTextureFromMemoryEx( d3dDevice, d3dContext, wicData, wicDataSize, maxsize, return CreateWICTextureFromMemoryEx(d3dDevice, d3dContext, wicData, wicDataSize, maxsize,
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, WIC_LOADER_DEFAULT,
texture, textureView ); texture, textureView);
} }
_Use_decl_annotations_ _Use_decl_annotations_
HRESULT DirectX::CreateWICTextureFromMemoryEx( ID3D11Device* d3dDevice, HRESULT DirectX::CreateWICTextureFromMemoryEx(ID3D11Device* d3dDevice,
const uint8_t* wicData, const uint8_t* wicData,
size_t wicDataSize, size_t wicDataSize,
size_t maxsize, size_t maxsize,
@ -708,17 +708,17 @@ HRESULT DirectX::CreateWICTextureFromMemoryEx( ID3D11Device* d3dDevice,
unsigned int bindFlags, unsigned int bindFlags,
unsigned int cpuAccessFlags, unsigned int cpuAccessFlags,
unsigned int miscFlags, unsigned int miscFlags,
bool forceSRGB, unsigned int loadFlags,
ID3D11Resource** texture, ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView ) ID3D11ShaderResourceView** textureView)
{ {
return CreateWICTextureFromMemoryEx( d3dDevice, nullptr, wicData, wicDataSize, maxsize, return CreateWICTextureFromMemoryEx(d3dDevice, nullptr, wicData, wicDataSize, maxsize,
usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, usage, bindFlags, cpuAccessFlags, miscFlags, loadFlags,
texture, textureView ); texture, textureView);
} }
_Use_decl_annotations_ _Use_decl_annotations_
HRESULT DirectX::CreateWICTextureFromMemoryEx( ID3D11Device* d3dDevice, HRESULT DirectX::CreateWICTextureFromMemoryEx(ID3D11Device* d3dDevice,
ID3D11DeviceContext* d3dContext, ID3D11DeviceContext* d3dContext,
const uint8_t* wicData, const uint8_t* wicData,
size_t wicDataSize, size_t wicDataSize,
@ -727,15 +727,15 @@ HRESULT DirectX::CreateWICTextureFromMemoryEx( ID3D11Device* d3dDevice,
unsigned int bindFlags, unsigned int bindFlags,
unsigned int cpuAccessFlags, unsigned int cpuAccessFlags,
unsigned int miscFlags, unsigned int miscFlags,
bool forceSRGB, unsigned int loadFlags,
ID3D11Resource** texture, ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView ) ID3D11ShaderResourceView** textureView)
{ {
if ( texture ) if (texture)
{ {
*texture = nullptr; *texture = nullptr;
} }
if ( textureView ) if (textureView)
{ {
*textureView = nullptr; *textureView = nullptr;
} }
@ -743,41 +743,41 @@ HRESULT DirectX::CreateWICTextureFromMemoryEx( ID3D11Device* d3dDevice,
if (!d3dDevice || !wicData || (!texture && !textureView)) if (!d3dDevice || !wicData || (!texture && !textureView))
return E_INVALIDARG; return E_INVALIDARG;
if ( !wicDataSize ) if (!wicDataSize)
return E_FAIL; return E_FAIL;
if ( wicDataSize > UINT32_MAX ) if (wicDataSize > UINT32_MAX)
return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE ); return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
IWICImagingFactory* pWIC = _GetWIC(); auto pWIC = _GetWIC();
if ( !pWIC ) if (!pWIC)
return E_NOINTERFACE; return E_NOINTERFACE;
// Create input stream for memory // Create input stream for memory
ComPtr<IWICStream> stream; ComPtr<IWICStream> stream;
HRESULT hr = pWIC->CreateStream( stream.GetAddressOf() ); HRESULT hr = pWIC->CreateStream(stream.GetAddressOf());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
hr = stream->InitializeFromMemory( const_cast<uint8_t*>( wicData ), static_cast<DWORD>( wicDataSize ) ); hr = stream->InitializeFromMemory(const_cast<uint8_t*>(wicData), static_cast<DWORD>(wicDataSize));
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
// Initialize WIC // Initialize WIC
ComPtr<IWICBitmapDecoder> decoder; ComPtr<IWICBitmapDecoder> decoder;
hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() ); hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
ComPtr<IWICBitmapFrameDecode> frame; ComPtr<IWICBitmapFrameDecode> frame;
hr = decoder->GetFrame( 0, frame.GetAddressOf() ); hr = decoder->GetFrame(0, frame.GetAddressOf());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
hr = CreateTextureFromWIC( d3dDevice, d3dContext, frame.Get(), maxsize, hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), maxsize,
usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, usage, bindFlags, cpuAccessFlags, miscFlags, loadFlags,
texture, textureView ); texture, textureView);
if ( FAILED(hr)) if (FAILED(hr))
return hr; return hr;
if (texture != 0 && *texture != 0) if (texture != 0 && *texture != 0)
@ -795,49 +795,49 @@ HRESULT DirectX::CreateWICTextureFromMemoryEx( ID3D11Device* d3dDevice,
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
_Use_decl_annotations_ _Use_decl_annotations_
HRESULT DirectX::CreateWICTextureFromFile( ID3D11Device* d3dDevice, HRESULT DirectX::CreateWICTextureFromFile(ID3D11Device* d3dDevice,
const wchar_t* fileName, const wchar_t* fileName,
ID3D11Resource** texture, ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView, ID3D11ShaderResourceView** textureView,
size_t maxsize ) size_t maxsize)
{ {
return CreateWICTextureFromFileEx( d3dDevice, nullptr, fileName, maxsize, return CreateWICTextureFromFileEx(d3dDevice, nullptr, fileName, maxsize,
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, WIC_LOADER_DEFAULT,
texture, textureView ); texture, textureView);
} }
_Use_decl_annotations_ _Use_decl_annotations_
HRESULT DirectX::CreateWICTextureFromFile( ID3D11Device* d3dDevice, HRESULT DirectX::CreateWICTextureFromFile(ID3D11Device* d3dDevice,
ID3D11DeviceContext* d3dContext, ID3D11DeviceContext* d3dContext,
const wchar_t* fileName, const wchar_t* fileName,
ID3D11Resource** texture, ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView, ID3D11ShaderResourceView** textureView,
size_t maxsize ) size_t maxsize)
{ {
return CreateWICTextureFromFileEx( d3dDevice, d3dContext, fileName, maxsize, return CreateWICTextureFromFileEx(d3dDevice, d3dContext, fileName, maxsize,
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, WIC_LOADER_DEFAULT,
texture, textureView ); texture, textureView);
} }
_Use_decl_annotations_ _Use_decl_annotations_
HRESULT DirectX::CreateWICTextureFromFileEx( ID3D11Device* d3dDevice, HRESULT DirectX::CreateWICTextureFromFileEx(ID3D11Device* d3dDevice,
const wchar_t* fileName, const wchar_t* fileName,
size_t maxsize, size_t maxsize,
D3D11_USAGE usage, D3D11_USAGE usage,
unsigned int bindFlags, unsigned int bindFlags,
unsigned int cpuAccessFlags, unsigned int cpuAccessFlags,
unsigned int miscFlags, unsigned int miscFlags,
bool forceSRGB, unsigned int loadFlags,
ID3D11Resource** texture, ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView ) ID3D11ShaderResourceView** textureView)
{ {
return CreateWICTextureFromFileEx( d3dDevice, nullptr, fileName, maxsize, return CreateWICTextureFromFileEx(d3dDevice, nullptr, fileName, maxsize,
usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, usage, bindFlags, cpuAccessFlags, miscFlags, loadFlags,
texture, textureView ); texture, textureView);
} }
_Use_decl_annotations_ _Use_decl_annotations_
HRESULT DirectX::CreateWICTextureFromFileEx( ID3D11Device* d3dDevice, HRESULT DirectX::CreateWICTextureFromFileEx(ID3D11Device* d3dDevice,
ID3D11DeviceContext* d3dContext, ID3D11DeviceContext* d3dContext,
const wchar_t* fileName, const wchar_t* fileName,
size_t maxsize, size_t maxsize,
@ -845,15 +845,15 @@ HRESULT DirectX::CreateWICTextureFromFileEx( ID3D11Device* d3dDevice,
unsigned int bindFlags, unsigned int bindFlags,
unsigned int cpuAccessFlags, unsigned int cpuAccessFlags,
unsigned int miscFlags, unsigned int miscFlags,
bool forceSRGB, unsigned int loadFlags,
ID3D11Resource** texture, ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView ) ID3D11ShaderResourceView** textureView)
{ {
if ( texture ) if (texture)
{ {
*texture = nullptr; *texture = nullptr;
} }
if ( textureView ) if (textureView)
{ {
*textureView = nullptr; *textureView = nullptr;
} }
@ -861,32 +861,32 @@ HRESULT DirectX::CreateWICTextureFromFileEx( ID3D11Device* d3dDevice,
if (!d3dDevice || !fileName || (!texture && !textureView)) if (!d3dDevice || !fileName || (!texture && !textureView))
return E_INVALIDARG; return E_INVALIDARG;
IWICImagingFactory* pWIC = _GetWIC(); auto pWIC = _GetWIC();
if ( !pWIC ) if (!pWIC)
return E_NOINTERFACE; return E_NOINTERFACE;
// Initialize WIC // Initialize WIC
ComPtr<IWICBitmapDecoder> decoder; ComPtr<IWICBitmapDecoder> decoder;
HRESULT hr = pWIC->CreateDecoderFromFilename( fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() ); HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
ComPtr<IWICBitmapFrameDecode> frame; ComPtr<IWICBitmapFrameDecode> frame;
hr = decoder->GetFrame( 0, frame.GetAddressOf() ); hr = decoder->GetFrame(0, frame.GetAddressOf());
if ( FAILED(hr) ) if (FAILED(hr))
return hr; return hr;
hr = CreateTextureFromWIC( d3dDevice, d3dContext, frame.Get(), maxsize, hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), maxsize,
usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, usage, bindFlags, cpuAccessFlags, miscFlags, loadFlags,
texture, textureView ); texture, textureView);
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) #if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
if ( SUCCEEDED(hr) ) if (SUCCEEDED(hr))
{ {
if (texture != 0 || textureView != 0) if (texture != 0 || textureView != 0)
{ {
CHAR strFileA[MAX_PATH]; CHAR strFileA[MAX_PATH];
int result = WideCharToMultiByte( CP_ACP, int result = WideCharToMultiByte(CP_ACP,
WC_NO_BEST_FIT_CHARS, WC_NO_BEST_FIT_CHARS,
fileName, fileName,
-1, -1,
@ -895,9 +895,9 @@ HRESULT DirectX::CreateWICTextureFromFileEx( ID3D11Device* d3dDevice,
nullptr, nullptr,
FALSE FALSE
); );
if ( result > 0 ) if (result > 0)
{ {
const CHAR* pstrName = strrchr( strFileA, '\\' ); const CHAR* pstrName = strrchr(strFileA, '\\');
if (!pstrName) if (!pstrName)
{ {
pstrName = strFileA; pstrName = strFileA;
@ -909,16 +909,16 @@ HRESULT DirectX::CreateWICTextureFromFileEx( ID3D11Device* d3dDevice,
if (texture != 0 && *texture != 0) if (texture != 0 && *texture != 0)
{ {
(*texture)->SetPrivateData( WKPDID_D3DDebugObjectName, (*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
static_cast<UINT>( strnlen_s(pstrName, MAX_PATH) ), static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
pstrName pstrName
); );
} }
if (textureView != 0 && *textureView != 0 ) if (textureView != 0 && *textureView != 0)
{ {
(*textureView)->SetPrivateData( WKPDID_D3DDebugObjectName, (*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
static_cast<UINT>( strnlen_s(pstrName, MAX_PATH) ), static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
pstrName pstrName
); );
} }

View File

@ -1,7 +1,7 @@
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// File: WICTextureLoader.h // File: WICTextureLoader.h
// //
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it // Function for loading a WIC image and creating a Direct3D runtime texture for it
// (auto-generating mipmaps if possible) // (auto-generating mipmaps if possible)
// //
// Note: Assumes application has already called CoInitializeEx // Note: Assumes application has already called CoInitializeEx
@ -33,23 +33,28 @@
namespace DirectX namespace DirectX
{ {
enum WIC_LOADER_FLAGS
{
WIC_LOADER_DEFAULT = 0,
WIC_LOADER_FORCE_SRGB = 0x1,
WIC_LOADER_IGNORE_SRGB = 0x2,
};
// Standard version // Standard version
HRESULT CreateWICTextureFromMemory( HRESULT CreateWICTextureFromMemory(
_In_ ID3D11Device* d3dDevice, _In_ ID3D11Device* d3dDevice,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData, _In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize, _In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView, _Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0 _In_ size_t maxsize = 0);
);
HRESULT CreateWICTextureFromFile( HRESULT CreateWICTextureFromFile(
_In_ ID3D11Device* d3dDevice, _In_ ID3D11Device* d3dDevice,
_In_z_ const wchar_t* szFileName, _In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView, _Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0 _In_ size_t maxsize = 0);
);
// Standard version with optional auto-gen mipmap support // Standard version with optional auto-gen mipmap support
HRESULT CreateWICTextureFromMemory( HRESULT CreateWICTextureFromMemory(
@ -57,19 +62,17 @@ namespace DirectX
_In_opt_ ID3D11DeviceContext* d3dContext, _In_opt_ ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData, _In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize, _In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView, _Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0 _In_ size_t maxsize = 0);
);
HRESULT CreateWICTextureFromFile( HRESULT CreateWICTextureFromFile(
_In_ ID3D11Device* d3dDevice, _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext, _In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName, _In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView, _Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0 _In_ size_t maxsize = 0);
);
// Extended version // Extended version
HRESULT CreateWICTextureFromMemoryEx( HRESULT CreateWICTextureFromMemoryEx(
@ -77,14 +80,13 @@ namespace DirectX
_In_reads_bytes_(wicDataSize) const uint8_t* wicData, _In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize, _In_ size_t wicDataSize,
_In_ size_t maxsize, _In_ size_t maxsize,
D3D11_USAGE usage, _In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags, _In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags, _In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags, _In_ unsigned int miscFlags,
_In_ bool forceSRGB, _In_ unsigned int loadFlags,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView _Outptr_opt_ ID3D11ShaderResourceView** textureView);
);
HRESULT CreateWICTextureFromFileEx( HRESULT CreateWICTextureFromFileEx(
_In_ ID3D11Device* d3dDevice, _In_ ID3D11Device* d3dDevice,
@ -94,10 +96,9 @@ namespace DirectX
_In_ unsigned int bindFlags, _In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags, _In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags, _In_ unsigned int miscFlags,
_In_ bool forceSRGB, _In_ unsigned int loadFlags,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView _Outptr_opt_ ID3D11ShaderResourceView** textureView);
);
// Extended version with optional auto-gen mipmap support // Extended version with optional auto-gen mipmap support
HRESULT CreateWICTextureFromMemoryEx( HRESULT CreateWICTextureFromMemoryEx(
@ -110,10 +111,9 @@ namespace DirectX
_In_ unsigned int bindFlags, _In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags, _In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags, _In_ unsigned int miscFlags,
_In_ bool forceSRGB, _In_ unsigned int loadFlags,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView _Outptr_opt_ ID3D11ShaderResourceView** textureView);
);
HRESULT CreateWICTextureFromFileEx( HRESULT CreateWICTextureFromFileEx(
_In_ ID3D11Device* d3dDevice, _In_ ID3D11Device* d3dDevice,
@ -124,8 +124,7 @@ namespace DirectX
_In_ unsigned int bindFlags, _In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags, _In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags, _In_ unsigned int miscFlags,
_In_ bool forceSRGB, _In_ unsigned int loadFlags,
_Out_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView _Outptr_opt_ ID3D11ShaderResourceView** textureView);
);
} }

View File

@ -269,9 +269,8 @@ namespace
HRESULT CreateTextureFromWIC(_In_ ID3D12Device* d3dDevice, HRESULT CreateTextureFromWIC(_In_ ID3D12Device* d3dDevice,
_In_ IWICBitmapFrameDecode *frame, _In_ IWICBitmapFrameDecode *frame,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
_Outptr_ ID3D12Resource** texture, _Outptr_ ID3D12Resource** texture,
std::unique_ptr<uint8_t[]>& decodedData, std::unique_ptr<uint8_t[]>& decodedData,
D3D12_SUBRESOURCE_DATA& subresource) D3D12_SUBRESOURCE_DATA& subresource)
@ -351,11 +350,11 @@ namespace
return E_FAIL; return E_FAIL;
// Handle sRGB formats // Handle sRGB formats
if (forceSRGB) if (loadFlags & WIC_LOADER_FORCE_SRGB)
{ {
format = MakeSRGB(format); format = MakeSRGB(format);
} }
else else if (!(loadFlags & WIC_LOADER_IGNORE_SRGB))
{ {
ComPtr<IWICMetadataQueryReader> metareader; ComPtr<IWICMetadataQueryReader> metareader;
if (SUCCEEDED(frame->GetMetadataQueryReader(metareader.GetAddressOf()))) if (SUCCEEDED(frame->GetMetadataQueryReader(metareader.GetAddressOf())))
@ -488,7 +487,7 @@ namespace
} }
// Count the number of mips // Count the number of mips
uint32_t mipCount = (reserveFullMipChain) ? CountMips(twidth, theight) : 1; uint32_t mipCount = (loadFlags & (WIC_LOADER_MIP_AUTOGEN | WIC_LOADER_MIP_RESERVE)) ? CountMips(twidth, theight) : 1;
// Create texture // Create texture
D3D12_RESOURCE_DESC desc = {}; D3D12_RESOURCE_DESC desc = {};
@ -499,7 +498,7 @@ namespace
desc.Format = format; desc.Format = format;
desc.SampleDesc.Count = 1; desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0; desc.SampleDesc.Quality = 0;
desc.Flags = flags; desc.Flags = resFlags;
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT);
@ -547,8 +546,7 @@ HRESULT DirectX::LoadWICTextureFromMemory(
wicDataSize, wicDataSize,
maxsize, maxsize,
D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_FLAG_NONE,
false, WIC_LOADER_DEFAULT,
false,
texture, texture,
decodedData, decodedData,
subresource); subresource);
@ -562,9 +560,8 @@ HRESULT DirectX::LoadWICTextureFromMemoryEx(
const uint8_t* wicData, const uint8_t* wicData,
size_t wicDataSize, size_t wicDataSize,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
ID3D12Resource** texture, ID3D12Resource** texture,
std::unique_ptr<uint8_t[]>& decodedData, std::unique_ptr<uint8_t[]>& decodedData,
D3D12_SUBRESOURCE_DATA& subresource) D3D12_SUBRESOURCE_DATA& subresource)
@ -610,7 +607,7 @@ HRESULT DirectX::LoadWICTextureFromMemoryEx(
hr = CreateTextureFromWIC( d3dDevice, hr = CreateTextureFromWIC( d3dDevice,
frame.Get(), maxsize, frame.Get(), maxsize,
flags, forceSRGB, reserveFullMipChain, resFlags, loadFlags,
texture, decodedData, subresource); texture, decodedData, subresource);
if ( FAILED(hr)) if ( FAILED(hr))
return hr; return hr;
@ -637,8 +634,7 @@ HRESULT DirectX::LoadWICTextureFromFile(
fileName, fileName,
maxsize, maxsize,
D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_FLAG_NONE,
false, WIC_LOADER_DEFAULT,
false,
texture, texture,
wicData, wicData,
subresource); subresource);
@ -651,9 +647,8 @@ HRESULT DirectX::LoadWICTextureFromFileEx(
ID3D12Device* d3dDevice, ID3D12Device* d3dDevice,
const wchar_t* fileName, const wchar_t* fileName,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
ID3D12Resource** texture, ID3D12Resource** texture,
std::unique_ptr<uint8_t[]>& decodedData, std::unique_ptr<uint8_t[]>& decodedData,
D3D12_SUBRESOURCE_DATA& subresource) D3D12_SUBRESOURCE_DATA& subresource)
@ -682,7 +677,7 @@ HRESULT DirectX::LoadWICTextureFromFileEx(
return hr; return hr;
hr = CreateTextureFromWIC( d3dDevice, frame.Get(), maxsize, hr = CreateTextureFromWIC( d3dDevice, frame.Get(), maxsize,
flags, forceSRGB, reserveFullMipChain, resFlags, loadFlags,
texture, decodedData, subresource ); texture, decodedData, subresource );
#if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) #if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )

View File

@ -1,7 +1,7 @@
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// File: WICTextureLoader12.h // File: WICTextureLoader12.h
// //
// Function for loading a WIC image and creating a Direct3D 12 runtime texture for it // Function for loading a WIC image and creating a Direct3D runtime texture for it
// (auto-generating mipmaps if possible) // (auto-generating mipmaps if possible)
// //
// Note: Assumes application has already called CoInitializeEx // Note: Assumes application has already called CoInitializeEx
@ -31,6 +31,15 @@
namespace DirectX namespace DirectX
{ {
enum WIC_LOADER_FLAGS
{
WIC_LOADER_DEFAULT = 0,
WIC_LOADER_FORCE_SRGB = 0x1,
WIC_LOADER_IGNORE_SRGB = 0x2,
WIC_LOADER_MIP_AUTOGEN = 0x4,
WIC_LOADER_MIP_RESERVE = 0x8,
};
// Standard version // Standard version
HRESULT __cdecl LoadWICTextureFromMemory( HRESULT __cdecl LoadWICTextureFromMemory(
_In_ ID3D12Device* d3dDevice, _In_ ID3D12Device* d3dDevice,
@ -55,9 +64,8 @@ namespace DirectX
_In_reads_bytes_(wicDataSize) const uint8_t* wicData, _In_reads_bytes_(wicDataSize) const uint8_t* wicData,
size_t wicDataSize, size_t wicDataSize,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
_Outptr_ ID3D12Resource** texture, _Outptr_ ID3D12Resource** texture,
std::unique_ptr<uint8_t[]>& decodedData, std::unique_ptr<uint8_t[]>& decodedData,
D3D12_SUBRESOURCE_DATA& subresource); D3D12_SUBRESOURCE_DATA& subresource);
@ -66,9 +74,8 @@ namespace DirectX
_In_ ID3D12Device* d3dDevice, _In_ ID3D12Device* d3dDevice,
_In_z_ const wchar_t* szFileName, _In_z_ const wchar_t* szFileName,
size_t maxsize, size_t maxsize,
D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_FLAGS resFlags,
bool forceSRGB, unsigned int loadFlags,
bool reserveFullMipChain,
_Outptr_ ID3D12Resource** texture, _Outptr_ ID3D12Resource** texture,
std::unique_ptr<uint8_t[]>& decodedData, std::unique_ptr<uint8_t[]>& decodedData,
D3D12_SUBRESOURCE_DATA& subresource); D3D12_SUBRESOURCE_DATA& subresource);