in MiniEngine/Core/DDSTextureLoader.cpp [969:1193]
static HRESULT CreateTextureFromDDS( _In_ ID3D12Device* d3dDevice,
_In_ const DDS_HEADER* header,
_In_reads_bytes_(bitSize) const uint8_t* bitData,
_In_ size_t bitSize,
_In_ size_t maxsize,
_In_ bool forceSRGB,
_Outptr_opt_ ID3D12Resource** texture,
_In_ D3D12_CPU_DESCRIPTOR_HANDLE textureView )
{
HRESULT hr = S_OK;
UINT width = header->width;
UINT height = header->height;
UINT depth = header->depth;
uint32_t resDim = D3D12_RESOURCE_DIMENSION_UNKNOWN;
UINT arraySize = 1;
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
bool isCubeMap = false;
size_t mipCount = header->mipMapCount;
if (0 == mipCount)
{
mipCount = 1;
}
if ((header->ddspf.flags & DDS_FOURCC) && (MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC ))
{
auto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const char*)header + sizeof(DDS_HEADER) );
arraySize = d3d10ext->arraySize;
if (arraySize == 0)
{
return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
}
switch( d3d10ext->dxgiFormat )
{
case DXGI_FORMAT_AI44:
case DXGI_FORMAT_IA44:
case DXGI_FORMAT_P8:
case DXGI_FORMAT_A8P8:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
default:
if ( BitsPerPixel( d3d10ext->dxgiFormat ) == 0 )
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
}
format = d3d10ext->dxgiFormat;
switch ( d3d10ext->resourceDimension )
{
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
// D3DX writes 1D textures with a fixed Height of 1
if ((header->flags & DDS_HEIGHT) && height != 1)
{
return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
}
height = depth = 1;
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
if (d3d10ext->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE)
{
arraySize *= 6;
isCubeMap = true;
}
depth = 1;
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
if (!(header->flags & DDS_HEADER_FLAGS_VOLUME))
{
return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
}
if (arraySize > 1)
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
resDim = d3d10ext->resourceDimension;
}
else
{
format = GetDXGIFormat( header->ddspf );
if (format == DXGI_FORMAT_UNKNOWN)
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
if (header->flags & DDS_HEADER_FLAGS_VOLUME)
{
resDim = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
}
else
{
if (header->caps2 & DDS_CUBEMAP)
{
// We require all six faces to be defined
if ((header->caps2 & DDS_CUBEMAP_ALLFACES ) != DDS_CUBEMAP_ALLFACES)
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
arraySize = 6;
isCubeMap = true;
}
depth = 1;
resDim = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
// Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
}
assert( BitsPerPixel( format ) != 0 );
}
// Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements)
if (mipCount > D3D12_REQ_MIP_LEVELS)
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
switch ( resDim )
{
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
if ((arraySize > D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||
(width > D3D12_REQ_TEXTURE1D_U_DIMENSION) )
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
if ( isCubeMap )
{
// This is the right bound because we set arraySize to (NumCubes*6) above
if ((arraySize > D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
(width > D3D12_REQ_TEXTURECUBE_DIMENSION) ||
(height > D3D12_REQ_TEXTURECUBE_DIMENSION))
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
}
else if ((arraySize > D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
(width > D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION) ||
(height > D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION))
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
if ((arraySize > 1) ||
(width > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
(height > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
(depth > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) )
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
{
// Create the texture
UINT subresourceCount = static_cast<UINT>(mipCount) * arraySize;
std::unique_ptr<D3D12_SUBRESOURCE_DATA[]> initData( new (std::nothrow) D3D12_SUBRESOURCE_DATA[subresourceCount] );
if ( !initData )
{
return E_OUTOFMEMORY;
}
size_t skipMip = 0;
size_t twidth = 0;
size_t theight = 0;
size_t tdepth = 0;
hr = FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
twidth, theight, tdepth, skipMip, initData.get() );
if ( SUCCEEDED(hr) )
{
hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,
format, forceSRGB,
isCubeMap, texture, textureView );
if ( FAILED(hr) && !maxsize && (mipCount > 1) )
{
// Retry with a maxsize determined by feature level
maxsize = (resDim == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
? 2048 /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
: 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
hr = FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
twidth, theight, tdepth, skipMip, initData.get() );
if ( SUCCEEDED(hr) )
{
hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,
format, forceSRGB,
isCubeMap, texture, textureView );
}
}
}
if (SUCCEEDED(hr))
{
GpuResource DestTexture(*texture, D3D12_RESOURCE_STATE_COPY_DEST);
CommandContext::InitializeTexture(DestTexture, subresourceCount, initData.get());
}
}
return hr;
}