DirectXTexD3D11.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. //-------------------------------------------------------------------------------------
  2. // DirectXTexD3D11.cpp
  3. //
  4. // DirectX Texture Library - Direct3D 11 helpers
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //
  11. // Copyright (c) Microsoft Corporation. All rights reserved.
  12. //
  13. // http://go.microsoft.com/fwlink/?LinkId=248926
  14. //-------------------------------------------------------------------------------------
  15. #include "directxtexp.h"
  16. #if !defined(_XBOX_ONE) || !defined(_TITLE) || !MONOLITHIC
  17. #include <d3d10.h>
  18. #endif
  19. using Microsoft::WRL::ComPtr;
  20. namespace DirectX
  21. {
  22. static HRESULT _Capture( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, _In_ const TexMetadata& metadata,
  23. _In_ const ScratchImage& result )
  24. {
  25. if ( !pContext || !pSource || !result.GetPixels() )
  26. return E_POINTER;
  27. if ( metadata.IsVolumemap() )
  28. {
  29. //--- Volume texture ----------------------------------------------------------
  30. assert( metadata.arraySize == 1 );
  31. size_t height = metadata.height;
  32. size_t depth = metadata.depth;
  33. for( size_t level = 0; level < metadata.mipLevels; ++level )
  34. {
  35. UINT dindex = D3D11CalcSubresource( static_cast<UINT>( level ), 0, static_cast<UINT>( metadata.mipLevels ) );
  36. D3D11_MAPPED_SUBRESOURCE mapped;
  37. HRESULT hr = pContext->Map( pSource, dindex, D3D11_MAP_READ, 0, &mapped );
  38. if ( FAILED(hr) )
  39. return hr;
  40. auto pslice = reinterpret_cast<const uint8_t*>( mapped.pData );
  41. if ( !pslice )
  42. {
  43. pContext->Unmap( pSource, dindex );
  44. return E_POINTER;
  45. }
  46. size_t lines = ComputeScanlines( metadata.format, height );
  47. if ( !lines )
  48. {
  49. pContext->Unmap( pSource, dindex );
  50. return E_UNEXPECTED;
  51. }
  52. for( size_t slice = 0; slice < depth; ++slice )
  53. {
  54. const Image* img = result.GetImage( level, 0, slice );
  55. if ( !img )
  56. {
  57. pContext->Unmap( pSource, dindex );
  58. return E_FAIL;
  59. }
  60. if ( !img->pixels )
  61. {
  62. pContext->Unmap( pSource, dindex );
  63. return E_POINTER;
  64. }
  65. const uint8_t* sptr = pslice;
  66. uint8_t* dptr = img->pixels;
  67. for( size_t h = 0; h < lines; ++h )
  68. {
  69. size_t msize = std::min<size_t>( img->rowPitch, mapped.RowPitch );
  70. memcpy_s( dptr, img->rowPitch, sptr, msize );
  71. sptr += mapped.RowPitch;
  72. dptr += img->rowPitch;
  73. }
  74. pslice += mapped.DepthPitch;
  75. }
  76. pContext->Unmap( pSource, dindex );
  77. if ( height > 1 )
  78. height >>= 1;
  79. if ( depth > 1 )
  80. depth >>= 1;
  81. }
  82. }
  83. else
  84. {
  85. //--- 1D or 2D texture --------------------------------------------------------
  86. assert( metadata.depth == 1 );
  87. for( size_t item = 0; item < metadata.arraySize; ++item )
  88. {
  89. size_t height = metadata.height;
  90. for( size_t level = 0; level < metadata.mipLevels; ++level )
  91. {
  92. UINT dindex = D3D11CalcSubresource( static_cast<UINT>( level ), static_cast<UINT>( item ), static_cast<UINT>( metadata.mipLevels ) );
  93. D3D11_MAPPED_SUBRESOURCE mapped;
  94. HRESULT hr = pContext->Map( pSource, dindex, D3D11_MAP_READ, 0, &mapped );
  95. if ( FAILED(hr) )
  96. return hr;
  97. const Image* img = result.GetImage( level, item, 0 );
  98. if ( !img )
  99. {
  100. pContext->Unmap( pSource, dindex );
  101. return E_FAIL;
  102. }
  103. if ( !img->pixels )
  104. {
  105. pContext->Unmap( pSource, dindex );
  106. return E_POINTER;
  107. }
  108. size_t lines = ComputeScanlines( metadata.format, height );
  109. if ( !lines )
  110. {
  111. pContext->Unmap( pSource, dindex );
  112. return E_UNEXPECTED;
  113. }
  114. auto sptr = reinterpret_cast<const uint8_t*>( mapped.pData );
  115. uint8_t* dptr = img->pixels;
  116. for( size_t h = 0; h < lines; ++h )
  117. {
  118. size_t msize = std::min<size_t>( img->rowPitch, mapped.RowPitch );
  119. memcpy_s( dptr, img->rowPitch, sptr, msize );
  120. sptr += mapped.RowPitch;
  121. dptr += img->rowPitch;
  122. }
  123. pContext->Unmap( pSource, dindex );
  124. if ( height > 1 )
  125. height >>= 1;
  126. }
  127. }
  128. }
  129. return S_OK;
  130. }
  131. //=====================================================================================
  132. // Entry-points
  133. //=====================================================================================
  134. //-------------------------------------------------------------------------------------
  135. // Determine if given texture metadata is supported on the given device
  136. //-------------------------------------------------------------------------------------
  137. _Use_decl_annotations_
  138. bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
  139. {
  140. if ( !pDevice )
  141. return false;
  142. D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel();
  143. // Validate format
  144. DXGI_FORMAT fmt = metadata.format;
  145. if ( !IsValid( fmt ) )
  146. return false;
  147. switch( fmt )
  148. {
  149. case DXGI_FORMAT_BC4_TYPELESS:
  150. case DXGI_FORMAT_BC4_UNORM:
  151. case DXGI_FORMAT_BC4_SNORM:
  152. case DXGI_FORMAT_BC5_TYPELESS:
  153. case DXGI_FORMAT_BC5_UNORM:
  154. case DXGI_FORMAT_BC5_SNORM:
  155. if ( fl < D3D_FEATURE_LEVEL_10_0 )
  156. return false;
  157. break;
  158. case DXGI_FORMAT_BC6H_TYPELESS:
  159. case DXGI_FORMAT_BC6H_UF16:
  160. case DXGI_FORMAT_BC6H_SF16:
  161. case DXGI_FORMAT_BC7_TYPELESS:
  162. case DXGI_FORMAT_BC7_UNORM:
  163. case DXGI_FORMAT_BC7_UNORM_SRGB:
  164. if ( fl < D3D_FEATURE_LEVEL_11_0 )
  165. return false;
  166. break;
  167. }
  168. // Validate miplevel count
  169. if ( metadata.mipLevels > D3D11_REQ_MIP_LEVELS )
  170. return false;
  171. // Validate array size, dimension, and width/height
  172. size_t arraySize = metadata.arraySize;
  173. size_t iWidth = metadata.width;
  174. size_t iHeight = metadata.height;
  175. size_t iDepth = metadata.depth;
  176. // Most cases are known apriori based on feature level, but we use this for robustness to handle the few optional cases
  177. UINT formatSupport = 0;
  178. HRESULT hr = pDevice->CheckFormatSupport( fmt, &formatSupport );
  179. if ( FAILED(hr) )
  180. {
  181. formatSupport = 0;
  182. }
  183. switch ( metadata.dimension )
  184. {
  185. case TEX_DIMENSION_TEXTURE1D:
  186. if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE1D) )
  187. return false;
  188. if ( (arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION)
  189. || (iWidth > D3D11_REQ_TEXTURE1D_U_DIMENSION) )
  190. return false;
  191. if ( fl < D3D_FEATURE_LEVEL_11_0 )
  192. {
  193. if ( (arraySize > D3D10_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION)
  194. || (iWidth > D3D10_REQ_TEXTURE1D_U_DIMENSION) )
  195. return false;
  196. if ( fl < D3D_FEATURE_LEVEL_10_0 )
  197. {
  198. if ( (arraySize > 1) || (iWidth > D3D_FL9_3_REQ_TEXTURE1D_U_DIMENSION) )
  199. return false;
  200. if ( (fl < D3D_FEATURE_LEVEL_9_3) && (iWidth > D3D_FL9_1_REQ_TEXTURE1D_U_DIMENSION ) )
  201. return false;
  202. }
  203. }
  204. break;
  205. case TEX_DIMENSION_TEXTURE2D:
  206. if ( metadata.IsCubemap() )
  207. {
  208. if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) )
  209. return false;
  210. if ( (arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION)
  211. || (iWidth > D3D11_REQ_TEXTURECUBE_DIMENSION)
  212. || (iHeight > D3D11_REQ_TEXTURECUBE_DIMENSION))
  213. return false;
  214. if ( fl < D3D_FEATURE_LEVEL_11_0 )
  215. {
  216. if ( (arraySize > D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION)
  217. || (iWidth > D3D10_REQ_TEXTURECUBE_DIMENSION)
  218. || (iHeight > D3D10_REQ_TEXTURECUBE_DIMENSION))
  219. return false;
  220. if ( (fl < D3D_FEATURE_LEVEL_10_1) && (arraySize != 6) )
  221. return false;
  222. if ( fl < D3D_FEATURE_LEVEL_10_0 )
  223. {
  224. if ( (iWidth > D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION )
  225. || (iHeight > D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION ) )
  226. return false;
  227. if ( (fl < D3D_FEATURE_LEVEL_9_3)
  228. && ( (iWidth > D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION)
  229. || (iHeight > D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION) ) )
  230. return false;
  231. }
  232. }
  233. }
  234. else // Not a cube map
  235. {
  236. if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) )
  237. return false;
  238. if ( (arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION)
  239. || (iWidth > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION)
  240. || (iHeight > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION))
  241. return false;
  242. if ( fl < D3D_FEATURE_LEVEL_11_0 )
  243. {
  244. if ( (arraySize > D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION)
  245. || (iWidth > D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION)
  246. || (iHeight > D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION))
  247. return false;
  248. if ( fl < D3D_FEATURE_LEVEL_10_0 )
  249. {
  250. if ( (arraySize > 1)
  251. || (iWidth > D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION)
  252. || (iHeight > D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION) )
  253. return false;
  254. if ( (fl < D3D_FEATURE_LEVEL_9_3)
  255. && ( (iWidth > D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION)
  256. || (iHeight > D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION) ) )
  257. return false;
  258. }
  259. }
  260. }
  261. break;
  262. case TEX_DIMENSION_TEXTURE3D:
  263. if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) )
  264. return false;
  265. if ( (arraySize > 1)
  266. || (iWidth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)
  267. || (iHeight > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)
  268. || (iDepth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) )
  269. return false;
  270. if ( fl < D3D_FEATURE_LEVEL_11_0 )
  271. {
  272. if ( (iWidth > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)
  273. || (iHeight > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)
  274. || (iDepth > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) )
  275. return false;
  276. if ( fl < D3D_FEATURE_LEVEL_10_0 )
  277. {
  278. if ( (iWidth > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)
  279. || (iHeight > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)
  280. || (iDepth > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) )
  281. return false;
  282. }
  283. }
  284. break;
  285. default:
  286. // Not a supported dimension
  287. return false;
  288. }
  289. return true;
  290. }
  291. //-------------------------------------------------------------------------------------
  292. // Create a texture resource
  293. //-------------------------------------------------------------------------------------
  294. _Use_decl_annotations_
  295. HRESULT CreateTexture( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
  296. ID3D11Resource** ppResource )
  297. {
  298. return CreateTextureEx( pDevice, srcImages, nimages, metadata,
  299. D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false,
  300. ppResource );
  301. }
  302. _Use_decl_annotations_
  303. HRESULT CreateTextureEx( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
  304. D3D11_USAGE usage, unsigned int bindFlags, unsigned int cpuAccessFlags, unsigned int miscFlags, bool forceSRGB,
  305. ID3D11Resource** ppResource )
  306. {
  307. if ( !pDevice || !srcImages || !nimages || !ppResource )
  308. return E_INVALIDARG;
  309. *ppResource = nullptr;
  310. if ( !metadata.mipLevels || !metadata.arraySize )
  311. return E_INVALIDARG;
  312. #ifdef _M_X64
  313. if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF)
  314. || (metadata.mipLevels > 0xFFFFFFFF) || (metadata.arraySize > 0xFFFFFFFF) )
  315. return E_INVALIDARG;
  316. #endif
  317. std::unique_ptr<D3D11_SUBRESOURCE_DATA[]> initData( new (std::nothrow) D3D11_SUBRESOURCE_DATA[ metadata.mipLevels * metadata.arraySize ] );
  318. if ( !initData )
  319. return E_OUTOFMEMORY;
  320. // Fill out subresource array
  321. if ( metadata.IsVolumemap() )
  322. {
  323. //--- Volume case -------------------------------------------------------------
  324. if ( !metadata.depth )
  325. return E_INVALIDARG;
  326. #ifdef _M_X64
  327. if ( metadata.depth > 0xFFFFFFFF )
  328. return E_INVALIDARG;
  329. #endif
  330. if ( metadata.arraySize > 1 )
  331. // Direct3D 11 doesn't support arrays of 3D textures
  332. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  333. size_t depth = metadata.depth;
  334. size_t idx = 0;
  335. for( size_t level = 0; level < metadata.mipLevels; ++level )
  336. {
  337. size_t index = metadata.ComputeIndex( level, 0, 0 );
  338. if ( index >= nimages )
  339. return E_FAIL;
  340. const Image& img = srcImages[ index ];
  341. if ( img.format != metadata.format )
  342. return E_FAIL;
  343. if ( !img.pixels )
  344. return E_POINTER;
  345. // Verify pixels in image 1 .. (depth-1) are exactly image->slicePitch apart
  346. // For 3D textures, this relies on all slices of the same miplevel being continous in memory
  347. // (this is how ScratchImage lays them out), which is why we just give the 0th slice to Direct3D 11
  348. const uint8_t* pSlice = img.pixels + img.slicePitch;
  349. for( size_t slice = 1; slice < depth; ++slice )
  350. {
  351. size_t tindex = metadata.ComputeIndex( level, 0, slice );
  352. if ( tindex >= nimages )
  353. return E_FAIL;
  354. const Image& timg = srcImages[ tindex ];
  355. if ( !timg.pixels )
  356. return E_POINTER;
  357. if ( timg.pixels != pSlice
  358. || timg.format != metadata.format
  359. || timg.rowPitch != img.rowPitch
  360. || timg.slicePitch != img.slicePitch )
  361. return E_FAIL;
  362. pSlice = timg.pixels + img.slicePitch;
  363. }
  364. assert( idx < (metadata.mipLevels * metadata.arraySize) );
  365. initData[idx].pSysMem = img.pixels;
  366. initData[idx].SysMemPitch = static_cast<DWORD>( img.rowPitch );
  367. initData[idx].SysMemSlicePitch = static_cast<DWORD>( img.slicePitch );
  368. ++idx;
  369. if ( depth > 1 )
  370. depth >>= 1;
  371. }
  372. }
  373. else
  374. {
  375. //--- 1D or 2D texture case ---------------------------------------------------
  376. size_t idx = 0;
  377. for( size_t item = 0; item < metadata.arraySize; ++item )
  378. {
  379. for( size_t level = 0; level < metadata.mipLevels; ++level )
  380. {
  381. size_t index = metadata.ComputeIndex( level, item, 0 );
  382. if ( index >= nimages )
  383. return E_FAIL;
  384. const Image& img = srcImages[ index ];
  385. if ( img.format != metadata.format )
  386. return E_FAIL;
  387. if ( !img.pixels )
  388. return E_POINTER;
  389. assert( idx < (metadata.mipLevels * metadata.arraySize) );
  390. initData[idx].pSysMem = img.pixels;
  391. initData[idx].SysMemPitch = static_cast<DWORD>( img.rowPitch );
  392. initData[idx].SysMemSlicePitch = static_cast<DWORD>( img.slicePitch );
  393. ++idx;
  394. }
  395. }
  396. }
  397. // Create texture using static initialization data
  398. HRESULT hr = E_FAIL;
  399. DXGI_FORMAT tformat = ( forceSRGB ) ? MakeSRGB( metadata.format ) : metadata.format;
  400. switch ( metadata.dimension )
  401. {
  402. case TEX_DIMENSION_TEXTURE1D:
  403. {
  404. D3D11_TEXTURE1D_DESC desc;
  405. desc.Width = static_cast<UINT>( metadata.width );
  406. desc.MipLevels = static_cast<UINT>( metadata.mipLevels );
  407. desc.ArraySize = static_cast<UINT>( metadata.arraySize );
  408. desc.Format = tformat;
  409. desc.Usage = usage;
  410. desc.BindFlags = bindFlags;
  411. desc.CPUAccessFlags = cpuAccessFlags;
  412. desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
  413. hr = pDevice->CreateTexture1D( &desc, initData.get(), reinterpret_cast<ID3D11Texture1D**>(ppResource) );
  414. }
  415. break;
  416. case TEX_DIMENSION_TEXTURE2D:
  417. {
  418. D3D11_TEXTURE2D_DESC desc;
  419. desc.Width = static_cast<UINT>( metadata.width );
  420. desc.Height = static_cast<UINT>( metadata.height );
  421. desc.MipLevels = static_cast<UINT>( metadata.mipLevels );
  422. desc.ArraySize = static_cast<UINT>( metadata.arraySize );
  423. desc.Format = tformat;
  424. desc.SampleDesc.Count = 1;
  425. desc.SampleDesc.Quality = 0;
  426. desc.Usage = usage;
  427. desc.BindFlags = bindFlags;
  428. desc.CPUAccessFlags = cpuAccessFlags;
  429. if ( metadata.IsCubemap() )
  430. desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE;
  431. else
  432. desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
  433. hr = pDevice->CreateTexture2D( &desc, initData.get(), reinterpret_cast<ID3D11Texture2D**>(ppResource) );
  434. }
  435. break;
  436. case TEX_DIMENSION_TEXTURE3D:
  437. {
  438. D3D11_TEXTURE3D_DESC desc;
  439. desc.Width = static_cast<UINT>( metadata.width );
  440. desc.Height = static_cast<UINT>( metadata.height );
  441. desc.Depth = static_cast<UINT>( metadata.depth );
  442. desc.MipLevels = static_cast<UINT>( metadata.mipLevels );
  443. desc.Format = tformat;
  444. desc.Usage = usage;
  445. desc.BindFlags = bindFlags;
  446. desc.CPUAccessFlags = cpuAccessFlags;
  447. desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
  448. hr = pDevice->CreateTexture3D( &desc, initData.get(), reinterpret_cast<ID3D11Texture3D**>(ppResource) );
  449. }
  450. break;
  451. }
  452. return hr;
  453. }
  454. //-------------------------------------------------------------------------------------
  455. // Create a shader resource view and associated texture
  456. //-------------------------------------------------------------------------------------
  457. _Use_decl_annotations_
  458. HRESULT CreateShaderResourceView( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
  459. ID3D11ShaderResourceView** ppSRV )
  460. {
  461. return CreateShaderResourceViewEx( pDevice, srcImages, nimages, metadata,
  462. D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false,
  463. ppSRV );
  464. }
  465. _Use_decl_annotations_
  466. HRESULT CreateShaderResourceViewEx( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
  467. D3D11_USAGE usage, unsigned int bindFlags, unsigned int cpuAccessFlags, unsigned int miscFlags, bool forceSRGB,
  468. ID3D11ShaderResourceView** ppSRV )
  469. {
  470. if ( !ppSRV )
  471. return E_INVALIDARG;
  472. *ppSRV = nullptr;
  473. ComPtr<ID3D11Resource> resource;
  474. HRESULT hr = CreateTextureEx( pDevice, srcImages, nimages, metadata,
  475. usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
  476. resource.GetAddressOf() );
  477. if ( FAILED(hr) )
  478. return hr;
  479. assert( resource );
  480. D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
  481. memset( &SRVDesc, 0, sizeof(SRVDesc) );
  482. if ( forceSRGB )
  483. SRVDesc.Format = MakeSRGB( metadata.format );
  484. else
  485. SRVDesc.Format = metadata.format;
  486. switch ( metadata.dimension )
  487. {
  488. case TEX_DIMENSION_TEXTURE1D:
  489. if ( metadata.arraySize > 1 )
  490. {
  491. SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY;
  492. SRVDesc.Texture1DArray.MipLevels = static_cast<UINT>( metadata.mipLevels );
  493. SRVDesc.Texture1DArray.ArraySize = static_cast<UINT>( metadata.arraySize );
  494. }
  495. else
  496. {
  497. SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D;
  498. SRVDesc.Texture1D.MipLevels = static_cast<UINT>( metadata.mipLevels );
  499. }
  500. break;
  501. case TEX_DIMENSION_TEXTURE2D:
  502. if ( metadata.IsCubemap() )
  503. {
  504. if (metadata.arraySize > 6)
  505. {
  506. assert( (metadata.arraySize % 6) == 0 );
  507. SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY;
  508. SRVDesc.TextureCubeArray.MipLevels = static_cast<UINT>( metadata.mipLevels );
  509. SRVDesc.TextureCubeArray.NumCubes = static_cast<UINT>( metadata.arraySize / 6 );
  510. }
  511. else
  512. {
  513. SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE;
  514. SRVDesc.TextureCube.MipLevels = static_cast<UINT>( metadata.mipLevels );
  515. }
  516. }
  517. else if ( metadata.arraySize > 1 )
  518. {
  519. SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY;
  520. SRVDesc.Texture2DArray.MipLevels = static_cast<UINT>( metadata.mipLevels );
  521. SRVDesc.Texture2DArray.ArraySize = static_cast<UINT>( metadata.arraySize );
  522. }
  523. else
  524. {
  525. SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
  526. SRVDesc.Texture2D.MipLevels = static_cast<UINT>( metadata.mipLevels );
  527. }
  528. break;
  529. case TEX_DIMENSION_TEXTURE3D:
  530. assert( metadata.arraySize == 1 );
  531. SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D;
  532. SRVDesc.Texture3D.MipLevels = static_cast<UINT>( metadata.mipLevels );
  533. break;
  534. default:
  535. return E_FAIL;
  536. }
  537. hr = pDevice->CreateShaderResourceView( resource.Get(), &SRVDesc, ppSRV );
  538. if ( FAILED(hr) )
  539. return hr;
  540. assert( *ppSRV );
  541. return S_OK;
  542. }
  543. //-------------------------------------------------------------------------------------
  544. // Save a texture resource to a DDS file in memory/on disk
  545. //-------------------------------------------------------------------------------------
  546. _Use_decl_annotations_
  547. HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID3D11Resource* pSource, ScratchImage& result )
  548. {
  549. if ( !pDevice || !pContext || !pSource )
  550. return E_INVALIDARG;
  551. D3D11_RESOURCE_DIMENSION resType = D3D11_RESOURCE_DIMENSION_UNKNOWN;
  552. pSource->GetType( &resType );
  553. HRESULT hr;
  554. switch( resType )
  555. {
  556. case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
  557. {
  558. ComPtr<ID3D11Texture1D> pTexture;
  559. hr = pSource->QueryInterface( __uuidof(ID3D11Texture1D), reinterpret_cast<void**>( pTexture.GetAddressOf() ) );
  560. if ( FAILED(hr) )
  561. break;
  562. assert( pTexture );
  563. D3D11_TEXTURE1D_DESC desc;
  564. pTexture->GetDesc( &desc );
  565. desc.BindFlags = 0;
  566. desc.MiscFlags = 0;
  567. desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  568. desc.Usage = D3D11_USAGE_STAGING;
  569. ComPtr<ID3D11Texture1D> pStaging;
  570. hr = pDevice->CreateTexture1D( &desc, 0, pStaging.GetAddressOf() );
  571. if ( FAILED(hr) )
  572. break;
  573. assert( pStaging );
  574. pContext->CopyResource( pStaging.Get(), pSource );
  575. TexMetadata mdata;
  576. mdata.width = desc.Width;
  577. mdata.height = mdata.depth = 1;
  578. mdata.arraySize = desc.ArraySize;
  579. mdata.mipLevels = desc.MipLevels;
  580. mdata.miscFlags = 0;
  581. mdata.miscFlags2 = 0;
  582. mdata.format = desc.Format;
  583. mdata.dimension = TEX_DIMENSION_TEXTURE1D;
  584. hr = result.Initialize( mdata );
  585. if ( FAILED(hr) )
  586. break;
  587. hr = _Capture( pContext, pStaging.Get(), mdata, result );
  588. }
  589. break;
  590. case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
  591. {
  592. ComPtr<ID3D11Texture2D> pTexture;
  593. hr = pSource->QueryInterface( __uuidof(ID3D11Texture2D), reinterpret_cast<void**>( pTexture.GetAddressOf() ) );
  594. if ( FAILED(hr) )
  595. break;
  596. assert( pTexture );
  597. D3D11_TEXTURE2D_DESC desc;
  598. pTexture->GetDesc( &desc );
  599. ComPtr<ID3D11Texture2D> pStaging;
  600. if ( desc.SampleDesc.Count > 1 )
  601. {
  602. desc.SampleDesc.Count = 1;
  603. desc.SampleDesc.Quality = 0;
  604. ComPtr<ID3D11Texture2D> pTemp;
  605. hr = pDevice->CreateTexture2D( &desc, 0, pTemp.GetAddressOf() );
  606. if ( FAILED(hr) )
  607. break;
  608. assert( pTemp );
  609. DXGI_FORMAT fmt = desc.Format;
  610. if ( IsTypeless(fmt) )
  611. {
  612. // Assume a UNORM if it exists otherwise use FLOAT
  613. fmt = MakeTypelessUNORM( fmt );
  614. fmt = MakeTypelessFLOAT( fmt );
  615. }
  616. UINT support = 0;
  617. hr = pDevice->CheckFormatSupport( fmt, &support );
  618. if ( FAILED(hr) )
  619. break;
  620. if ( !(support & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE) )
  621. {
  622. hr = E_FAIL;
  623. break;
  624. }
  625. for( UINT item = 0; item < desc.ArraySize; ++item )
  626. {
  627. for( UINT level = 0; level < desc.MipLevels; ++level )
  628. {
  629. UINT index = D3D11CalcSubresource( level, item, desc.MipLevels );
  630. pContext->ResolveSubresource( pTemp.Get(), index, pSource, index, fmt );
  631. }
  632. }
  633. desc.BindFlags = 0;
  634. desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
  635. desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  636. desc.Usage = D3D11_USAGE_STAGING;
  637. hr = pDevice->CreateTexture2D( &desc, 0, pStaging.GetAddressOf() );
  638. if ( FAILED(hr) )
  639. break;
  640. assert( pStaging );
  641. pContext->CopyResource( pStaging.Get(), pTemp.Get() );
  642. }
  643. else
  644. {
  645. desc.BindFlags = 0;
  646. desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
  647. desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  648. desc.Usage = D3D11_USAGE_STAGING;
  649. hr = pDevice->CreateTexture2D( &desc, 0, &pStaging );
  650. if ( FAILED(hr) )
  651. break;
  652. assert( pStaging );
  653. pContext->CopyResource( pStaging.Get(), pSource );
  654. }
  655. TexMetadata mdata;
  656. mdata.width = desc.Width;
  657. mdata.height = desc.Height;
  658. mdata.depth = 1;
  659. mdata.arraySize = desc.ArraySize;
  660. mdata.mipLevels = desc.MipLevels;
  661. mdata.miscFlags = (desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) ? TEX_MISC_TEXTURECUBE : 0;
  662. mdata.miscFlags2 = 0;
  663. mdata.format = desc.Format;
  664. mdata.dimension = TEX_DIMENSION_TEXTURE2D;
  665. hr = result.Initialize( mdata );
  666. if ( FAILED(hr) )
  667. break;
  668. hr = _Capture( pContext, pStaging.Get(), mdata, result );
  669. }
  670. break;
  671. case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
  672. {
  673. ComPtr<ID3D11Texture3D> pTexture;
  674. hr = pSource->QueryInterface( __uuidof(ID3D11Texture3D), reinterpret_cast<void**>( pTexture.GetAddressOf() ) );
  675. if ( FAILED(hr) )
  676. break;
  677. assert( pTexture );
  678. D3D11_TEXTURE3D_DESC desc;
  679. pTexture->GetDesc( &desc );
  680. desc.BindFlags = 0;
  681. desc.MiscFlags = 0;
  682. desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  683. desc.Usage = D3D11_USAGE_STAGING;
  684. ComPtr<ID3D11Texture3D> pStaging;
  685. hr = pDevice->CreateTexture3D( &desc, 0, pStaging.GetAddressOf() );
  686. if ( FAILED(hr) )
  687. break;
  688. assert( pStaging );
  689. pContext->CopyResource( pStaging.Get(), pSource );
  690. TexMetadata mdata;
  691. mdata.width = desc.Width;
  692. mdata.height = desc.Height;
  693. mdata.depth = desc.Depth;
  694. mdata.arraySize = 1;
  695. mdata.mipLevels = desc.MipLevels;
  696. mdata.miscFlags = 0;
  697. mdata.miscFlags2 = 0;
  698. mdata.format = desc.Format;
  699. mdata.dimension = TEX_DIMENSION_TEXTURE3D;
  700. hr = result.Initialize( mdata );
  701. if ( FAILED(hr) )
  702. break;
  703. hr = _Capture( pContext, pStaging.Get(), mdata, result );
  704. }
  705. break;
  706. default:
  707. hr = E_FAIL;
  708. break;
  709. }
  710. if ( FAILED(hr) )
  711. {
  712. result.Release();
  713. return hr;
  714. }
  715. return S_OK;
  716. }
  717. }; // namespace