1 //--------------------------------------------------------------------------------------
2 // File: DDSTextureLoader.cpp
4 // Function for loading a DDS texture and creating a Direct3D 11 runtime resource for it
6 // Note this function is useful as a light-weight runtime loader for DDS files. For
7 // a full-featured DDS file reader, writer, and texture processing pipeline see
8 // the 'Texconv' sample and the 'DirectXTex' library.
10 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
11 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
12 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
13 // PARTICULAR PURPOSE.
15 // Copyright (c) Microsoft Corporation. All rights reserved.
16 //--------------------------------------------------------------------------------------
19 #include <dxgiformat.h>
22 #include "DDSTextureLoader.h"
23 #include "DirectXSample.h"
25 using namespace Microsoft::WRL;
27 //--------------------------------------------------------------------------------------
29 //--------------------------------------------------------------------------------------
31 #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
32 ((uint32)(byte)(ch0) | ((uint32)(byte)(ch1) << 8) | \
33 ((uint32)(byte)(ch2) << 16) | ((uint32)(byte)(ch3) << 24 ))
34 #endif /* defined(MAKEFOURCC) */
36 //--------------------------------------------------------------------------------------
37 // DDS file structure definitions
39 // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library
40 //--------------------------------------------------------------------------------------
43 #define DDS_MAGIC 0x20534444 // "DDS "
45 struct DDS_PIXELFORMAT
57 #define DDS_FOURCC 0x00000004 // DDPF_FOURCC
58 #define DDS_RGB 0x00000040 // DDPF_RGB
59 #define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
60 #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
61 #define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS
62 #define DDS_ALPHA 0x00000002 // DDPF_ALPHA
63 #define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8
65 #define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
66 #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
67 #define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
68 #define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
69 #define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
71 #define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
72 #define DDS_WIDTH 0x00000004 // DDSD_WIDTH
74 #define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
75 #define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
76 #define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
78 #define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
79 #define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
80 #define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
81 #define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
82 #define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
83 #define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
85 #define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
86 DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
87 DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )
89 #define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP
91 #define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
99 uint32 pitchOrLinearSize;
100 uint32 depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags
102 uint32 reserved1[11];
103 DDS_PIXELFORMAT ddspf;
113 DXGI_FORMAT dxgiFormat;
114 uint32 resourceDimension;
115 uint32 miscFlag; // see D3D11_RESOURCE_MISC_FLAG
122 //--------------------------------------------------------------------------------------
123 // Return the BPP for a particular format
124 //--------------------------------------------------------------------------------------
125 static size_t BitsPerPixel( _In_ DXGI_FORMAT fmt )
129 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
130 case DXGI_FORMAT_R32G32B32A32_FLOAT:
131 case DXGI_FORMAT_R32G32B32A32_UINT:
132 case DXGI_FORMAT_R32G32B32A32_SINT:
135 case DXGI_FORMAT_R32G32B32_TYPELESS:
136 case DXGI_FORMAT_R32G32B32_FLOAT:
137 case DXGI_FORMAT_R32G32B32_UINT:
138 case DXGI_FORMAT_R32G32B32_SINT:
141 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
142 case DXGI_FORMAT_R16G16B16A16_FLOAT:
143 case DXGI_FORMAT_R16G16B16A16_UNORM:
144 case DXGI_FORMAT_R16G16B16A16_UINT:
145 case DXGI_FORMAT_R16G16B16A16_SNORM:
146 case DXGI_FORMAT_R16G16B16A16_SINT:
147 case DXGI_FORMAT_R32G32_TYPELESS:
148 case DXGI_FORMAT_R32G32_FLOAT:
149 case DXGI_FORMAT_R32G32_UINT:
150 case DXGI_FORMAT_R32G32_SINT:
151 case DXGI_FORMAT_R32G8X24_TYPELESS:
152 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
153 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
154 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
157 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
158 case DXGI_FORMAT_R10G10B10A2_UNORM:
159 case DXGI_FORMAT_R10G10B10A2_UINT:
160 case DXGI_FORMAT_R11G11B10_FLOAT:
161 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
162 case DXGI_FORMAT_R8G8B8A8_UNORM:
163 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
164 case DXGI_FORMAT_R8G8B8A8_UINT:
165 case DXGI_FORMAT_R8G8B8A8_SNORM:
166 case DXGI_FORMAT_R8G8B8A8_SINT:
167 case DXGI_FORMAT_R16G16_TYPELESS:
168 case DXGI_FORMAT_R16G16_FLOAT:
169 case DXGI_FORMAT_R16G16_UNORM:
170 case DXGI_FORMAT_R16G16_UINT:
171 case DXGI_FORMAT_R16G16_SNORM:
172 case DXGI_FORMAT_R16G16_SINT:
173 case DXGI_FORMAT_R32_TYPELESS:
174 case DXGI_FORMAT_D32_FLOAT:
175 case DXGI_FORMAT_R32_FLOAT:
176 case DXGI_FORMAT_R32_UINT:
177 case DXGI_FORMAT_R32_SINT:
178 case DXGI_FORMAT_R24G8_TYPELESS:
179 case DXGI_FORMAT_D24_UNORM_S8_UINT:
180 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
181 case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
182 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
183 case DXGI_FORMAT_R8G8_B8G8_UNORM:
184 case DXGI_FORMAT_G8R8_G8B8_UNORM:
185 case DXGI_FORMAT_B8G8R8A8_UNORM:
186 case DXGI_FORMAT_B8G8R8X8_UNORM:
187 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
188 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
189 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
190 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
191 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
194 case DXGI_FORMAT_R8G8_TYPELESS:
195 case DXGI_FORMAT_R8G8_UNORM:
196 case DXGI_FORMAT_R8G8_UINT:
197 case DXGI_FORMAT_R8G8_SNORM:
198 case DXGI_FORMAT_R8G8_SINT:
199 case DXGI_FORMAT_R16_TYPELESS:
200 case DXGI_FORMAT_R16_FLOAT:
201 case DXGI_FORMAT_D16_UNORM:
202 case DXGI_FORMAT_R16_UNORM:
203 case DXGI_FORMAT_R16_UINT:
204 case DXGI_FORMAT_R16_SNORM:
205 case DXGI_FORMAT_R16_SINT:
206 case DXGI_FORMAT_B5G6R5_UNORM:
207 case DXGI_FORMAT_B5G5R5A1_UNORM:
208 case DXGI_FORMAT_B4G4R4A4_UNORM:
211 case DXGI_FORMAT_R8_TYPELESS:
212 case DXGI_FORMAT_R8_UNORM:
213 case DXGI_FORMAT_R8_UINT:
214 case DXGI_FORMAT_R8_SNORM:
215 case DXGI_FORMAT_R8_SINT:
216 case DXGI_FORMAT_A8_UNORM:
219 case DXGI_FORMAT_R1_UNORM:
222 case DXGI_FORMAT_BC1_TYPELESS:
223 case DXGI_FORMAT_BC1_UNORM:
224 case DXGI_FORMAT_BC1_UNORM_SRGB:
225 case DXGI_FORMAT_BC4_TYPELESS:
226 case DXGI_FORMAT_BC4_UNORM:
227 case DXGI_FORMAT_BC4_SNORM:
230 case DXGI_FORMAT_BC2_TYPELESS:
231 case DXGI_FORMAT_BC2_UNORM:
232 case DXGI_FORMAT_BC2_UNORM_SRGB:
233 case DXGI_FORMAT_BC3_TYPELESS:
234 case DXGI_FORMAT_BC3_UNORM:
235 case DXGI_FORMAT_BC3_UNORM_SRGB:
236 case DXGI_FORMAT_BC5_TYPELESS:
237 case DXGI_FORMAT_BC5_UNORM:
238 case DXGI_FORMAT_BC5_SNORM:
239 case DXGI_FORMAT_BC6H_TYPELESS:
240 case DXGI_FORMAT_BC6H_UF16:
241 case DXGI_FORMAT_BC6H_SF16:
242 case DXGI_FORMAT_BC7_TYPELESS:
243 case DXGI_FORMAT_BC7_UNORM:
244 case DXGI_FORMAT_BC7_UNORM_SRGB:
253 //--------------------------------------------------------------------------------------
254 // Get surface information for a particular format
255 //--------------------------------------------------------------------------------------
256 static void GetSurfaceInfo( _In_ size_t width,
258 _In_ DXGI_FORMAT fmt,
259 _Out_opt_ size_t* outNumBytes,
260 _Out_opt_ size_t* outRowBytes,
261 _Out_opt_ size_t* outNumRows )
269 size_t bcnumBytesPerBlock = 0;
272 case DXGI_FORMAT_BC1_TYPELESS:
273 case DXGI_FORMAT_BC1_UNORM:
274 case DXGI_FORMAT_BC1_UNORM_SRGB:
275 case DXGI_FORMAT_BC4_TYPELESS:
276 case DXGI_FORMAT_BC4_UNORM:
277 case DXGI_FORMAT_BC4_SNORM:
279 bcnumBytesPerBlock = 8;
282 case DXGI_FORMAT_BC2_TYPELESS:
283 case DXGI_FORMAT_BC2_UNORM:
284 case DXGI_FORMAT_BC2_UNORM_SRGB:
285 case DXGI_FORMAT_BC3_TYPELESS:
286 case DXGI_FORMAT_BC3_UNORM:
287 case DXGI_FORMAT_BC3_UNORM_SRGB:
288 case DXGI_FORMAT_BC5_TYPELESS:
289 case DXGI_FORMAT_BC5_UNORM:
290 case DXGI_FORMAT_BC5_SNORM:
291 case DXGI_FORMAT_BC6H_TYPELESS:
292 case DXGI_FORMAT_BC6H_UF16:
293 case DXGI_FORMAT_BC6H_SF16:
294 case DXGI_FORMAT_BC7_TYPELESS:
295 case DXGI_FORMAT_BC7_UNORM:
296 case DXGI_FORMAT_BC7_UNORM_SRGB:
298 bcnumBytesPerBlock = 16;
301 case DXGI_FORMAT_R8G8_B8G8_UNORM:
302 case DXGI_FORMAT_G8R8_G8B8_UNORM:
309 size_t numBlocksWide = 0;
312 numBlocksWide = max( 1, (width + 3) / 4 );
314 size_t numBlocksHigh = 0;
317 numBlocksHigh = max( 1, (height + 3) / 4 );
319 rowBytes = numBlocksWide * bcnumBytesPerBlock;
320 numRows = numBlocksHigh;
324 rowBytes = ( ( width + 1 ) >> 1 ) * 4;
329 size_t bpp = BitsPerPixel( fmt );
330 rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte
334 numBytes = rowBytes * numRows;
337 *outNumBytes = numBytes;
341 *outRowBytes = rowBytes;
345 *outNumRows = numRows;
350 //--------------------------------------------------------------------------------------
351 #define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a )
353 static DXGI_FORMAT GetDXGIFormat( const DDS_PIXELFORMAT& ddpf )
355 if (ddpf.flags & DDS_RGB)
357 // Note that sRGB formats are written using the "DX10" extended header
359 switch (ddpf.RGBBitCount)
362 if (ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000))
364 return DXGI_FORMAT_R8G8B8A8_UNORM;
367 if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0xff000000))
369 return DXGI_FORMAT_B8G8R8A8_UNORM;
372 if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000))
374 return DXGI_FORMAT_B8G8R8X8_UNORM;
377 // No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8
379 // Note that many common DDS reader/writers (including D3DX) swap the
380 // the RED/BLUE masks for 10:10:10:2 formats. We assumme
381 // below that the 'backwards' header mask is being used since it is most
382 // likely written by D3DX. The more robust solution is to use the 'DX10'
383 // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly
385 // For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data
386 if (ISBITMASK(0x3ff00000,0x000ffc00,0x000003ff,0xc0000000))
388 return DXGI_FORMAT_R10G10B10A2_UNORM;
391 // No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10
393 if (ISBITMASK(0x0000ffff,0xffff0000,0x00000000,0x00000000))
395 return DXGI_FORMAT_R16G16_UNORM;
398 if (ISBITMASK(0xffffffff,0x00000000,0x00000000,0x00000000))
400 // Only 32-bit color channel format in D3D9 was R32F
401 return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114
406 // No 24bpp DXGI formats aka D3DFMT_R8G8B8
410 if (ISBITMASK(0x7c00,0x03e0,0x001f,0x8000))
412 return DXGI_FORMAT_B5G5R5A1_UNORM;
414 if (ISBITMASK(0xf800,0x07e0,0x001f,0x0000))
416 return DXGI_FORMAT_B5G6R5_UNORM;
419 // No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5
420 if (ISBITMASK(0x0f00,0x00f0,0x000f,0xf000))
422 return DXGI_FORMAT_B4G4R4A4_UNORM;
425 // No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4
427 // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
431 else if (ddpf.flags & DDS_LUMINANCE)
433 if (8 == ddpf.RGBBitCount)
435 if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x00000000))
437 return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension
440 // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4
443 if (16 == ddpf.RGBBitCount)
445 if (ISBITMASK(0x0000ffff,0x00000000,0x00000000,0x00000000))
447 return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension
449 if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x0000ff00))
451 return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension
455 else if (ddpf.flags & DDS_ALPHA)
457 if (8 == ddpf.RGBBitCount)
459 return DXGI_FORMAT_A8_UNORM;
462 else if (ddpf.flags & DDS_FOURCC)
464 if (MAKEFOURCC( 'D', 'X', 'T', '1' ) == ddpf.fourCC)
466 return DXGI_FORMAT_BC1_UNORM;
468 if (MAKEFOURCC( 'D', 'X', 'T', '3' ) == ddpf.fourCC)
470 return DXGI_FORMAT_BC2_UNORM;
472 if (MAKEFOURCC( 'D', 'X', 'T', '5' ) == ddpf.fourCC)
474 return DXGI_FORMAT_BC3_UNORM;
477 // While pre-mulitplied alpha isn't directly supported by the DXGI formats,
478 // they are basically the same as these BC formats so they can be mapped
479 if (MAKEFOURCC( 'D', 'X', 'T', '2' ) == ddpf.fourCC)
481 return DXGI_FORMAT_BC2_UNORM;
483 if (MAKEFOURCC( 'D', 'X', 'T', '4' ) == ddpf.fourCC)
485 return DXGI_FORMAT_BC3_UNORM;
488 if (MAKEFOURCC( 'A', 'T', 'I', '1' ) == ddpf.fourCC)
490 return DXGI_FORMAT_BC4_UNORM;
492 if (MAKEFOURCC( 'B', 'C', '4', 'U' ) == ddpf.fourCC)
494 return DXGI_FORMAT_BC4_UNORM;
496 if (MAKEFOURCC( 'B', 'C', '4', 'S' ) == ddpf.fourCC)
498 return DXGI_FORMAT_BC4_SNORM;
501 if (MAKEFOURCC( 'A', 'T', 'I', '2' ) == ddpf.fourCC)
503 return DXGI_FORMAT_BC5_UNORM;
505 if (MAKEFOURCC( 'B', 'C', '5', 'U' ) == ddpf.fourCC)
507 return DXGI_FORMAT_BC5_UNORM;
509 if (MAKEFOURCC( 'B', 'C', '5', 'S' ) == ddpf.fourCC)
511 return DXGI_FORMAT_BC5_SNORM;
514 // BC6H and BC7 are written using the "DX10" extended header
516 if (MAKEFOURCC( 'R', 'G', 'B', 'G' ) == ddpf.fourCC)
518 return DXGI_FORMAT_R8G8_B8G8_UNORM;
520 if (MAKEFOURCC( 'G', 'R', 'G', 'B' ) == ddpf.fourCC)
522 return DXGI_FORMAT_G8R8_G8B8_UNORM;
525 // Check for D3DFORMAT enums being set here
526 switch( ddpf.fourCC )
528 case 36: // D3DFMT_A16B16G16R16
529 return DXGI_FORMAT_R16G16B16A16_UNORM;
531 case 110: // D3DFMT_Q16W16V16U16
532 return DXGI_FORMAT_R16G16B16A16_SNORM;
534 case 111: // D3DFMT_R16F
535 return DXGI_FORMAT_R16_FLOAT;
537 case 112: // D3DFMT_G16R16F
538 return DXGI_FORMAT_R16G16_FLOAT;
540 case 113: // D3DFMT_A16B16G16R16F
541 return DXGI_FORMAT_R16G16B16A16_FLOAT;
543 case 114: // D3DFMT_R32F
544 return DXGI_FORMAT_R32_FLOAT;
546 case 115: // D3DFMT_G32R32F
547 return DXGI_FORMAT_R32G32_FLOAT;
549 case 116: // D3DFMT_A32B32G32R32F
550 return DXGI_FORMAT_R32G32B32A32_FLOAT;
554 return DXGI_FORMAT_UNKNOWN;
558 //--------------------------------------------------------------------------------------
559 static void FillInitData( _In_ size_t width,
562 _In_ size_t mipCount,
563 _In_ size_t arraySize,
564 _In_ DXGI_FORMAT format,
567 _In_reads_bytes_(bitSize) const byte* bitData,
568 _Out_ size_t& twidth,
569 _Out_ size_t& theight,
570 _Out_ size_t& tdepth,
571 _Out_ size_t& skipMip,
572 _Out_writes_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData )
574 if ( !bitData || !initData )
575 throw ref new Platform::InvalidArgumentException();
585 const byte* pSrcBits = bitData;
586 const byte* pEndBits = bitData + bitSize;
589 for( size_t j = 0; j < arraySize; j++ )
594 for( size_t i = 0; i < mipCount; i++ )
604 if ( (mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize) )
613 initData[index].pSysMem = ( const void* )pSrcBits;
614 initData[index].SysMemPitch = static_cast<UINT>( RowBytes );
615 initData[index].SysMemSlicePitch = static_cast<UINT>( NumBytes );
621 if (pSrcBits + (NumBytes*d) > pEndBits)
623 throw ref new Platform::OutOfBoundsException();
626 pSrcBits += NumBytes * d;
647 throw ref new Platform::FailureException();
651 //--------------------------------------------------------------------------------------
652 static HRESULT CreateD3DResources( _In_ ID3D11Device* d3dDevice,
657 _In_ size_t mipCount,
658 _In_ size_t arraySize,
659 _In_ DXGI_FORMAT format,
661 _In_reads_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData,
662 _Out_opt_ ID3D11Resource** texture,
663 _Out_opt_ ID3D11ShaderResourceView** textureView )
665 if ( !d3dDevice || !initData )
672 case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
674 D3D11_TEXTURE1D_DESC desc;
675 desc.Width = static_cast<UINT>( width );
676 desc.MipLevels = static_cast<UINT>( mipCount );
677 desc.ArraySize = static_cast<UINT>( arraySize );
678 desc.Format = format;
679 desc.Usage = D3D11_USAGE_DEFAULT;
680 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
681 desc.CPUAccessFlags = 0;
684 ID3D11Texture1D* tex = nullptr;
685 hr = d3dDevice->CreateTexture1D( &desc,
689 if (SUCCEEDED( hr ) && tex != 0)
691 if (textureView != 0)
693 D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
694 memset( &SRVDesc, 0, sizeof( SRVDesc ) );
695 SRVDesc.Format = format;
699 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY;
700 SRVDesc.Texture1DArray.MipLevels = desc.MipLevels;
701 SRVDesc.Texture1DArray.ArraySize = static_cast<UINT>( arraySize );
705 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D;
706 SRVDesc.Texture1D.MipLevels = desc.MipLevels;
709 hr = d3dDevice->CreateShaderResourceView( tex,
727 case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
729 D3D11_TEXTURE2D_DESC desc;
730 desc.Width = static_cast<UINT>( width );
731 desc.Height = static_cast<UINT>( height );
732 desc.MipLevels = static_cast<UINT>( mipCount );
733 desc.ArraySize = static_cast<UINT>( arraySize );
734 desc.Format = format;
735 desc.SampleDesc.Count = 1;
736 desc.SampleDesc.Quality = 0;
737 desc.Usage = D3D11_USAGE_DEFAULT;
738 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
739 desc.CPUAccessFlags = 0;
740 desc.MiscFlags = (isCubeMap) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
742 ID3D11Texture2D* tex = nullptr;
743 hr = d3dDevice->CreateTexture2D( &desc,
747 if (SUCCEEDED( hr ) && tex != 0)
749 if (textureView != 0)
751 D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
752 memset( &SRVDesc, 0, sizeof( SRVDesc ) );
753 SRVDesc.Format = format;
759 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY;
760 SRVDesc.TextureCubeArray.MipLevels = desc.MipLevels;
762 // Earlier we set arraySize to (NumCubes * 6)
763 SRVDesc.TextureCubeArray.NumCubes = static_cast<UINT>( arraySize / 6 );
767 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE;
768 SRVDesc.TextureCube.MipLevels = desc.MipLevels;
771 else if (arraySize > 1)
773 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY;
774 SRVDesc.Texture2DArray.MipLevels = desc.MipLevels;
775 SRVDesc.Texture2DArray.ArraySize = static_cast<UINT>( arraySize );
779 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
780 SRVDesc.Texture2D.MipLevels = desc.MipLevels;
783 hr = d3dDevice->CreateShaderResourceView( tex,
801 case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
803 D3D11_TEXTURE3D_DESC desc;
804 desc.Width = static_cast<UINT>( width );
805 desc.Height = static_cast<UINT>( height );
806 desc.Depth = static_cast<UINT>( depth );
807 desc.MipLevels = static_cast<UINT>( mipCount );
808 desc.Format = format;
809 desc.Usage = D3D11_USAGE_DEFAULT;
810 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
811 desc.CPUAccessFlags = 0;
814 ID3D11Texture3D* tex = nullptr;
815 hr = d3dDevice->CreateTexture3D( &desc,
819 if (SUCCEEDED( hr ) && tex != 0)
821 if (textureView != 0)
823 D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
824 memset( &SRVDesc, 0, sizeof( SRVDesc ) );
825 SRVDesc.Format = format;
826 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D;
827 SRVDesc.Texture3D.MipLevels = desc.MipLevels;
829 hr = d3dDevice->CreateShaderResourceView( tex,
852 //--------------------------------------------------------------------------------------
853 static void CreateTextureFromDDS( _In_ ID3D11Device* d3dDevice,
854 _In_ const DDS_HEADER* header,
855 _In_reads_bytes_(bitSize) const byte* bitData,
857 _Out_opt_ ID3D11Resource** texture,
858 _Out_opt_ ID3D11ShaderResourceView** textureView,
859 _In_ size_t maxsize )
863 size_t width = header->width;
864 size_t height = header->height;
865 size_t depth = header->depth;
867 uint32 resDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
868 size_t arraySize = 1;
869 DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
870 bool isCubeMap = false;
872 size_t mipCount = header->mipMapCount;
878 if ((header->ddspf.flags & DDS_FOURCC) &&
879 (MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC ))
881 const DDS_HEADER_DXT10* d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const char*)header + sizeof(DDS_HEADER) );
883 arraySize = d3d10ext->arraySize;
886 throw ref new Platform::FailureException();
889 if (BitsPerPixel( d3d10ext->dxgiFormat ) == 0)
891 throw ref new Platform::FailureException();
894 format = d3d10ext->dxgiFormat;
896 switch ( d3d10ext->resourceDimension )
898 case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
899 // D3DX writes 1D textures with a fixed Height of 1
900 if ((header->flags & DDS_HEIGHT) && height != 1)
902 throw ref new Platform::FailureException();
907 case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
908 if (d3d10ext->miscFlag & D3D11_RESOURCE_MISC_TEXTURECUBE)
916 case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
917 if (!(header->flags & DDS_HEADER_FLAGS_VOLUME))
919 throw ref new Platform::FailureException();
924 throw ref new Platform::FailureException();
929 return throw ref new Platform::FailureException();
932 resDim = d3d10ext->resourceDimension;
936 format = GetDXGIFormat( header->ddspf );
938 if (format == DXGI_FORMAT_UNKNOWN)
940 return throw ref new Platform::FailureException();
943 if (header->flags & DDS_HEADER_FLAGS_VOLUME)
945 resDim = D3D11_RESOURCE_DIMENSION_TEXTURE3D;
949 if (header->caps2 & DDS_CUBEMAP)
951 // We require all six faces to be defined
952 if ((header->caps2 & DDS_CUBEMAP_ALLFACES ) != DDS_CUBEMAP_ALLFACES)
954 return throw ref new Platform::FailureException();
962 resDim = D3D11_RESOURCE_DIMENSION_TEXTURE2D;
964 // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
967 assert( BitsPerPixel( format ) != 0 );
970 // Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements)
971 if (mipCount > D3D11_REQ_MIP_LEVELS)
973 return throw ref new Platform::FailureException();
978 case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
979 if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||
980 (width > D3D11_REQ_TEXTURE1D_U_DIMENSION) )
982 return throw ref new Platform::FailureException();
986 case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
989 // This is the right bound because we set arraySize to (NumCubes*6) above
990 if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
991 (width > D3D11_REQ_TEXTURECUBE_DIMENSION) ||
992 (height > D3D11_REQ_TEXTURECUBE_DIMENSION))
994 return throw ref new Platform::FailureException();
997 else if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
998 (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) ||
999 (height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION))
1001 return throw ref new Platform::FailureException();
1005 case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
1006 if ((arraySize > 1) ||
1007 (width > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
1008 (height > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
1009 (depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) )
1011 return throw ref new Platform::FailureException();
1016 // Create the texture
1017 std::unique_ptr<D3D11_SUBRESOURCE_DATA> initData( new D3D11_SUBRESOURCE_DATA[ mipCount * arraySize ] );
1023 FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
1024 twidth, theight, tdepth, skipMip, initData.get() );
1026 hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, isCubeMap, initData.get(), texture, textureView );
1028 if ( (hr == E_INVALIDARG) && !maxsize && (mipCount > 1) )
1030 // Retry with a maxsize determined by feature level
1031 switch( d3dDevice->GetFeatureLevel() )
1033 case D3D_FEATURE_LEVEL_9_1:
1034 case D3D_FEATURE_LEVEL_9_2:
1037 maxsize = 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/;
1041 maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
1042 ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
1043 : 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
1047 case D3D_FEATURE_LEVEL_9_3:
1048 maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
1049 ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
1050 : 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
1053 default: // D3D_FEATURE_LEVEL_10_0 & D3D_FEATURE_LEVEL_10_1
1054 maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
1055 ? 2048 /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
1056 : 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
1060 FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
1061 twidth, theight, tdepth, skipMip, initData.get() );
1063 hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, isCubeMap, initData.get(), texture, textureView );
1066 DX::ThrowIfFailed(hr);
1069 //--------------------------------------------------------------------------------------
1070 void CreateDDSTextureFromMemory( _In_ ID3D11Device* d3dDevice,
1071 _In_reads_bytes_(ddsDataSize) const byte* ddsData,
1072 _In_ size_t ddsDataSize,
1073 _Out_opt_ ID3D11Resource** texture,
1074 _Out_opt_ ID3D11ShaderResourceView** textureView,
1075 _In_ size_t maxsize )
1077 if (!d3dDevice || !ddsData || (!texture && !textureView))
1079 throw ref new Platform::InvalidArgumentException();
1082 // Validate DDS file in memory
1083 if (ddsDataSize < (sizeof(uint32) + sizeof(DDS_HEADER)))
1085 throw ref new Platform::FailureException();
1088 uint32 dwMagicNumber = *( const uint32* )( ddsData );
1089 if (dwMagicNumber != DDS_MAGIC)
1091 throw ref new Platform::FailureException();
1094 const DDS_HEADER* header = reinterpret_cast<const DDS_HEADER*>( ddsData + sizeof( uint32 ) );
1096 // Verify header to validate DDS file
1097 if (header->size != sizeof(DDS_HEADER) ||
1098 header->ddspf.size != sizeof(DDS_PIXELFORMAT))
1100 throw ref new Platform::FailureException();
1103 // Check for DX10 extension
1104 bool bDXT10Header = false;
1105 if ((header->ddspf.flags & DDS_FOURCC) &&
1106 (MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC) )
1108 // Must be long enough for both headers and magic value
1109 if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32) + sizeof(DDS_HEADER_DXT10)))
1111 throw ref new Platform::FailureException();
1114 bDXT10Header = true;
1117 ptrdiff_t offset = sizeof( uint32 )
1118 + sizeof( DDS_HEADER )
1119 + (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0);
1121 CreateTextureFromDDS( d3dDevice,
1124 ddsDataSize - offset,