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>
23 #include "DDSTextureLoader.h"
24 #include "DirectXSample.h"
26 using namespace Microsoft::WRL;
28 //--------------------------------------------------------------------------------------
30 //--------------------------------------------------------------------------------------
32 #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
33 ((uint32)(byte)(ch0) | ((uint32)(byte)(ch1) << 8) | \
34 ((uint32)(byte)(ch2) << 16) | ((uint32)(byte)(ch3) << 24))
35 #endif /* defined(MAKEFOURCC) */
37 //--------------------------------------------------------------------------------------
38 // DDS file structure definitions
40 // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library
41 //--------------------------------------------------------------------------------------
44 #define DDS_MAGIC 0x20534444 // "DDS "
46 struct DDS_PIXELFORMAT
58 #define DDS_FOURCC 0x00000004 // DDPF_FOURCC
59 #define DDS_RGB 0x00000040 // DDPF_RGB
60 #define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
61 #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
62 #define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS
63 #define DDS_ALPHA 0x00000002 // DDPF_ALPHA
64 #define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8
66 #define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
67 #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
68 #define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
69 #define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
70 #define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
72 #define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
73 #define DDS_WIDTH 0x00000004 // DDSD_WIDTH
75 #define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
76 #define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
77 #define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
79 #define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
80 #define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
81 #define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
82 #define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
83 #define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
84 #define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
86 #define DDS_CUBEMAP_ALLFACES (DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
87 DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
88 DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ)
90 #define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP
92 #define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
100 uint32 pitchOrLinearSize;
101 uint32 depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags
103 uint32 reserved1[11];
104 DDS_PIXELFORMAT ddspf;
114 DXGI_FORMAT dxgiFormat;
115 uint32 resourceDimension;
116 uint32 miscFlag; // see D3D11_RESOURCE_MISC_FLAG
123 //--------------------------------------------------------------------------------------
124 // Return the BPP for a particular format
125 //--------------------------------------------------------------------------------------
126 static size_t BitsPerPixel(_In_ DXGI_FORMAT fmt)
130 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
131 case DXGI_FORMAT_R32G32B32A32_FLOAT:
132 case DXGI_FORMAT_R32G32B32A32_UINT:
133 case DXGI_FORMAT_R32G32B32A32_SINT:
136 case DXGI_FORMAT_R32G32B32_TYPELESS:
137 case DXGI_FORMAT_R32G32B32_FLOAT:
138 case DXGI_FORMAT_R32G32B32_UINT:
139 case DXGI_FORMAT_R32G32B32_SINT:
142 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
143 case DXGI_FORMAT_R16G16B16A16_FLOAT:
144 case DXGI_FORMAT_R16G16B16A16_UNORM:
145 case DXGI_FORMAT_R16G16B16A16_UINT:
146 case DXGI_FORMAT_R16G16B16A16_SNORM:
147 case DXGI_FORMAT_R16G16B16A16_SINT:
148 case DXGI_FORMAT_R32G32_TYPELESS:
149 case DXGI_FORMAT_R32G32_FLOAT:
150 case DXGI_FORMAT_R32G32_UINT:
151 case DXGI_FORMAT_R32G32_SINT:
152 case DXGI_FORMAT_R32G8X24_TYPELESS:
153 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
154 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
155 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
158 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
159 case DXGI_FORMAT_R10G10B10A2_UNORM:
160 case DXGI_FORMAT_R10G10B10A2_UINT:
161 case DXGI_FORMAT_R11G11B10_FLOAT:
162 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
163 case DXGI_FORMAT_R8G8B8A8_UNORM:
164 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
165 case DXGI_FORMAT_R8G8B8A8_UINT:
166 case DXGI_FORMAT_R8G8B8A8_SNORM:
167 case DXGI_FORMAT_R8G8B8A8_SINT:
168 case DXGI_FORMAT_R16G16_TYPELESS:
169 case DXGI_FORMAT_R16G16_FLOAT:
170 case DXGI_FORMAT_R16G16_UNORM:
171 case DXGI_FORMAT_R16G16_UINT:
172 case DXGI_FORMAT_R16G16_SNORM:
173 case DXGI_FORMAT_R16G16_SINT:
174 case DXGI_FORMAT_R32_TYPELESS:
175 case DXGI_FORMAT_D32_FLOAT:
176 case DXGI_FORMAT_R32_FLOAT:
177 case DXGI_FORMAT_R32_UINT:
178 case DXGI_FORMAT_R32_SINT:
179 case DXGI_FORMAT_R24G8_TYPELESS:
180 case DXGI_FORMAT_D24_UNORM_S8_UINT:
181 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
182 case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
183 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
184 case DXGI_FORMAT_R8G8_B8G8_UNORM:
185 case DXGI_FORMAT_G8R8_G8B8_UNORM:
186 case DXGI_FORMAT_B8G8R8A8_UNORM:
187 case DXGI_FORMAT_B8G8R8X8_UNORM:
188 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
189 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
190 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
191 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
192 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
195 case DXGI_FORMAT_R8G8_TYPELESS:
196 case DXGI_FORMAT_R8G8_UNORM:
197 case DXGI_FORMAT_R8G8_UINT:
198 case DXGI_FORMAT_R8G8_SNORM:
199 case DXGI_FORMAT_R8G8_SINT:
200 case DXGI_FORMAT_R16_TYPELESS:
201 case DXGI_FORMAT_R16_FLOAT:
202 case DXGI_FORMAT_D16_UNORM:
203 case DXGI_FORMAT_R16_UNORM:
204 case DXGI_FORMAT_R16_UINT:
205 case DXGI_FORMAT_R16_SNORM:
206 case DXGI_FORMAT_R16_SINT:
207 case DXGI_FORMAT_B5G6R5_UNORM:
208 case DXGI_FORMAT_B5G5R5A1_UNORM:
209 case DXGI_FORMAT_B4G4R4A4_UNORM:
212 case DXGI_FORMAT_R8_TYPELESS:
213 case DXGI_FORMAT_R8_UNORM:
214 case DXGI_FORMAT_R8_UINT:
215 case DXGI_FORMAT_R8_SNORM:
216 case DXGI_FORMAT_R8_SINT:
217 case DXGI_FORMAT_A8_UNORM:
220 case DXGI_FORMAT_R1_UNORM:
223 case DXGI_FORMAT_BC1_TYPELESS:
224 case DXGI_FORMAT_BC1_UNORM:
225 case DXGI_FORMAT_BC1_UNORM_SRGB:
226 case DXGI_FORMAT_BC4_TYPELESS:
227 case DXGI_FORMAT_BC4_UNORM:
228 case DXGI_FORMAT_BC4_SNORM:
231 case DXGI_FORMAT_BC2_TYPELESS:
232 case DXGI_FORMAT_BC2_UNORM:
233 case DXGI_FORMAT_BC2_UNORM_SRGB:
234 case DXGI_FORMAT_BC3_TYPELESS:
235 case DXGI_FORMAT_BC3_UNORM:
236 case DXGI_FORMAT_BC3_UNORM_SRGB:
237 case DXGI_FORMAT_BC5_TYPELESS:
238 case DXGI_FORMAT_BC5_UNORM:
239 case DXGI_FORMAT_BC5_SNORM:
240 case DXGI_FORMAT_BC6H_TYPELESS:
241 case DXGI_FORMAT_BC6H_UF16:
242 case DXGI_FORMAT_BC6H_SF16:
243 case DXGI_FORMAT_BC7_TYPELESS:
244 case DXGI_FORMAT_BC7_UNORM:
245 case DXGI_FORMAT_BC7_UNORM_SRGB:
254 //--------------------------------------------------------------------------------------
255 // Get surface information for a particular format
256 //--------------------------------------------------------------------------------------
257 static void GetSurfaceInfo(
260 _In_ DXGI_FORMAT fmt,
261 _Out_opt_ size_t* outNumBytes,
262 _Out_opt_ size_t* outRowBytes,
263 _Out_opt_ size_t* outNumRows
272 size_t bcnumBytesPerBlock = 0;
275 case DXGI_FORMAT_BC1_TYPELESS:
276 case DXGI_FORMAT_BC1_UNORM:
277 case DXGI_FORMAT_BC1_UNORM_SRGB:
278 case DXGI_FORMAT_BC4_TYPELESS:
279 case DXGI_FORMAT_BC4_UNORM:
280 case DXGI_FORMAT_BC4_SNORM:
282 bcnumBytesPerBlock = 8;
285 case DXGI_FORMAT_BC2_TYPELESS:
286 case DXGI_FORMAT_BC2_UNORM:
287 case DXGI_FORMAT_BC2_UNORM_SRGB:
288 case DXGI_FORMAT_BC3_TYPELESS:
289 case DXGI_FORMAT_BC3_UNORM:
290 case DXGI_FORMAT_BC3_UNORM_SRGB:
291 case DXGI_FORMAT_BC5_TYPELESS:
292 case DXGI_FORMAT_BC5_UNORM:
293 case DXGI_FORMAT_BC5_SNORM:
294 case DXGI_FORMAT_BC6H_TYPELESS:
295 case DXGI_FORMAT_BC6H_UF16:
296 case DXGI_FORMAT_BC6H_SF16:
297 case DXGI_FORMAT_BC7_TYPELESS:
298 case DXGI_FORMAT_BC7_UNORM:
299 case DXGI_FORMAT_BC7_UNORM_SRGB:
301 bcnumBytesPerBlock = 16;
304 case DXGI_FORMAT_R8G8_B8G8_UNORM:
305 case DXGI_FORMAT_G8R8_G8B8_UNORM:
312 size_t numBlocksWide = 0;
315 numBlocksWide = std::max<size_t>(1, (width + 3) / 4);
317 size_t numBlocksHigh = 0;
320 numBlocksHigh = std::max<size_t>(1, (height + 3) / 4);
322 rowBytes = numBlocksWide * bcnumBytesPerBlock;
323 numRows = numBlocksHigh;
327 rowBytes = ((width + 1) >> 1) * 4;
332 size_t bpp = BitsPerPixel(fmt);
333 rowBytes = (width * bpp + 7) / 8; // round up to nearest byte
337 numBytes = rowBytes * numRows;
340 *outNumBytes = numBytes;
344 *outRowBytes = rowBytes;
348 *outNumRows = numRows;
353 //--------------------------------------------------------------------------------------
354 #define ISBITMASK(r, g, b, a) (ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a)
356 static DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT& ddpf)
358 if (ddpf.flags & DDS_RGB)
360 // Note that sRGB formats are written using the "DX10" extended header
362 switch (ddpf.RGBBitCount)
365 if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000))
367 return DXGI_FORMAT_R8G8B8A8_UNORM;
370 if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000))
372 return DXGI_FORMAT_B8G8R8A8_UNORM;
375 if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000))
377 return DXGI_FORMAT_B8G8R8X8_UNORM;
380 // No DXGI format maps to ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000) aka D3DFMT_X8B8G8R8
382 // Note that many common DDS reader/writers (including D3DX) swap the
383 // the RED/BLUE masks for 10:10:10:2 formats. We assumme
384 // below that the 'backwards' header mask is being used since it is most
385 // likely written by D3DX. The more robust solution is to use the 'DX10'
386 // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly
388 // For 'correct' writers, this should be 0x000003ff, 0x000ffc00, 0x3ff00000 for RGB data
389 if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000))
391 return DXGI_FORMAT_R10G10B10A2_UNORM;
394 // No DXGI format maps to ISBITMASK(0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000) aka D3DFMT_A2R10G10B10
396 if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))
398 return DXGI_FORMAT_R16G16_UNORM;
401 if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000))
403 // Only 32-bit color channel format in D3D9 was R32F
404 return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114
409 // No 24bpp DXGI formats aka D3DFMT_R8G8B8
413 if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000))
415 return DXGI_FORMAT_B5G5R5A1_UNORM;
417 if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000))
419 return DXGI_FORMAT_B5G6R5_UNORM;
422 // No DXGI format maps to ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x0000) aka D3DFMT_X1R5G5B5
423 if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000))
425 return DXGI_FORMAT_B4G4R4A4_UNORM;
428 // No DXGI format maps to ISBITMASK(0x0f00, 0x00f0, 0x000f, 0x0000) aka D3DFMT_X4R4G4B4
430 // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
434 else if (ddpf.flags & DDS_LUMINANCE)
436 if (8 == ddpf.RGBBitCount)
438 if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000))
440 return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension
443 // No DXGI format maps to ISBITMASK(0x0f, 0x00, 0x00, 0xf0) aka D3DFMT_A4L4
446 if (16 == ddpf.RGBBitCount)
448 if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000))
450 return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension
452 if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00))
454 return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension
458 else if (ddpf.flags & DDS_ALPHA)
460 if (8 == ddpf.RGBBitCount)
462 return DXGI_FORMAT_A8_UNORM;
465 else if (ddpf.flags & DDS_FOURCC)
467 if (MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC)
469 return DXGI_FORMAT_BC1_UNORM;
471 if (MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC)
473 return DXGI_FORMAT_BC2_UNORM;
475 if (MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC)
477 return DXGI_FORMAT_BC3_UNORM;
480 // While pre-mulitplied alpha isn't directly supported by the DXGI formats,
481 // they are basically the same as these BC formats so they can be mapped
482 if (MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC)
484 return DXGI_FORMAT_BC2_UNORM;
486 if (MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC)
488 return DXGI_FORMAT_BC3_UNORM;
491 if (MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC)
493 return DXGI_FORMAT_BC4_UNORM;
495 if (MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC)
497 return DXGI_FORMAT_BC4_UNORM;
499 if (MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC)
501 return DXGI_FORMAT_BC4_SNORM;
504 if (MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC)
506 return DXGI_FORMAT_BC5_UNORM;
508 if (MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC)
510 return DXGI_FORMAT_BC5_UNORM;
512 if (MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC)
514 return DXGI_FORMAT_BC5_SNORM;
517 // BC6H and BC7 are written using the "DX10" extended header
519 if (MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC)
521 return DXGI_FORMAT_R8G8_B8G8_UNORM;
523 if (MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC)
525 return DXGI_FORMAT_G8R8_G8B8_UNORM;
528 // Check for D3DFORMAT enums being set here
531 case 36: // D3DFMT_A16B16G16R16
532 return DXGI_FORMAT_R16G16B16A16_UNORM;
534 case 110: // D3DFMT_Q16W16V16U16
535 return DXGI_FORMAT_R16G16B16A16_SNORM;
537 case 111: // D3DFMT_R16F
538 return DXGI_FORMAT_R16_FLOAT;
540 case 112: // D3DFMT_G16R16F
541 return DXGI_FORMAT_R16G16_FLOAT;
543 case 113: // D3DFMT_A16B16G16R16F
544 return DXGI_FORMAT_R16G16B16A16_FLOAT;
546 case 114: // D3DFMT_R32F
547 return DXGI_FORMAT_R32_FLOAT;
549 case 115: // D3DFMT_G32R32F
550 return DXGI_FORMAT_R32G32_FLOAT;
552 case 116: // D3DFMT_A32B32G32R32F
553 return DXGI_FORMAT_R32G32B32A32_FLOAT;
557 return DXGI_FORMAT_UNKNOWN;
561 //--------------------------------------------------------------------------------------
562 static void FillInitData(
566 _In_ size_t mipCount,
567 _In_ size_t arraySize,
568 _In_ DXGI_FORMAT format,
571 _In_reads_bytes_(bitSize) const byte* bitData,
572 _Out_ size_t& twidth,
573 _Out_ size_t& theight,
574 _Out_ size_t& tdepth,
575 _Out_ size_t& skipMip,
576 _Out_writes_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData
579 if (!bitData || !initData)
581 throw ref new Platform::InvalidArgumentException();
592 const byte* pSrcBits = bitData;
593 const byte* pEndBits = bitData + bitSize;
596 for (size_t j = 0; j < arraySize; j++)
601 for (size_t i = 0; i < mipCount; i++)
603 GetSurfaceInfo(w, h, format, &NumBytes, &RowBytes, &NumRows);
605 if ((mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize))
614 initData[index].pSysMem = (const void*)pSrcBits;
615 initData[index].SysMemPitch = static_cast<UINT>(RowBytes);
616 initData[index].SysMemSlicePitch = static_cast<UINT>(NumBytes);
624 if (pSrcBits + (NumBytes*d) > pEndBits)
626 throw ref new Platform::OutOfBoundsException();
629 pSrcBits += NumBytes * d;
651 throw ref new Platform::FailureException();
656 //--------------------------------------------------------------------------------------
657 static HRESULT CreateD3DResources(
658 _In_ ID3D11Device* d3dDevice,
663 _In_ size_t mipCount,
664 _In_ size_t arraySize,
665 _In_ DXGI_FORMAT format,
667 _In_reads_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData,
668 _Out_opt_ ID3D11Resource** texture,
669 _Out_opt_ ID3D11ShaderResourceView** textureView
672 if (!d3dDevice || !initData)
681 case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
683 D3D11_TEXTURE1D_DESC desc;
684 desc.Width = static_cast<UINT>(width);
685 desc.MipLevels = static_cast<UINT>(mipCount);
686 desc.ArraySize = static_cast<UINT>(arraySize);
687 desc.Format = format;
688 desc.Usage = D3D11_USAGE_DEFAULT;
689 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
690 desc.CPUAccessFlags = 0;
693 ID3D11Texture1D* tex = nullptr;
694 hr = d3dDevice->CreateTexture1D(&desc, initData, &tex);
696 if (SUCCEEDED(hr) && tex != 0)
698 if (textureView != 0)
700 D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
701 memset(&SRVDesc, 0, sizeof(SRVDesc));
702 SRVDesc.Format = format;
706 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY;
707 SRVDesc.Texture1DArray.MipLevels = desc.MipLevels;
708 SRVDesc.Texture1DArray.ArraySize = static_cast<UINT>(arraySize);
712 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D;
713 SRVDesc.Texture1D.MipLevels = desc.MipLevels;
716 hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
737 case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
739 D3D11_TEXTURE2D_DESC desc;
740 desc.Width = static_cast<UINT>(width);
741 desc.Height = static_cast<UINT>(height);
742 desc.MipLevels = static_cast<UINT>(mipCount);
743 desc.ArraySize = static_cast<UINT>(arraySize);
744 desc.Format = format;
745 desc.SampleDesc.Count = 1;
746 desc.SampleDesc.Quality = 0;
747 desc.Usage = D3D11_USAGE_DEFAULT;
748 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
749 desc.CPUAccessFlags = 0;
750 desc.MiscFlags = (isCubeMap) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
752 ID3D11Texture2D* tex = nullptr;
753 hr = d3dDevice->CreateTexture2D(&desc, initData, &tex);
755 if (SUCCEEDED(hr) && tex != 0)
757 if (textureView != 0)
759 D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
760 memset(&SRVDesc, 0, sizeof(SRVDesc));
761 SRVDesc.Format = format;
767 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY;
768 SRVDesc.TextureCubeArray.MipLevels = desc.MipLevels;
770 // Earlier we set arraySize to (NumCubes * 6)
771 SRVDesc.TextureCubeArray.NumCubes = static_cast<UINT>(arraySize / 6);
775 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE;
776 SRVDesc.TextureCube.MipLevels = desc.MipLevels;
779 else if (arraySize > 1)
781 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY;
782 SRVDesc.Texture2DArray.MipLevels = desc.MipLevels;
783 SRVDesc.Texture2DArray.ArraySize = static_cast<UINT>(arraySize);
787 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
788 SRVDesc.Texture2D.MipLevels = desc.MipLevels;
791 hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
812 case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
814 D3D11_TEXTURE3D_DESC desc;
815 desc.Width = static_cast<UINT>(width);
816 desc.Height = static_cast<UINT>(height);
817 desc.Depth = static_cast<UINT>(depth);
818 desc.MipLevels = static_cast<UINT>(mipCount);
819 desc.Format = format;
820 desc.Usage = D3D11_USAGE_DEFAULT;
821 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
822 desc.CPUAccessFlags = 0;
825 ID3D11Texture3D* tex = nullptr;
826 hr = d3dDevice->CreateTexture3D(&desc, initData, &tex);
828 if (SUCCEEDED(hr) && tex != 0)
830 if (textureView != 0)
832 D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
833 memset(&SRVDesc, 0, sizeof(SRVDesc));
834 SRVDesc.Format = format;
835 SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D;
836 SRVDesc.Texture3D.MipLevels = desc.MipLevels;
838 hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
864 //--------------------------------------------------------------------------------------
865 static void CreateTextureFromDDS(
866 _In_ ID3D11Device* d3dDevice,
867 _In_ const DDS_HEADER* header,
868 _In_reads_bytes_(bitSize) const byte* bitData,
870 _Out_opt_ ID3D11Resource** texture,
871 _Out_opt_ ID3D11ShaderResourceView** textureView,
877 size_t width = header->width;
878 size_t height = header->height;
879 size_t depth = header->depth;
881 uint32 resDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
882 size_t arraySize = 1;
883 DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
884 bool isCubeMap = false;
886 size_t mipCount = header->mipMapCount;
892 if ((header->ddspf.flags & DDS_FOURCC) &&
893 (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC))
895 const DDS_HEADER_DXT10* d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>((const char*)header + sizeof(DDS_HEADER));
897 arraySize = d3d10ext->arraySize;
900 throw ref new Platform::FailureException();
903 if (BitsPerPixel(d3d10ext->dxgiFormat) == 0)
905 throw ref new Platform::FailureException();
908 format = d3d10ext->dxgiFormat;
910 switch (d3d10ext->resourceDimension)
912 case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
913 // D3DX writes 1D textures with a fixed Height of 1
914 if ((header->flags & DDS_HEIGHT) && height != 1)
916 throw ref new Platform::FailureException();
921 case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
922 if (d3d10ext->miscFlag & D3D11_RESOURCE_MISC_TEXTURECUBE)
930 case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
931 if (!(header->flags & DDS_HEADER_FLAGS_VOLUME))
933 throw ref new Platform::FailureException();
938 throw ref new Platform::FailureException();
943 return throw ref new Platform::FailureException();
946 resDim = d3d10ext->resourceDimension;
950 format = GetDXGIFormat(header->ddspf);
952 if (format == DXGI_FORMAT_UNKNOWN)
954 return throw ref new Platform::FailureException();
957 if (header->flags & DDS_HEADER_FLAGS_VOLUME)
959 resDim = D3D11_RESOURCE_DIMENSION_TEXTURE3D;
963 if (header->caps2 & DDS_CUBEMAP)
965 // We require all six faces to be defined
966 if ((header->caps2 & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES)
968 return throw ref new Platform::FailureException();
976 resDim = D3D11_RESOURCE_DIMENSION_TEXTURE2D;
978 // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
981 assert(BitsPerPixel(format) != 0);
984 // Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements)
985 if (mipCount > D3D11_REQ_MIP_LEVELS)
987 return throw ref new Platform::FailureException();
992 case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
993 if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||
994 (width > D3D11_REQ_TEXTURE1D_U_DIMENSION))
996 return throw ref new Platform::FailureException();
1000 case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
1003 // This is the right bound because we set arraySize to (NumCubes*6) above
1004 if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
1005 (width > D3D11_REQ_TEXTURECUBE_DIMENSION) ||
1006 (height > D3D11_REQ_TEXTURECUBE_DIMENSION))
1008 return throw ref new Platform::FailureException();
1011 else if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
1012 (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) ||
1013 (height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION))
1015 return throw ref new Platform::FailureException();
1019 case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
1020 if ((arraySize > 1) ||
1021 (width > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
1022 (height > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
1023 (depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION))
1025 return throw ref new Platform::FailureException();
1030 // Create the texture
1031 std::unique_ptr<D3D11_SUBRESOURCE_DATA> initData(new D3D11_SUBRESOURCE_DATA[mipCount * arraySize]);
1037 FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, twidth, theight, tdepth, skipMip, initData.get());
1039 hr = CreateD3DResources(d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, isCubeMap, initData.get(), texture, textureView);
1041 if (FAILED(hr) && !maxsize && (mipCount > 1))
1043 // Retry with a maxsize determined by feature level
1044 switch (d3dDevice->GetFeatureLevel())
1046 case D3D_FEATURE_LEVEL_9_1:
1047 case D3D_FEATURE_LEVEL_9_2:
1050 maxsize = D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
1054 maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
1055 ? D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
1056 : D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1060 case D3D_FEATURE_LEVEL_9_3:
1061 maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
1062 ? D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
1063 : D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1066 default: // D3D_FEATURE_LEVEL_10_0 & D3D_FEATURE_LEVEL_10_1
1067 maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
1068 ? D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
1069 : D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1073 FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, twidth, theight, tdepth, skipMip, initData.get());
1075 hr = CreateD3DResources(d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, isCubeMap, initData.get(), texture, textureView);
1078 DX::ThrowIfFailed(hr);
1081 //--------------------------------------------------------------------------------------
1082 void CreateDDSTextureFromMemory(
1083 _In_ ID3D11Device* d3dDevice,
1084 _In_reads_bytes_(ddsDataSize) const byte* ddsData,
1085 _In_ size_t ddsDataSize,
1086 _Out_opt_ ID3D11Resource** texture,
1087 _Out_opt_ ID3D11ShaderResourceView** textureView,
1091 if (!d3dDevice || !ddsData || (!texture && !textureView))
1093 throw ref new Platform::InvalidArgumentException();
1096 // Validate DDS file in memory
1097 if (ddsDataSize < (sizeof(uint32) + sizeof(DDS_HEADER)))
1099 throw ref new Platform::FailureException();
1102 uint32 dwMagicNumber = *(const uint32*)(ddsData);
1103 if (dwMagicNumber != DDS_MAGIC)
1105 throw ref new Platform::FailureException();
1108 const DDS_HEADER* header = reinterpret_cast<const DDS_HEADER*>(ddsData + sizeof(uint32));
1110 // Verify header to validate DDS file
1111 if (header->size != sizeof(DDS_HEADER) ||
1112 header->ddspf.size != sizeof(DDS_PIXELFORMAT))
1114 throw ref new Platform::FailureException();
1117 // Check for DX10 extension
1118 bool bDXT10Header = false;
1119 if ((header->ddspf.flags & DDS_FOURCC) &&
1120 (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC))
1122 // Must be long enough for both headers and magic value
1123 if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32) + sizeof(DDS_HEADER_DXT10)))
1125 throw ref new Platform::FailureException();
1128 bDXT10Header = true;
1131 ptrdiff_t offset = sizeof(uint32)
1132 + sizeof(DDS_HEADER)
1133 + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0);
1135 CreateTextureFromDDS(d3dDevice, header, ddsData + offset, ddsDataSize - offset, texture, textureView, maxsize);