summaryrefslogtreecommitdiffstats
path: root/TextureLoader/src/DDSLoader.cpp
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2015-10-21 04:05:29 +0000
committerEgor Yusov <egor.yusov@gmail.com>2015-10-21 04:05:29 +0000
commitf2e065dee10fb110e9d51175ee6381333319ef56 (patch)
treeda85ca78fe050280d7592bf6bf1071410846031f /TextureLoader/src/DDSLoader.cpp
downloadDiligentTools-f2e065dee10fb110e9d51175ee6381333319ef56.tar.gz
DiligentTools-f2e065dee10fb110e9d51175ee6381333319ef56.zip
Release v1.0.0
Diffstat (limited to 'TextureLoader/src/DDSLoader.cpp')
-rw-r--r--TextureLoader/src/DDSLoader.cpp1489
1 files changed, 1489 insertions, 0 deletions
diff --git a/TextureLoader/src/DDSLoader.cpp b/TextureLoader/src/DDSLoader.cpp
new file mode 100644
index 0000000..2c701f3
--- /dev/null
+++ b/TextureLoader/src/DDSLoader.cpp
@@ -0,0 +1,1489 @@
+/* Copyright 2015 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+//--------------------------------------------------------------------------------------
+// File: DDSLoader.cpp
+//
+// Functions for loading a DDS texture and creating a Direct3D 11 runtime resource for it
+//
+// Note these functions are useful as a light-weight runtime loader for DDS files. For
+// a full-featured DDS file reader, writer, and texture processing pipeline see
+// the 'Texconv' sample and the 'DirectXTex' library.
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// http://go.microsoft.com/fwlink/?LinkId=248926
+// http://go.microsoft.com/fwlink/?LinkId=248929
+//--------------------------------------------------------------------------------------
+
+#include "pch.h"
+#include "dxgiformat.h"
+#include <memory>
+#include <algorithm>
+#include "DDSLoader.h"
+
+#ifndef _In_
+# define _In_
+#endif
+
+#ifndef _Out_
+# define _Out_
+#endif
+
+#ifndef _Out_opt_
+# define _Out_opt_
+#endif
+
+#ifndef _Outptr_opt_
+# define _Outptr_opt_
+#endif
+
+using namespace Diligent;
+using namespace Diligent;
+
+// D3D11 definitions
+
+enum D3D11_RESOURCE_DIMENSION
+{
+ D3D11_RESOURCE_DIMENSION_UNKNOWN = 0,
+ D3D11_RESOURCE_DIMENSION_BUFFER = 1,
+ D3D11_RESOURCE_DIMENSION_TEXTURE1D = 2,
+ D3D11_RESOURCE_DIMENSION_TEXTURE2D = 3,
+ D3D11_RESOURCE_DIMENSION_TEXTURE3D = 4
+};
+
+enum D3D11_RESOURCE_MISC_FLAG
+{
+ D3D11_RESOURCE_MISC_TEXTURECUBE = 0x4L,
+};
+
+#ifndef D3D11_REQ_MIP_LEVELS
+# define D3D11_REQ_MIP_LEVELS ( 15 )
+#endif
+
+#ifndef D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION
+# define D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION ( 2048 )
+#endif
+
+#ifndef D3D11_REQ_TEXTURE1D_U_DIMENSION
+# define D3D11_REQ_TEXTURE1D_U_DIMENSION ( 16384 )
+#endif
+
+#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
+# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION ( 2048 )
+#endif
+
+#ifndef D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION
+# define D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION ( 16384 )
+#endif
+
+#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
+# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION ( 2048 )
+#endif
+
+#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION
+# define D3D11_REQ_TEXTURECUBE_DIMENSION ( 16384 )
+#endif
+
+
+//--------------------------------------------------------------------------------------
+// Macros
+//--------------------------------------------------------------------------------------
+#ifndef MAKEFOURCC
+ #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((Uint32)(Uint8)(ch0) | ((Uint32)(Uint8)(ch1) << 8) | \
+ ((Uint32)(Uint8)(ch2) << 16) | ((Uint32)(Uint8)(ch3) << 24))
+#endif /* defined(MAKEFOURCC) */
+
+//--------------------------------------------------------------------------------------
+// DDS file structure definitions
+//
+// See DDS.h in the 'Texconv' sample and the 'DirectXTex' library
+//--------------------------------------------------------------------------------------
+#pragma pack(push, 1)
+
+#define DDS_MAGIC 0x20534444 // "DDS "
+
+struct DDS_PIXELFORMAT
+{
+ Uint32 size;
+ Uint32 flags;
+ Uint32 fourCC;
+ Uint32 RGBBitCount;
+ Uint32 RBitMask;
+ Uint32 GBitMask;
+ Uint32 BBitMask;
+ Uint32 ABitMask;
+};
+
+#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
+#define DDS_RGB 0x00000040 // DDPF_RGB
+#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
+#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
+#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS
+#define DDS_ALPHA 0x00000002 // DDPF_ALPHA
+#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8
+
+#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
+#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
+#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
+#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
+#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
+
+#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
+#define DDS_WIDTH 0x00000004 // DDSD_WIDTH
+
+#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
+#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
+#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
+
+#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
+#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
+#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
+#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
+#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
+#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
+
+#define DDS_CUBEMAP_ALLFACES (DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
+ DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
+ DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ)
+
+#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP
+
+#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
+
+enum DDS_MISC_FLAGS2
+{
+ DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L,
+};
+
+enum DDS_ALPHA_MODE
+{
+ DDS_ALPHA_MODE_UNKNOWN = 0,
+ DDS_ALPHA_MODE_STRAIGHT = 1,
+ DDS_ALPHA_MODE_PREMULTIPLIED = 2,
+ DDS_ALPHA_MODE_OPAQUE = 3,
+ DDS_ALPHA_MODE_CUSTOM = 4,
+};
+
+typedef struct
+{
+ Uint32 size;
+ Uint32 flags;
+ Uint32 height;
+ Uint32 width;
+ Uint32 pitchOrLinearSize;
+ Uint32 depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags
+ Uint32 mipMapCount;
+ Uint32 reserved1[11];
+ DDS_PIXELFORMAT ddspf;
+ Uint32 caps;
+ Uint32 caps2;
+ Uint32 caps3;
+ Uint32 caps4;
+ Uint32 reserved2;
+} DDS_HEADER;
+
+
+typedef struct
+{
+ DXGI_FORMAT dxgiFormat;
+ Uint32 resourceDimension;
+ Uint32 miscFlag; // see D3D11_RESOURCE_MISC_FLAG
+ Uint32 arraySize;
+ Uint32 miscFlags2;
+} DDS_HEADER_DXT10;
+
+#pragma pack(pop)
+
+
+
+//--------------------------------------------------------------------------------------
+// Return the BPP for a particular format
+//--------------------------------------------------------------------------------------
+static size_t BitsPerPixel(_In_ DXGI_FORMAT fmt)
+{
+ switch (fmt)
+ {
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return 128;
+
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return 96;
+
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return 64;
+
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R32_SINT:
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return 32;
+
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_SINT:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return 16;
+
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
+ return 8;
+
+ case DXGI_FORMAT_R1_UNORM:
+ return 1;
+
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ return 4;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return 8;
+
+ default:
+ return 0;
+ }
+}
+
+
+static TEXTURE_FORMAT DXGIFormatToTexFormat( DXGI_FORMAT TexFormat )
+{
+ switch(TexFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN: return TEX_FORMAT_UNKNOWN;
+
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS: return TEX_FORMAT_RGBA32_TYPELESS;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT: return TEX_FORMAT_RGBA32_FLOAT;
+ case DXGI_FORMAT_R32G32B32A32_UINT: return TEX_FORMAT_RGBA32_UINT;
+ case DXGI_FORMAT_R32G32B32A32_SINT: return TEX_FORMAT_RGBA32_SINT;
+
+ case DXGI_FORMAT_R32G32B32_TYPELESS: return TEX_FORMAT_RGB32_TYPELESS;
+ case DXGI_FORMAT_R32G32B32_FLOAT: return TEX_FORMAT_RGB32_FLOAT;
+ case DXGI_FORMAT_R32G32B32_UINT: return TEX_FORMAT_RGB32_UINT;
+ case DXGI_FORMAT_R32G32B32_SINT: return TEX_FORMAT_RGB32_SINT;
+
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS: return TEX_FORMAT_RGBA16_TYPELESS;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT: return TEX_FORMAT_RGBA16_FLOAT;
+ case DXGI_FORMAT_R16G16B16A16_UNORM: return TEX_FORMAT_RGBA16_UNORM;
+ case DXGI_FORMAT_R16G16B16A16_UINT: return TEX_FORMAT_RGBA16_UINT;
+ case DXGI_FORMAT_R16G16B16A16_SNORM: return TEX_FORMAT_RGBA16_SNORM;
+ case DXGI_FORMAT_R16G16B16A16_SINT: return TEX_FORMAT_RGBA16_SINT;
+
+ case DXGI_FORMAT_R32G32_TYPELESS: return TEX_FORMAT_RG32_TYPELESS;
+ case DXGI_FORMAT_R32G32_FLOAT: return TEX_FORMAT_RG32_FLOAT;
+ case DXGI_FORMAT_R32G32_UINT: return TEX_FORMAT_RG32_UINT;
+ case DXGI_FORMAT_R32G32_SINT: return TEX_FORMAT_RG32_SINT;
+
+ case DXGI_FORMAT_R32G8X24_TYPELESS: return TEX_FORMAT_R32G8X24_TYPELESS;
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return TEX_FORMAT_D32_FLOAT_S8X24_UINT;
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: return TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS;
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: return TEX_FORMAT_X32_TYPELESS_G8X24_UINT;
+
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS: return TEX_FORMAT_RGB10A2_TYPELESS;
+ case DXGI_FORMAT_R10G10B10A2_UNORM: return TEX_FORMAT_RGB10A2_UNORM;
+ case DXGI_FORMAT_R10G10B10A2_UINT: return TEX_FORMAT_RGB10A2_UINT;
+
+ case DXGI_FORMAT_R11G11B10_FLOAT: return TEX_FORMAT_R11G11B10_FLOAT;
+
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS: return TEX_FORMAT_RGBA8_TYPELESS;
+ case DXGI_FORMAT_R8G8B8A8_UNORM: return TEX_FORMAT_RGBA8_UNORM;
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return TEX_FORMAT_RGBA8_UNORM_SRGB;
+ case DXGI_FORMAT_R8G8B8A8_UINT: return TEX_FORMAT_RGBA8_UINT;
+ case DXGI_FORMAT_R8G8B8A8_SNORM: return TEX_FORMAT_RGBA8_SNORM;
+ case DXGI_FORMAT_R8G8B8A8_SINT: return TEX_FORMAT_RGBA8_SINT;
+
+ case DXGI_FORMAT_R16G16_TYPELESS: return TEX_FORMAT_RG16_TYPELESS;
+ case DXGI_FORMAT_R16G16_FLOAT: return TEX_FORMAT_RG16_FLOAT;
+ case DXGI_FORMAT_R16G16_UNORM: return TEX_FORMAT_RG16_UNORM;
+ case DXGI_FORMAT_R16G16_UINT: return TEX_FORMAT_RG16_UINT;
+ case DXGI_FORMAT_R16G16_SNORM: return TEX_FORMAT_RG16_SNORM;
+ case DXGI_FORMAT_R16G16_SINT: return TEX_FORMAT_RG16_SINT;
+
+ case DXGI_FORMAT_R32_TYPELESS: return TEX_FORMAT_R32_TYPELESS;
+ case DXGI_FORMAT_D32_FLOAT: return TEX_FORMAT_D32_FLOAT;
+ case DXGI_FORMAT_R32_FLOAT: return TEX_FORMAT_R32_FLOAT;
+ case DXGI_FORMAT_R32_UINT: return TEX_FORMAT_R32_UINT;
+ case DXGI_FORMAT_R32_SINT: return TEX_FORMAT_R32_SINT;
+
+ case DXGI_FORMAT_R24G8_TYPELESS: return TEX_FORMAT_R24G8_TYPELESS;
+ case DXGI_FORMAT_D24_UNORM_S8_UINT: return TEX_FORMAT_D24_UNORM_S8_UINT;
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: return TEX_FORMAT_R24_UNORM_X8_TYPELESS;
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT: return TEX_FORMAT_X24_TYPELESS_G8_UINT;
+
+ case DXGI_FORMAT_R8G8_TYPELESS: return TEX_FORMAT_RG8_TYPELESS;
+ case DXGI_FORMAT_R8G8_UNORM: return TEX_FORMAT_RG8_UNORM;
+ case DXGI_FORMAT_R8G8_UINT: return TEX_FORMAT_RG8_UINT;
+ case DXGI_FORMAT_R8G8_SNORM: return TEX_FORMAT_RG8_SNORM;
+ case DXGI_FORMAT_R8G8_SINT: return TEX_FORMAT_RG8_SINT;
+
+ case DXGI_FORMAT_R16_TYPELESS: return TEX_FORMAT_R16_TYPELESS;
+ case DXGI_FORMAT_R16_FLOAT: return TEX_FORMAT_R16_FLOAT;
+ case DXGI_FORMAT_D16_UNORM: return TEX_FORMAT_D16_UNORM;
+ case DXGI_FORMAT_R16_UNORM: return TEX_FORMAT_R16_UNORM;
+ case DXGI_FORMAT_R16_UINT: return TEX_FORMAT_R16_UINT;
+ case DXGI_FORMAT_R16_SNORM: return TEX_FORMAT_R16_SNORM;
+ case DXGI_FORMAT_R16_SINT: return TEX_FORMAT_R16_SINT;
+
+ case DXGI_FORMAT_R8_TYPELESS: return TEX_FORMAT_R8_TYPELESS;
+ case DXGI_FORMAT_R8_UNORM: return TEX_FORMAT_R8_UNORM;
+ case DXGI_FORMAT_R8_UINT: return TEX_FORMAT_R8_UINT;
+ case DXGI_FORMAT_R8_SNORM: return TEX_FORMAT_R8_SNORM;
+ case DXGI_FORMAT_R8_SINT: return TEX_FORMAT_R8_SINT;
+ case DXGI_FORMAT_A8_UNORM: return TEX_FORMAT_A8_UNORM;
+
+ case DXGI_FORMAT_R1_UNORM : return TEX_FORMAT_R1_UNORM;
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: return TEX_FORMAT_RGB9E5_SHAREDEXP;
+ case DXGI_FORMAT_R8G8_B8G8_UNORM: return TEX_FORMAT_RG8_B8G8_UNORM;
+ case DXGI_FORMAT_G8R8_G8B8_UNORM: return TEX_FORMAT_G8R8_G8B8_UNORM;
+
+ case DXGI_FORMAT_BC1_TYPELESS: return TEX_FORMAT_BC1_TYPELESS;
+ case DXGI_FORMAT_BC1_UNORM: return TEX_FORMAT_BC1_UNORM;
+ case DXGI_FORMAT_BC1_UNORM_SRGB: return TEX_FORMAT_BC1_UNORM_SRGB;
+ case DXGI_FORMAT_BC2_TYPELESS: return TEX_FORMAT_BC2_TYPELESS;
+ case DXGI_FORMAT_BC2_UNORM: return TEX_FORMAT_BC2_UNORM;
+ case DXGI_FORMAT_BC2_UNORM_SRGB: return TEX_FORMAT_BC2_UNORM_SRGB;
+ case DXGI_FORMAT_BC3_TYPELESS: return TEX_FORMAT_BC3_TYPELESS;
+ case DXGI_FORMAT_BC3_UNORM: return TEX_FORMAT_BC3_UNORM;
+ case DXGI_FORMAT_BC3_UNORM_SRGB: return TEX_FORMAT_BC3_UNORM_SRGB;
+ case DXGI_FORMAT_BC4_TYPELESS: return TEX_FORMAT_BC4_TYPELESS;
+ case DXGI_FORMAT_BC4_UNORM: return TEX_FORMAT_BC4_UNORM;
+ case DXGI_FORMAT_BC4_SNORM: return TEX_FORMAT_BC4_SNORM;
+ case DXGI_FORMAT_BC5_TYPELESS: return TEX_FORMAT_BC5_TYPELESS;
+ case DXGI_FORMAT_BC5_UNORM: return TEX_FORMAT_BC5_UNORM;
+ case DXGI_FORMAT_BC5_SNORM: return TEX_FORMAT_BC5_SNORM;
+
+ case DXGI_FORMAT_B5G6R5_UNORM: return TEX_FORMAT_B5G6R5_UNORM;
+ case DXGI_FORMAT_B5G5R5A1_UNORM: return TEX_FORMAT_B5G5R5A1_UNORM;
+ case DXGI_FORMAT_B8G8R8A8_UNORM: return TEX_FORMAT_BGRA8_UNORM;
+ case DXGI_FORMAT_B8G8R8X8_UNORM: return TEX_FORMAT_BGRX8_UNORM;
+
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: return TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM;
+
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS: return TEX_FORMAT_BGRA8_TYPELESS;
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return TEX_FORMAT_BGRA8_UNORM_SRGB;
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS: return TEX_FORMAT_BGRX8_TYPELESS;
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return TEX_FORMAT_BGRX8_UNORM_SRGB;
+
+ case DXGI_FORMAT_BC6H_TYPELESS: return TEX_FORMAT_BC6H_TYPELESS;
+ case DXGI_FORMAT_BC6H_UF16: return TEX_FORMAT_BC6H_UF16;
+ case DXGI_FORMAT_BC6H_SF16: return TEX_FORMAT_BC6H_SF16;
+ case DXGI_FORMAT_BC7_TYPELESS : return TEX_FORMAT_BC7_TYPELESS;
+ case DXGI_FORMAT_BC7_UNORM: return TEX_FORMAT_BC7_UNORM;
+ case DXGI_FORMAT_BC7_UNORM_SRGB: return TEX_FORMAT_BC7_UNORM_SRGB;
+
+ default: UNEXPECTED( "Unsupported DXGI formate" ); return TEX_FORMAT_UNKNOWN;
+ }
+}
+
+//--------------------------------------------------------------------------------------
+// Get surface information for a particular format
+//--------------------------------------------------------------------------------------
+static void GetSurfaceInfo(
+ _In_ size_t width,
+ _In_ size_t height,
+ _In_ DXGI_FORMAT fmt,
+ _Out_opt_ size_t* outNumBytes,
+ _Out_opt_ size_t* outRowBytes,
+ _Out_opt_ size_t* outNumRows
+ )
+{
+ size_t numBytes = 0;
+ size_t rowBytes = 0;
+ size_t numRows = 0;
+
+ bool bc = false;
+ bool packed = false;
+ size_t bcnumBytesPerBlock = 0;
+ switch (fmt)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ bc = true;
+ bcnumBytesPerBlock = 8;
+ break;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ bc = true;
+ bcnumBytesPerBlock = 16;
+ break;
+
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ packed = true;
+ break;
+ }
+
+ if (bc)
+ {
+ size_t numBlocksWide = 0;
+ if (width > 0)
+ {
+ numBlocksWide = std::max<size_t>(1, (width + 3) / 4);
+ }
+ size_t numBlocksHigh = 0;
+ if (height > 0)
+ {
+ numBlocksHigh = std::max<size_t>(1, (height + 3) / 4);
+ }
+ rowBytes = numBlocksWide * bcnumBytesPerBlock;
+ numRows = numBlocksHigh;
+ }
+ else if (packed)
+ {
+ rowBytes = ((width + 1) >> 1) * 4;
+ numRows = height;
+ }
+ else
+ {
+ size_t bpp = BitsPerPixel(fmt);
+ rowBytes = (width * bpp + 7) / 8; // round up to nearest byte
+ numRows = height;
+ }
+
+ numBytes = rowBytes * numRows;
+ if (outNumBytes)
+ {
+ *outNumBytes = numBytes;
+ }
+ if (outRowBytes)
+ {
+ *outRowBytes = rowBytes;
+ }
+ if (outNumRows)
+ {
+ *outNumRows = numRows;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+#define ISBITMASK(r, g, b, a) (ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a)
+
+static DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT& ddpf)
+{
+ if (ddpf.flags & DDS_RGB)
+ {
+ // Note that sRGB formats are written using the "DX10" extended header
+
+ switch (ddpf.RGBBitCount)
+ {
+ case 32:
+ if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000))
+ {
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ }
+
+ if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000))
+ {
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+ }
+
+ if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000))
+ {
+ return DXGI_FORMAT_B8G8R8X8_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000) aka D3DFMT_X8B8G8R8
+
+ // Note that many common DDS reader/writers (including D3DX) swap the
+ // the RED/BLUE masks for 10:10:10:2 formats. We assumme
+ // below that the 'backwards' header mask is being used since it is most
+ // likely written by D3DX. The more robust solution is to use the 'DX10'
+ // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly
+
+ // For 'correct' writers, this should be 0x000003ff, 0x000ffc00, 0x3ff00000 for RGB data
+ if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000))
+ {
+ return DXGI_FORMAT_R10G10B10A2_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000) aka D3DFMT_A2R10G10B10
+
+ if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))
+ {
+ return DXGI_FORMAT_R16G16_UNORM;
+ }
+
+ if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ // Only 32-bit color channel format in D3D9 was R32F
+ return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114
+ }
+ break;
+
+ case 24:
+ // No 24bpp DXGI formats aka D3DFMT_R8G8B8
+ break;
+
+ case 16:
+ if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000))
+ {
+ return DXGI_FORMAT_B5G5R5A1_UNORM;
+ }
+ if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000))
+ {
+ return DXGI_FORMAT_B5G6R5_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x0000) aka D3DFMT_X1R5G5B5
+ if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000))
+ {
+ return DXGI_FORMAT_B4G4R4A4_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x0f00, 0x00f0, 0x000f, 0x0000) aka D3DFMT_X4R4G4B4
+
+ // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
+ break;
+ }
+ }
+ else if (ddpf.flags & DDS_LUMINANCE)
+ {
+ if (8 == ddpf.RGBBitCount)
+ {
+ if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+
+ // No DXGI format maps to ISBITMASK(0x0f, 0x00, 0x00, 0xf0) aka D3DFMT_A4L4
+ }
+
+ if (16 == ddpf.RGBBitCount)
+ {
+ if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+ if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00))
+ {
+ return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+ }
+ }
+ else if (ddpf.flags & DDS_ALPHA)
+ {
+ if (8 == ddpf.RGBBitCount)
+ {
+ return DXGI_FORMAT_A8_UNORM;
+ }
+ }
+ else if (ddpf.flags & DDS_FOURCC)
+ {
+ if (MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC1_UNORM;
+ }
+ if (MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC2_UNORM;
+ }
+ if (MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC3_UNORM;
+ }
+
+ // While pre-mulitplied alpha isn't directly supported by the DXGI formats,
+ // they are basically the same as these BC formats so they can be mapped
+ if (MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC2_UNORM;
+ }
+ if (MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC3_UNORM;
+ }
+
+ if (MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_UNORM;
+ }
+ if (MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_UNORM;
+ }
+ if (MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_SNORM;
+ }
+
+ if (MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_UNORM;
+ }
+ if (MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_UNORM;
+ }
+ if (MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_SNORM;
+ }
+
+ // BC6H and BC7 are written using the "DX10" extended header
+
+ if (MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_R8G8_B8G8_UNORM;
+ }
+ if (MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_G8R8_G8B8_UNORM;
+ }
+
+ // Check for D3DFORMAT enums being set here
+ switch (ddpf.fourCC)
+ {
+ case 36: // D3DFMT_A16B16G16R16
+ return DXGI_FORMAT_R16G16B16A16_UNORM;
+
+ case 110: // D3DFMT_Q16W16V16U16
+ return DXGI_FORMAT_R16G16B16A16_SNORM;
+
+ case 111: // D3DFMT_R16F
+ return DXGI_FORMAT_R16_FLOAT;
+
+ case 112: // D3DFMT_G16R16F
+ return DXGI_FORMAT_R16G16_FLOAT;
+
+ case 113: // D3DFMT_A16B16G16R16F
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+
+ case 114: // D3DFMT_R32F
+ return DXGI_FORMAT_R32_FLOAT;
+
+ case 115: // D3DFMT_G32R32F
+ return DXGI_FORMAT_R32G32_FLOAT;
+
+ case 116: // D3DFMT_A32B32G32R32F
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ }
+ }
+
+ return DXGI_FORMAT_UNKNOWN;
+}
+
+
+//--------------------------------------------------------------------------------------
+static DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+
+ case DXGI_FORMAT_BC1_UNORM:
+ return DXGI_FORMAT_BC1_UNORM_SRGB;
+
+ case DXGI_FORMAT_BC2_UNORM:
+ return DXGI_FORMAT_BC2_UNORM_SRGB;
+
+ case DXGI_FORMAT_BC3_UNORM:
+ return DXGI_FORMAT_BC3_UNORM_SRGB;
+
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
+
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
+
+ case DXGI_FORMAT_BC7_UNORM:
+ return DXGI_FORMAT_BC7_UNORM_SRGB;
+
+ default:
+ return format;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+static void FillInitData(
+ _In_ size_t width,
+ _In_ size_t height,
+ _In_ size_t depth,
+ _In_ size_t mipCount,
+ _In_ size_t arraySize,
+ _In_ DXGI_FORMAT format,
+ _In_ size_t maxsize,
+ _In_ size_t bitSize,
+ _In_ const Uint8* bitData,
+ _Out_ size_t& twidth,
+ _Out_ size_t& theight,
+ _Out_ size_t& tdepth,
+ _Out_ size_t& skipMip,
+ _Out_ TextureSubResData *initData
+ )
+{
+ if (!bitData || !initData)
+ {
+ LOG_ERROR_AND_THROW( "Invalid arguments" );
+ }
+
+ skipMip = 0;
+ twidth = 0;
+ theight = 0;
+ tdepth = 0;
+
+ size_t NumBytes = 0;
+ size_t RowBytes = 0;
+ size_t NumRows = 0;
+ const Uint8* pSrcBits = bitData;
+ const Uint8* pEndBits = bitData + bitSize;
+
+ size_t index = 0;
+ for (size_t j = 0; j < arraySize; j++)
+ {
+ size_t w = width;
+ size_t h = height;
+ size_t d = depth;
+ for (size_t i = 0; i < mipCount; i++)
+ {
+ GetSurfaceInfo(w, h, format, &NumBytes, &RowBytes, &NumRows);
+
+ if ((mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize))
+ {
+ if (!twidth)
+ {
+ twidth = w;
+ theight = h;
+ tdepth = d;
+ }
+
+ VERIFY_EXPR(index < mipCount * arraySize);
+ initData[index].pData = (const void*)pSrcBits;
+ initData[index].Stride = static_cast<Uint32>(RowBytes);
+ initData[index].DepthStride = static_cast<Uint32>(NumBytes);
+ ++index;
+ }
+ else if (!j)
+ {
+ // Count number of skipped mipmaps (first item only)
+ ++skipMip;
+ }
+
+ if (pSrcBits + (NumBytes*d) > pEndBits)
+ {
+ LOG_ERROR_AND_THROW( "Out of bounds" );
+ }
+
+ pSrcBits += NumBytes * d;
+
+ w = w >> 1;
+ h = h >> 1;
+ d = d >> 1;
+ if (w == 0)
+ {
+ w = 1;
+ }
+ if (h == 0)
+ {
+ h = 1;
+ }
+ if (d == 0)
+ {
+ d = 1;
+ }
+ }
+ }
+
+ if (!index)
+ {
+ LOG_ERROR_AND_THROW( "Unknown error" );
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+static void CreateTexture(
+ _In_ IRenderDevice* pDevice,
+ _In_ Uint32 resDim,
+ _In_ size_t width,
+ _In_ size_t height,
+ _In_ size_t depth,
+ _In_ size_t mipCount,
+ _In_ size_t arraySize,
+ _In_ DXGI_FORMAT format,
+ _In_ USAGE usage,
+ _In_ unsigned int bindFlags,
+ _In_ unsigned int cpuAccessFlags,
+ _In_ unsigned int miscFlags,
+ _In_ bool forceSRGB,
+ _In_ bool isCubeMap,
+ _In_ TextureSubResData* initData,
+ _Outptr_opt_ ITexture** texture
+ )
+{
+ if (!pDevice || !initData)
+ {
+ LOG_ERROR_AND_THROW("Invalid arguments")
+ }
+
+
+ if (forceSRGB)
+ {
+ format = MakeSRGB(format);
+ }
+
+ TextureDesc desc;
+ desc.Width = static_cast<Uint32>(width);
+ desc.MipLevels = static_cast<Uint32>(mipCount);
+ desc.ArraySize = static_cast<Uint32>(arraySize);
+ desc.Format = DXGIFormatToTexFormat(format);
+ desc.Usage = usage;
+ desc.BindFlags = bindFlags;
+ desc.CPUAccessFlags = cpuAccessFlags;
+ //desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
+
+ TextureData InitData;
+ InitData.pSubResources = initData;
+ InitData.NumSubresources = static_cast<Uint32>(mipCount * arraySize);
+
+ switch (resDim)
+ {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ {
+ desc.Type = arraySize > 1 ? TEXTURE_TYPE_1D_ARRAY : TEXTURE_TYPE_1D;
+ pDevice->CreateTexture( desc, InitData, texture );
+
+ // ID3D11Texture1D* tex = nullptr;
+ // hr = d3dDevice->CreateTexture1D(&desc, initData, &tex);
+
+ // if (SUCCEEDED(hr) && tex != 0)
+ // {
+ // if (textureView != 0)
+ // {
+ // D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ // memset(&SRVDesc, 0, sizeof(SRVDesc));
+ // SRVDesc.Format = format;
+
+ // if (arraySize > 1)
+ // {
+ // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY;
+ // SRVDesc.Texture1DArray.MipLevels = desc.MipLevels;
+ // SRVDesc.Texture1DArray.ArraySize = static_cast<UINT>(arraySize);
+ // }
+ // else
+ // {
+ // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D;
+ // SRVDesc.Texture1D.MipLevels = desc.MipLevels;
+ // }
+
+ // hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
+
+ // if (FAILED(hr))
+ // {
+ // tex->Release();
+ // return hr;
+ // }
+ // }
+
+ // if (texture != 0)
+ // {
+ // *texture = tex;
+ // }
+ // else
+ // {
+ // tex->Release();
+ // }
+ // }
+ }
+ break;
+
+ case TEXTURE_TYPE_2D:
+ case TEXTURE_TYPE_2D_ARRAY:
+ case TEXTURE_TYPE_CUBE:
+ case TEXTURE_TYPE_CUBE_ARRAY:
+ {
+ desc.Type = isCubeMap ?
+ (arraySize > 1 ? TEXTURE_TYPE_CUBE_ARRAY : TEXTURE_TYPE_CUBE) :
+ (arraySize > 1 ? TEXTURE_TYPE_2D_ARRAY : TEXTURE_TYPE_2D);
+ desc.Height = static_cast<Uint32>(height);
+
+ //if (isCubeMap)
+ //{
+ // desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE;
+ //}
+ //else
+ //{
+ // desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
+ //}
+
+ pDevice->CreateTexture( desc, InitData, texture );
+
+ //ID3D11Texture2D* tex = nullptr;
+ //hr = d3dDevice->CreateTexture2D(&desc, initData, &tex);
+
+ //if (SUCCEEDED(hr) && tex != 0)
+ //{
+ // if (textureView != 0)
+ // {
+ // D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ // memset(&SRVDesc, 0, sizeof(SRVDesc));
+ // SRVDesc.Format = format;
+
+ // if (isCubeMap)
+ // {
+ // if (arraySize > 6)
+ // {
+ // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY;
+ // SRVDesc.TextureCubeArray.MipLevels = desc.MipLevels;
+
+ // // Earlier we set arraySize to (NumCubes * 6)
+ // SRVDesc.TextureCubeArray.NumCubes = static_cast<UINT>(arraySize / 6);
+ // }
+ // else
+ // {
+ // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE;
+ // SRVDesc.TextureCube.MipLevels = desc.MipLevels;
+ // }
+ // }
+ // else if (arraySize > 1)
+ // {
+ // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY;
+ // SRVDesc.Texture2DArray.MipLevels = desc.MipLevels;
+ // SRVDesc.Texture2DArray.ArraySize = static_cast<UINT>(arraySize);
+ // }
+ // else
+ // {
+ // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
+ // SRVDesc.Texture2D.MipLevels = desc.MipLevels;
+ // }
+
+ // hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
+
+ // if (FAILED(hr))
+ // {
+ // tex->Release();
+ // return hr;
+ // }
+ // }
+
+ // if (texture != 0)
+ // {
+ // *texture = tex;
+ // }
+ // else
+ // {
+ // tex->Release();
+ // }
+ //}
+ }
+ break;
+
+ case TEXTURE_TYPE_3D:
+ {
+ desc.Type = TEXTURE_TYPE_3D;
+ desc.Height = static_cast<Uint32>(height);
+ desc.Depth = static_cast<Uint32>(depth);
+
+ //desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
+
+ pDevice->CreateTexture( desc, InitData, texture );
+
+ //ID3D11Texture3D* tex = nullptr;
+ //hr = d3dDevice->CreateTexture3D(&desc, initData, &tex);
+
+ //if (SUCCEEDED(hr) && tex != 0)
+ //{
+ // if (textureView != 0)
+ // {
+ // D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ // memset(&SRVDesc, 0, sizeof(SRVDesc));
+ // SRVDesc.Format = format;
+ // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D;
+ // SRVDesc.Texture3D.MipLevels = desc.MipLevels;
+
+ // hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
+
+ // if (FAILED(hr))
+ // {
+ // tex->Release();
+ // return hr;
+ // }
+ // }
+
+ // if (texture != 0)
+ // {
+ // *texture = tex;
+ // }
+ // else
+ // {
+ // tex->Release();
+ // }
+ //}
+ }
+ break;
+ }
+}
+
+//--------------------------------------------------------------------------------------
+static void CreateTextureFromDDS(
+ _In_ IRenderDevice* pDevice,
+ _In_ const DDS_HEADER* header,
+ _In_ const Uint8* bitData,
+ _In_ size_t bitSize,
+ _In_ size_t maxsize,
+ _In_ USAGE usage,
+ _In_ unsigned int bindFlags,
+ _In_ unsigned int cpuAccessFlags,
+ _In_ unsigned int miscFlags,
+ _In_ bool forceSRGB,
+ _Outptr_opt_ ITexture** texture
+ )
+{
+ size_t width = header->width;
+ size_t height = header->height;
+ size_t depth = header->depth;
+
+ Uint32 resDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ size_t arraySize = 1;
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ bool isCubeMap = false;
+
+ size_t mipCount = header->mipMapCount;
+ if (0 == mipCount)
+ {
+ mipCount = 1;
+ }
+
+
+ if ((header->ddspf.flags & DDS_FOURCC) &&
+ (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC))
+ {
+ auto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>((const char*)header + sizeof(DDS_HEADER));
+
+ arraySize = d3d10ext->arraySize;
+ if (arraySize == 0)
+ {
+ LOG_ERROR_AND_THROW("Array size is zero");
+ }
+
+ if (BitsPerPixel(d3d10ext->dxgiFormat) == 0)
+ {
+ LOG_ERROR_AND_THROW("Undefined DXGI format");
+ }
+
+ format = d3d10ext->dxgiFormat;
+
+ switch (d3d10ext->resourceDimension)
+ {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ // D3DX writes 1D textures with a fixed Height of 1
+ if ((header->flags & DDS_HEIGHT) && height != 1)
+ {
+ LOG_ERROR_AND_THROW("Unexpected height (", height, ") for texture 1D");
+ }
+ height = depth = 1;
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ if (d3d10ext->miscFlag & D3D11_RESOURCE_MISC_TEXTURECUBE)
+ {
+ arraySize *= 6;
+ isCubeMap = true;
+ }
+ depth = 1;
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ if (!(header->flags & DDS_HEADER_FLAGS_VOLUME))
+ {
+ LOG_ERROR_AND_THROW("DDS_HEADER_FLAGS_VOLUME flag is not set");
+ }
+
+ if (arraySize > 1)
+ {
+ LOG_ERROR_AND_THROW("Texture3D arrays are not allowed");
+ }
+ break;
+
+ default:
+ LOG_ERROR_AND_THROW("Unknown resource dimension");
+ }
+
+ resDim = d3d10ext->resourceDimension;
+ }
+ else
+ {
+ format = GetDXGIFormat(header->ddspf);
+
+ if (format == DXGI_FORMAT_UNKNOWN)
+ {
+ LOG_ERROR_AND_THROW("Unknown DXGIF format");
+ }
+
+ if (header->flags & DDS_HEADER_FLAGS_VOLUME)
+ {
+ resDim = D3D11_RESOURCE_DIMENSION_TEXTURE3D;
+ }
+ else
+ {
+ if (header->caps2 & DDS_CUBEMAP)
+ {
+ // We require all six faces to be defined
+ if ((header->caps2 & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES)
+ {
+ LOG_ERROR_AND_THROW("All six faces of a cubemap must be defined");
+ }
+
+ arraySize = 6;
+ isCubeMap = true;
+ }
+
+ depth = 1;
+ resDim = D3D11_RESOURCE_DIMENSION_TEXTURE2D;
+
+ // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
+ }
+
+ VERIFY_EXPR(BitsPerPixel(format) != 0);
+ }
+
+ // Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements)
+ if (mipCount > D3D11_REQ_MIP_LEVELS)
+ {
+ LOG_ERROR_AND_THROW("Too many mip levels specified");
+ }
+
+ switch (resDim)
+ {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||
+ (width > D3D11_REQ_TEXTURE1D_U_DIMENSION))
+ {
+ LOG_ERROR_AND_THROW("Texture1D dimensions are out of bounds");
+ }
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ if (isCubeMap)
+ {
+ // This is the right bound because we set arraySize to (NumCubes*6) above
+ if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
+ (width > D3D11_REQ_TEXTURECUBE_DIMENSION) ||
+ (height > D3D11_REQ_TEXTURECUBE_DIMENSION))
+ {
+ LOG_ERROR_AND_THROW("TextureCube dimensions are out of bounds");
+ }
+ }
+ else if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
+ (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) ||
+ (height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION))
+ {
+ LOG_ERROR_AND_THROW("Texture2D dimensions are out of bounds");
+ }
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ if ((arraySize > 1) ||
+ (width > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
+ (height > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
+ (depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION))
+ {
+ LOG_ERROR_AND_THROW("Texture3D dimensions are out of bounds");
+ }
+ break;
+ }
+ // Create the texture
+ std::unique_ptr<TextureSubResData[]> initData(new TextureSubResData[mipCount * arraySize]);
+
+ size_t skipMip = 0;
+ size_t twidth = 0;
+ size_t theight = 0;
+ size_t tdepth = 0;
+ FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, twidth, theight, tdepth, skipMip, initData.get());
+
+ CreateTexture(pDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, isCubeMap, initData.get(), texture/*, textureView*/);
+
+#if 0
+ if (FAILED(hr) && !maxsize && (mipCount > 1))
+ {
+ // Retry with a maxsize determined by feature level
+ switch (d3dDevice->GetFeatureLevel())
+ {
+ case D3D_FEATURE_LEVEL_9_1:
+ case D3D_FEATURE_LEVEL_9_2:
+ if (isCubeMap)
+ {
+ maxsize = D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
+ }
+ else
+ {
+ maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+ ? D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
+ : D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ }
+ break;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+ ? D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
+ : D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ break;
+
+ default: // D3D_FEATURE_LEVEL_10_0 & D3D_FEATURE_LEVEL_10_1
+ maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+ ? D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
+ : D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ break;
+ }
+
+ FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, twidth, theight, tdepth, skipMip, initData.get());
+
+ hr = CreateTexture(d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, isCubeMap, initData.get(), texture, textureView);
+ }
+#endif
+}
+
+#if 0
+//--------------------------------------------------------------------------------------
+static D2D1_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header)
+{
+ if (header->ddspf.flags & DDS_FOURCC)
+ {
+ if (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC)
+ {
+ auto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>((const char*)header + sizeof(DDS_HEADER));
+ switch (d3d10ext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK)
+ {
+ case DDS_ALPHA_MODE_STRAIGHT:
+ return D2D1_ALPHA_MODE_STRAIGHT;
+
+ case DDS_ALPHA_MODE_PREMULTIPLIED:
+ return D2D1_ALPHA_MODE_PREMULTIPLIED;
+
+ case DDS_ALPHA_MODE_OPAQUE:
+ case DDS_ALPHA_MODE_CUSTOM:
+ // No D2D1_ALPHA_MODE equivalent, so return "Ignore" for now
+ return D2D1_ALPHA_MODE_IGNORE;
+ }
+ }
+ else if ((MAKEFOURCC('D', 'X', 'T', '2') == header->ddspf.fourCC)
+ || (MAKEFOURCC('D', 'X', 'T', '4') == header->ddspf.fourCC))
+ {
+ return D2D1_ALPHA_MODE_PREMULTIPLIED;
+ }
+ // DXT1, DXT3, and DXT5 legacy files could be straight alpha or something else, so return "Unknown" to leave it up to the app
+ }
+
+ return D2D1_ALPHA_MODE_UNKNOWN;
+}
+
+#endif
+
+//--------------------------------------------------------------------------------------
+void CreateDDSTextureFromMemory(
+ IRenderDevice* pDevice,
+ const Uint8* ddsData,
+ size_t ddsDataSize,
+ ITexture** texture,
+ size_t maxsize/*,
+ D2D1_ALPHA_MODE* alphaMode*/
+ )
+{
+ return CreateDDSTextureFromMemoryEx(pDevice, ddsData, ddsDataSize, maxsize, USAGE_DEFAULT, BIND_SHADER_RESOURCE, 0, 0, false, texture/*, alphaMode*/);
+}
+
+
+//--------------------------------------------------------------------------------------
+void CreateDDSTextureFromMemoryEx(
+ IRenderDevice* pDevice,
+ const Uint8* ddsData,
+ size_t ddsDataSize,
+ size_t maxsize,
+ USAGE usage,
+ unsigned int bindFlags,
+ unsigned int cpuAccessFlags,
+ unsigned int miscFlags,
+ bool forceSRGB,
+ ITexture** texture/*,
+ D2D1_ALPHA_MODE* alphaMode*/
+ )
+{
+ if (texture)
+ {
+ VERIFY( *texture == nullptr, "Overwriting reference to an existing object is unsafe")
+ *texture = nullptr;
+ }
+ //if (textureView)
+ //{
+ // *textureView = nullptr;
+ //}
+ //if (alphaMode)
+ //{
+ // *alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
+ //}
+
+ if (!pDevice || !ddsData || (!texture /*&& !textureView*/))
+ {
+ LOG_ERROR_AND_THROW("Invalid arguments");
+ }
+
+ // Validate DDS file in memory
+ if (ddsDataSize < (sizeof(Uint32) + sizeof(DDS_HEADER)))
+ {
+ LOG_ERROR_AND_THROW("Invalid dds file");
+ }
+
+ Uint32 dwMagicNumber = *(const Uint32*)(ddsData);
+ if (dwMagicNumber != DDS_MAGIC)
+ {
+ LOG_ERROR_AND_THROW("Invalid dds file");
+ }
+
+ auto header = reinterpret_cast<const DDS_HEADER*>(ddsData + sizeof(Uint32));
+
+ // Verify header to validate DDS file
+ if (header->size != sizeof(DDS_HEADER) ||
+ header->ddspf.size != sizeof(DDS_PIXELFORMAT))
+ {
+ LOG_ERROR_AND_THROW("Invalid dds file header");
+ }
+
+ // Check for DX10 extension
+ bool bDXT10Header = false;
+ if ((header->ddspf.flags & DDS_FOURCC) &&
+ (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC))
+ {
+ // Must be long enough for both headers and magic value
+ if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(Uint32) + sizeof(DDS_HEADER_DXT10)))
+ {
+ LOG_ERROR_AND_THROW("Invalid DX10 extension");
+ }
+
+ bDXT10Header = true;
+ }
+
+ ptrdiff_t offset = sizeof(Uint32) + sizeof(DDS_HEADER) + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0);
+
+ CreateTextureFromDDS(pDevice, header, ddsData + offset, ddsDataSize - offset, maxsize, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, texture/*, textureView*/);
+
+ //if (alphaMode)
+ // *alphaMode = GetAlphaMode(header);
+}