X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=thirdparty%2Fdirectxtex%2FDirectXTex%2FDirectXTexD3D11.cpp;fp=thirdparty%2Fdirectxtex%2FDirectXTex%2FDirectXTexD3D11.cpp;h=e640dfd037e494b901384131db3c43b878c0f0e7;hb=d7c738e13decf8a8a891008c51b437ccbe3434fb;hp=0000000000000000000000000000000000000000;hpb=4f9982f5ec3dccae65d5a49dfd5a81b9737d90cd;p=apitrace diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexD3D11.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexD3D11.cpp new file mode 100644 index 0000000..e640dfd --- /dev/null +++ b/thirdparty/directxtex/DirectXTex/DirectXTexD3D11.cpp @@ -0,0 +1,820 @@ +//------------------------------------------------------------------------------------- +// DirectXTexD3D11.cpp +// +// DirectX Texture Library - Direct3D 11 helpers +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "DirectXTexP.h" + +#include + +namespace DirectX +{ + +static HRESULT _Capture( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, _In_ const TexMetadata& metadata, + _In_ const ScratchImage& result ) +{ + if ( !pContext || !pSource || !result.GetPixels() ) + return E_POINTER; + + if ( metadata.dimension == TEX_DIMENSION_TEXTURE3D ) + { + //--- Volume texture ---------------------------------------------------------- + assert( metadata.arraySize == 1 ); + + size_t height = metadata.height; + size_t depth = metadata.depth; + + for( size_t level = 0; level < metadata.mipLevels; ++level ) + { + UINT dindex = D3D11CalcSubresource( static_cast( level ), 0, static_cast( metadata.mipLevels ) ); + + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map( pSource, dindex, D3D11_MAP_READ, 0, &mapped ); + if ( FAILED(hr) ) + return hr; + + const uint8_t* pslice = reinterpret_cast( mapped.pData ); + if ( !pslice ) + { + pContext->Unmap( pSource, dindex ); + return E_POINTER; + } + + size_t lines = ComputeScanlines( metadata.format, height ); + + for( size_t slice = 0; slice < depth; ++slice ) + { + const Image* img = result.GetImage( level, 0, slice ); + if ( !img ) + { + pContext->Unmap( pSource, dindex ); + return E_FAIL; + } + + if ( !img->pixels ) + { + pContext->Unmap( pSource, dindex ); + return E_POINTER; + } + + const uint8_t* sptr = pslice; + uint8_t* dptr = img->pixels; + for( size_t h = 0; h < lines; ++h ) + { + size_t msize = std::min( img->rowPitch, mapped.RowPitch ); + memcpy_s( dptr, img->rowPitch, sptr, msize ); + sptr += mapped.RowPitch; + dptr += img->rowPitch; + } + + pslice += mapped.DepthPitch; + } + + pContext->Unmap( pSource, dindex ); + + if ( height > 1 ) + height >>= 1; + if ( depth > 1 ) + depth >>= 1; + } + } + else + { + //--- 1D or 2D texture -------------------------------------------------------- + assert( metadata.depth == 1 ); + + for( size_t item = 0; item < metadata.arraySize; ++item ) + { + size_t height = metadata.height; + + for( size_t level = 0; level < metadata.mipLevels; ++level ) + { + UINT dindex = D3D11CalcSubresource( static_cast( level ), static_cast( item ), static_cast( metadata.mipLevels ) ); + + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map( pSource, dindex, D3D11_MAP_READ, 0, &mapped ); + if ( FAILED(hr) ) + return hr; + + const Image* img = result.GetImage( level, item, 0 ); + if ( !img ) + { + pContext->Unmap( pSource, dindex ); + return E_FAIL; + } + + if ( !img->pixels ) + { + pContext->Unmap( pSource, dindex ); + return E_POINTER; + } + + size_t lines = ComputeScanlines( metadata.format, height ); + + const uint8_t* sptr = reinterpret_cast( mapped.pData ); + uint8_t* dptr = img->pixels; + for( size_t h = 0; h < lines; ++h ) + { + size_t msize = std::min( img->rowPitch, mapped.RowPitch ); + memcpy_s( dptr, img->rowPitch, sptr, msize ); + sptr += mapped.RowPitch; + dptr += img->rowPitch; + } + + pContext->Unmap( pSource, dindex ); + + if ( height > 1 ) + height >>= 1; + } + } + } + + return S_OK; +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Determine if given texture metadata is supported on the given device +//------------------------------------------------------------------------------------- +bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata ) +{ + if ( !pDevice ) + return false; + + D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel(); + + // Validate format + DXGI_FORMAT fmt = metadata.format; + + if ( !IsValid( fmt ) ) + return false; + + if ( IsVideo(fmt) ) + return false; + + switch( fmt ) + { + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + if ( fl < D3D_FEATURE_LEVEL_10_0 ) + return false; + break; + + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + if ( fl < D3D_FEATURE_LEVEL_11_0 ) + return false; + break; + } + + // Validate miplevel count + if ( metadata.mipLevels > D3D11_REQ_MIP_LEVELS ) + return false; + + // Validate array size, dimension, and width/height + size_t arraySize = metadata.arraySize; + size_t iWidth = metadata.width; + size_t iHeight = metadata.height; + size_t iDepth = metadata.depth; + + // Most cases are known apriori based on feature level, but we use this for robustness to handle the few optional cases + UINT formatSupport = 0; + pDevice->CheckFormatSupport( fmt, &formatSupport ); + + switch ( metadata.dimension ) + { + case TEX_DIMENSION_TEXTURE1D: + if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE1D) ) + return false; + + if ( (arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D11_REQ_TEXTURE1D_U_DIMENSION) ) + return false; + + if ( fl < D3D_FEATURE_LEVEL_11_0 ) + { + if ( (arraySize > D3D10_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D10_REQ_TEXTURE1D_U_DIMENSION) ) + return false; + + if ( fl < D3D_FEATURE_LEVEL_10_0 ) + { + if ( (arraySize > 1) || (iWidth > 4096 /*D3D_FL9_3_REQ_TEXTURE1D_U_DIMENSION*/) ) + return false; + + if ( (fl < D3D_FEATURE_LEVEL_9_3) && (iWidth > 2048 /*D3D_FL9_1_REQ_TEXTURE1D_U_DIMENSION*/ ) ) + return false; + } + } + break; + + case TEX_DIMENSION_TEXTURE2D: + if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE ) + { + if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) ) + return false; + + if ( (arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D11_REQ_TEXTURECUBE_DIMENSION) + || (iHeight > D3D11_REQ_TEXTURECUBE_DIMENSION)) + return false; + + if ( fl < D3D_FEATURE_LEVEL_11_0 ) + { + if ( (arraySize > D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D10_REQ_TEXTURECUBE_DIMENSION) + || (iHeight > D3D10_REQ_TEXTURECUBE_DIMENSION)) + return false; + + if ( (fl < D3D_FEATURE_LEVEL_10_1) && (arraySize != 6) ) + return false; + + if ( fl < D3D_FEATURE_LEVEL_10_0 ) + { + if ( (iWidth > 4096 /*D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION*/ ) + || (iHeight > 4096 /*D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION*/ ) ) + return false; + + if ( (fl < D3D_FEATURE_LEVEL_9_3) + && ( (iWidth > 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/) + || (iHeight > 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/) ) ) + return false; + } + } + } + else // Not a cube map + { + if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) + return false; + + if ( (arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) + || (iHeight > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + return false; + + if ( fl < D3D_FEATURE_LEVEL_11_0 ) + { + if ( (arraySize > D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION) + || (iHeight > D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + return false; + + if ( fl < D3D_FEATURE_LEVEL_10_0 ) + { + if ( (arraySize > 1) + || (iWidth > 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/) + || (iHeight > 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/) ) + return false; + + if ( (fl < D3D_FEATURE_LEVEL_9_3) + && ( (iWidth > 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/) + || (iHeight > 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/) ) ) + return false; + } + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) ) + return false; + + if ( (arraySize > 1) + || (iWidth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iHeight > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iDepth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ) + return false; + + if ( fl < D3D_FEATURE_LEVEL_11_0 ) + { + if ( (iWidth > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iHeight > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iDepth > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ) + return false; + + if ( fl < D3D_FEATURE_LEVEL_10_0 ) + { + if ( (iWidth > 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/) + || (iHeight > 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/) + || (iDepth > 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/) ) + return false; + } + } + break; + + default: + // Not a supported dimension + return false; + } + + return true; +} + + +//------------------------------------------------------------------------------------- +// Create a texture resource +//------------------------------------------------------------------------------------- +HRESULT CreateTexture( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata, + ID3D11Resource** ppResource ) +{ + if ( !pDevice || !srcImages || !nimages || !ppResource ) + return E_INVALIDARG; + + if ( !metadata.mipLevels || !metadata.arraySize ) + return E_INVALIDARG; + +#ifdef _AMD64_ + if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) + || (metadata.mipLevels > 0xFFFFFFFF) || (metadata.arraySize > 0xFFFFFFFF) ) + return E_INVALIDARG; +#endif + + std::unique_ptr initData( new D3D11_SUBRESOURCE_DATA[ metadata.mipLevels * metadata.arraySize ] ); + if ( !initData ) + return E_OUTOFMEMORY; + + // Fill out subresource array + if ( metadata.dimension == TEX_DIMENSION_TEXTURE3D ) + { + //--- Volume case ------------------------------------------------------------- + if ( !metadata.depth ) + return E_INVALIDARG; + +#ifdef _AMD64_ + if ( metadata.depth > 0xFFFFFFFF ) + return E_INVALIDARG; +#endif + + if ( metadata.arraySize > 1 ) + // Direct3D 11 doesn't support arrays of 3D textures + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + + size_t depth = metadata.depth; + + size_t idx = 0; + for( size_t level = 0; level < metadata.mipLevels; ++level ) + { + size_t index = metadata.ComputeIndex( level, 0, 0 ); + if ( index >= nimages ) + return E_FAIL; + + const Image& img = srcImages[ index ]; + + if ( img.format != metadata.format ) + return E_FAIL; + + if ( !img.pixels ) + return E_POINTER; + + // Verify pixels in image 1 .. (depth-1) are exactly image->slicePitch apart + // For 3D textures, this relies on all slices of the same miplevel being continous in memory + // (this is how ScratchImage lays them out), which is why we just give the 0th slice to Direct3D 11 + const uint8_t* pSlice = img.pixels + img.slicePitch; + for( size_t slice = 1; slice < depth; ++slice ) + { + size_t tindex = metadata.ComputeIndex( level, 0, slice ); + if ( tindex >= nimages ) + return E_FAIL; + + const Image& timg = srcImages[ tindex ]; + + if ( !timg.pixels ) + return E_POINTER; + + if ( timg.pixels != pSlice + || timg.format != metadata.format + || timg.rowPitch != img.rowPitch + || timg.slicePitch != img.slicePitch ) + return E_FAIL; + + pSlice = timg.pixels + img.slicePitch; + } + + assert( idx < (metadata.mipLevels * metadata.arraySize) ); + + initData[idx].pSysMem = img.pixels; + initData[idx].SysMemPitch = static_cast( img.rowPitch ); + initData[idx].SysMemSlicePitch = static_cast( img.slicePitch ); + ++idx; + + if ( depth > 1 ) + depth >>= 1; + } + } + else + { + //--- 1D or 2D texture case --------------------------------------------------- + size_t idx = 0; + for( size_t item = 0; item < metadata.arraySize; ++item ) + { + for( size_t level = 0; level < metadata.mipLevels; ++level ) + { + size_t index = metadata.ComputeIndex( level, item, 0 ); + if ( index >= nimages ) + return E_FAIL; + + const Image& img = srcImages[ index ]; + + if ( img.format != metadata.format ) + return E_FAIL; + + if ( !img.pixels ) + return E_POINTER; + + assert( idx < (metadata.mipLevels * metadata.arraySize) ); + + initData[idx].pSysMem = img.pixels; + initData[idx].SysMemPitch = static_cast( img.rowPitch ); + initData[idx].SysMemSlicePitch = static_cast( img.slicePitch ); + ++idx; + } + } + } + + // Create texture using static initialization data + HRESULT hr = E_FAIL; + + switch ( metadata.dimension ) + { + case TEX_DIMENSION_TEXTURE1D: + { + D3D11_TEXTURE1D_DESC desc; + desc.Width = static_cast( metadata.width ); + desc.MipLevels = static_cast( metadata.mipLevels ); + desc.ArraySize = static_cast( metadata.arraySize ); + desc.Format = metadata.format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture1D( &desc, initData.get(), reinterpret_cast(ppResource) ); + } + break; + + case TEX_DIMENSION_TEXTURE2D: + { + D3D11_TEXTURE2D_DESC desc; + desc.Width = static_cast( metadata.width ); + desc.Height = static_cast( metadata.height ); + desc.MipLevels = static_cast( metadata.mipLevels ); + desc.ArraySize = static_cast( metadata.arraySize ); + desc.Format = metadata.format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = (metadata.miscFlags & TEX_MISC_TEXTURECUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0; + + hr = pDevice->CreateTexture2D( &desc, initData.get(), reinterpret_cast(ppResource) ); + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + D3D11_TEXTURE3D_DESC desc; + desc.Width = static_cast( metadata.width ); + desc.Height = static_cast( metadata.height ); + desc.Depth = static_cast( metadata.depth ); + desc.MipLevels = static_cast( metadata.mipLevels ); + desc.Format = metadata.format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + hr = pDevice->CreateTexture3D( &desc, initData.get(), reinterpret_cast(ppResource) ); + } + break; + } + + return hr; +} + + +//------------------------------------------------------------------------------------- +// Create a shader resource view and associated texture +//------------------------------------------------------------------------------------- +HRESULT CreateShaderResourceView( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata, + ID3D11ShaderResourceView** ppSRV ) +{ + if ( !ppSRV ) + return E_INVALIDARG; + + ScopedObject resource; + HRESULT hr = CreateTexture( pDevice, srcImages, nimages, metadata, &resource ); + if ( FAILED(hr) ) + return hr; + + assert( !resource.IsNull() ); + + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + memset( &SRVDesc, 0, sizeof(SRVDesc) ); + SRVDesc.Format = metadata.format; + + switch ( metadata.dimension ) + { + case TEX_DIMENSION_TEXTURE1D: + if ( metadata.arraySize > 1 ) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + SRVDesc.Texture1DArray.MipLevels = static_cast( metadata.mipLevels ); + SRVDesc.Texture1DArray.ArraySize = static_cast( metadata.arraySize ); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + SRVDesc.Texture1D.MipLevels = static_cast( metadata.mipLevels ); + } + break; + + case TEX_DIMENSION_TEXTURE2D: + if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE ) + { + if (metadata.arraySize > 6) + { + assert( (metadata.arraySize % 6) == 0 ); + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY; + SRVDesc.TextureCubeArray.MipLevels = static_cast( metadata.mipLevels ); + SRVDesc.TextureCubeArray.NumCubes = static_cast( metadata.arraySize / 6 ); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + SRVDesc.TextureCube.MipLevels = static_cast( metadata.mipLevels ); + } + } + else if ( metadata.arraySize > 1 ) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + SRVDesc.Texture2DArray.MipLevels = static_cast( metadata.mipLevels ); + SRVDesc.Texture2DArray.ArraySize = static_cast( metadata.arraySize ); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MipLevels = static_cast( metadata.mipLevels ); + } + break; + + case TEX_DIMENSION_TEXTURE3D: + assert( metadata.arraySize == 1 ); + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + SRVDesc.Texture3D.MipLevels = static_cast( metadata.mipLevels ); + break; + + default: + return E_FAIL; + } + + hr = pDevice->CreateShaderResourceView( resource.Get(), &SRVDesc, ppSRV ); + if ( FAILED(hr) ) + return hr; + + assert( *ppSRV ); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a texture resource to a DDS file in memory/on disk +//------------------------------------------------------------------------------------- +HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID3D11Resource* pSource, ScratchImage& result ) +{ + if ( !pDevice || !pContext || !pSource ) + return E_INVALIDARG; + + D3D11_RESOURCE_DIMENSION resType = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pSource->GetType( &resType ); + + HRESULT hr; + + switch( resType ) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + { + ScopedObject pTexture; + hr = pSource->QueryInterface( __uuidof(ID3D11Texture1D), (void**) &pTexture ); + if ( FAILED(hr) ) + break; + + assert( pTexture.Get() ); + + D3D11_TEXTURE1D_DESC desc; + pTexture->GetDesc( &desc ); + + desc.BindFlags = 0; + desc.MiscFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.Usage = D3D11_USAGE_STAGING; + + ScopedObject pStaging; + hr = pDevice->CreateTexture1D( &desc, 0, &pStaging ); + if ( FAILED(hr) ) + break; + + assert( pStaging.Get() ); + + pContext->CopyResource( pStaging.Get(), pSource ); + + TexMetadata mdata; + mdata.width = desc.Width; + mdata.height = mdata.depth = 1; + mdata.arraySize = desc.ArraySize; + mdata.mipLevels = desc.MipLevels; + mdata.miscFlags = 0; + mdata.format = desc.Format; + mdata.dimension = TEX_DIMENSION_TEXTURE1D; + + hr = result.Initialize( mdata ); + if ( FAILED(hr) ) + break; + + hr = _Capture( pContext, pStaging.Get(), mdata, result ); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + { + ScopedObject pTexture; + hr = pSource->QueryInterface( __uuidof(ID3D11Texture2D), (void**) &pTexture ); + if ( FAILED(hr) ) + break; + + assert( pTexture.Get() ); + + D3D11_TEXTURE2D_DESC desc; + pTexture->GetDesc( &desc ); + + ScopedObject pStaging; + if ( desc.SampleDesc.Count > 1 ) + { + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + + ScopedObject pTemp; + hr = pDevice->CreateTexture2D( &desc, 0, &pTemp ); + if ( FAILED(hr) ) + break; + + assert( pTemp.Get() ); + + DXGI_FORMAT fmt = desc.Format; + if ( IsTypeless(fmt) ) + { + // Assume a UNORM if it exists otherwise use FLOAT + fmt = MakeTypelessUNORM( fmt ); + fmt = MakeTypelessFLOAT( fmt ); + } + + UINT support = 0; + hr = pDevice->CheckFormatSupport( fmt, &support ); + if ( FAILED(hr) ) + break; + + if ( !(support & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE) ) + { + hr = E_FAIL; + break; + } + + for( UINT item = 0; item < desc.ArraySize; ++item ) + { + for( UINT level = 0; level < desc.MipLevels; ++level ) + { + UINT index = D3D11CalcSubresource( level, item, desc.MipLevels ); + + pContext->ResolveSubresource( pTemp.Get(), index, pSource, index, fmt ); + } + } + + desc.BindFlags = 0; + desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.Usage = D3D11_USAGE_STAGING; + + hr = pDevice->CreateTexture2D( &desc, 0, &pStaging ); + if ( FAILED(hr) ) + break; + + assert( pStaging.Get() ); + + pContext->CopyResource( pStaging.Get(), pTemp.Get() ); + } + else + { + desc.BindFlags = 0; + desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.Usage = D3D11_USAGE_STAGING; + + hr = pDevice->CreateTexture2D( &desc, 0, &pStaging ); + if ( FAILED(hr) ) + break; + + assert( pStaging.Get() ); + + pContext->CopyResource( pStaging.Get(), pSource ); + } + + TexMetadata mdata; + mdata.width = desc.Width; + mdata.height = desc.Height; + mdata.depth = 1; + mdata.arraySize = desc.ArraySize; + mdata.mipLevels = desc.MipLevels; + mdata.miscFlags = (desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) ? TEX_MISC_TEXTURECUBE : 0; + mdata.format = desc.Format; + mdata.dimension = TEX_DIMENSION_TEXTURE2D; + + hr = result.Initialize( mdata ); + if ( FAILED(hr) ) + break; + + hr = _Capture( pContext, pStaging.Get(), mdata, result ); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + { + ScopedObject pTexture; + hr = pSource->QueryInterface( __uuidof(ID3D11Texture3D), (void**) &pTexture ); + if ( FAILED(hr) ) + break; + + assert( pTexture.Get() ); + + D3D11_TEXTURE3D_DESC desc; + pTexture->GetDesc( &desc ); + + desc.BindFlags = 0; + desc.MiscFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.Usage = D3D11_USAGE_STAGING; + + ScopedObject pStaging; + hr = pDevice->CreateTexture3D( &desc, 0, &pStaging ); + if ( FAILED(hr) ) + break; + + assert( pStaging.Get() ); + + pContext->CopyResource( pStaging.Get(), pSource ); + + TexMetadata mdata; + mdata.width = desc.Width; + mdata.height = desc.Height; + mdata.depth = desc.Depth; + mdata.arraySize = 1; + mdata.mipLevels = desc.MipLevels; + mdata.miscFlags = 0; + mdata.format = desc.Format; + mdata.dimension = TEX_DIMENSION_TEXTURE3D; + + hr = result.Initialize( mdata ); + if ( FAILED(hr) ) + break; + + hr = _Capture( pContext, pStaging.Get(), mdata, result ); + } + break; + + default: + hr = E_FAIL; + break; + } + + if ( FAILED(hr) ) + { + result.Release(); + return hr; + } + + return S_OK; +} + +}; // namespace