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