packages feed

d3d11binding 0.0.0.6 → 0.0.0.7

raw patch · 13 files changed

+2642/−4 lines, 13 filesnew-component:exe:D3D11Binding-Texture

Files

+ csource/DDSTextureLoader.c view
@@ -0,0 +1,1794 @@+//--------------------------------------------------------------------------------------
+// File: DDSTextureLoader.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 "../include/DDSTextureLoader.h"
+
+//--------------------------------------------------------------------------------------
+// Macros
+//--------------------------------------------------------------------------------------
+#ifndef MAKEFOURCC
+    #define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
+                ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) |       \
+                ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
+#endif /* defined(MAKEFOURCC) */
+
+//--------------------------------------------------------------------------------------
+// DDS file structure definitions
+//
+// See DDS.h in the 'Texconv' sample and the 'DirectXTex' library
+//--------------------------------------------------------------------------------------
+#pragma pack(push,1)
+
+const uint32_t DDS_MAGIC = 0x20534444; // "DDS "
+
+typedef struct
+{
+    uint32_t    size;
+    uint32_t    flags;
+    uint32_t    fourCC;
+    uint32_t    RGBBitCount;
+    uint32_t    RBitMask;
+    uint32_t    GBitMask;
+    uint32_t    BBitMask;
+    uint32_t    ABitMask;
+} DDS_PIXELFORMAT;
+
+#define DDS_FOURCC      0x00000004  // DDPF_FOURCC
+#define DDS_RGB         0x00000040  // DDPF_RGB
+#define DDS_LUMINANCE   0x00020000  // DDPF_LUMINANCE
+#define DDS_ALPHA       0x00000002  // DDPF_ALPHA
+#define DDS_BUMPDUDV    0x00080000  // DDPF_BUMPDUDV
+
+#define DDS_HEADER_FLAGS_VOLUME         0x00800000  // DDSD_DEPTH
+
+#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
+#define DDS_WIDTH  0x00000004 // DDSD_WIDTH
+
+#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
+
+enum DDS_MISC_FLAGS2
+{
+    DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L,
+};
+
+typedef struct
+{
+    uint32_t        size;
+    uint32_t        flags;
+    uint32_t        height;
+    uint32_t        width;
+    uint32_t        pitchOrLinearSize;
+    uint32_t        depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags
+    uint32_t        mipMapCount;
+    uint32_t        reserved1[11];
+    DDS_PIXELFORMAT ddspf;
+    uint32_t        caps;
+    uint32_t        caps2;
+    uint32_t        caps3;
+    uint32_t        caps4;
+    uint32_t        reserved2;
+} DDS_HEADER;
+
+typedef struct
+{
+    DXGI_FORMAT     dxgiFormat;
+    uint32_t        resourceDimension;
+    uint32_t        miscFlag; // see D3D11_RESOURCE_MISC_FLAG
+    uint32_t        arraySize;
+    uint32_t        miscFlags2;
+} DDS_HEADER_DXT10;
+
+#pragma pack(pop)
+
+//--------------------------------------------------------------------------------------
+
+void CloseHandleSafe(HANDLE h) { if (h) CloseHandle(h);}
+
+inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }
+
+//--------------------------------------------------------------------------------------
+static HRESULT LoadTextureDataFromFile( const wchar_t* fileName,
+                                        uint8_t** ddsData,
+                                        DDS_HEADER** header,
+                                        uint8_t** bitData,
+                                        size_t* bitSize
+                                      )
+{
+    if (!header || !bitData || !bitSize)
+    {
+        return E_POINTER;
+    }
+
+    // open the file
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
+    HANDLE hFile = safe_handle( CreateFile2( fileName,
+                                                  GENERIC_READ,
+                                                  FILE_SHARE_READ,
+                                                  OPEN_EXISTING,
+                                                  NULL ) ) ;
+#else
+    HANDLE hFile = safe_handle( CreateFileW( fileName,
+                                                  GENERIC_READ,
+                                                  FILE_SHARE_READ,
+                                                  NULL,
+                                                  OPEN_EXISTING,
+                                                  FILE_ATTRIBUTE_NORMAL,
+                                                  NULL ) );
+#endif
+
+    if ( !hFile )
+    {
+        CloseHandleSafe(hFile);
+        return HRESULT_FROM_WIN32( GetLastError() );
+    }
+
+    // Get the file size
+    LARGE_INTEGER FileSize = { 0 };
+
+#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+    FILE_STANDARD_INFO fileInfo;
+    if ( !GetFileInformationByHandleEx( hFile, FileStandardInfo, &fileInfo, sizeof(fileInfo) ) )
+    {
+        CloseHandleSafe(hFile);
+        return HRESULT_FROM_WIN32( GetLastError() );
+    }
+    FileSize = fileInfo.EndOfFile;
+#else
+    GetFileSizeEx( hFile, &FileSize );
+#endif
+
+    // File is too big for 32-bit allocation, so reject read
+    if (FileSize.HighPart > 0)
+    {
+        CloseHandleSafe(hFile);
+        return E_FAIL;
+    }
+
+    // Need at least enough data to fill the header and magic number to be a valid DDS
+    if (FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) ) )
+    {
+        CloseHandleSafe(hFile);
+        return E_FAIL;
+    }
+
+    // create enough space for the file data
+    *ddsData = malloc(sizeof(uint8_t) * FileSize.LowPart);
+    if (!*ddsData)
+    {
+        CloseHandleSafe(hFile);
+        return E_OUTOFMEMORY;
+    }
+
+    // read the data in
+    DWORD BytesRead = 0;
+    if (!ReadFile( hFile,
+                   *ddsData,
+                   FileSize.LowPart,
+                   &BytesRead,
+                   NULL
+                 ))
+    {
+        CloseHandleSafe(hFile);
+        return HRESULT_FROM_WIN32( GetLastError() );
+    }
+
+    if (BytesRead < FileSize.LowPart)
+    {
+        CloseHandleSafe(hFile);
+        return E_FAIL;
+    }
+
+    // DDS files always start with the same magic number ("DDS ")
+    uint32_t dwMagicNumber = *( const uint32_t* )( *ddsData );
+    if (dwMagicNumber != DDS_MAGIC)
+    {
+        CloseHandleSafe(hFile);
+        return E_FAIL;
+    }
+
+    DDS_HEADER* hdr = (DDS_HEADER*)( *ddsData + sizeof( uint32_t ) );
+
+    // Verify header to validate DDS file
+    if (hdr->size != sizeof(DDS_HEADER) ||
+        hdr->ddspf.size != sizeof(DDS_PIXELFORMAT))
+    {
+        CloseHandleSafe(hFile);
+        return E_FAIL;
+    }
+
+    // Check for DX10 extension
+    BOOL bDXT10Header = FALSE;
+    if ((hdr->ddspf.flags & DDS_FOURCC) &&
+        (MAKEFOURCC( 'D', 'X', '1', '0' ) == hdr->ddspf.fourCC))
+    {
+        // Must be long enough for both headers and magic value
+        if (FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10) ) )
+        {
+            CloseHandleSafe(hFile);
+            return E_FAIL;
+        }
+
+        bDXT10Header = TRUE;
+    }
+
+    // setup the pointers in the process request
+    *header = hdr;
+    ptrdiff_t offset = sizeof( uint32_t ) + sizeof( DDS_HEADER )
+                       + (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0);
+    *bitData = *ddsData + offset;
+    *bitSize = FileSize.LowPart - offset;
+    
+    CloseHandleSafe(hFile);
+    return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+// 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:
+    case DXGI_FORMAT_Y416:
+    case DXGI_FORMAT_Y210:
+    case DXGI_FORMAT_Y216:
+        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:
+    case DXGI_FORMAT_AYUV:
+    case DXGI_FORMAT_Y410:
+    case DXGI_FORMAT_YUY2:
+        return 32;
+
+    case DXGI_FORMAT_P010:
+    case DXGI_FORMAT_P016:
+        return 24;
+
+    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_A8P8:
+    case DXGI_FORMAT_B4G4R4A4_UNORM:
+        return 16;
+
+    case DXGI_FORMAT_NV12:
+    case DXGI_FORMAT_420_OPAQUE:
+    case DXGI_FORMAT_NV11:
+        return 12;
+
+    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:
+    case DXGI_FORMAT_AI44:
+    case DXGI_FORMAT_IA44:
+    case DXGI_FORMAT_P8:
+        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;
+    }
+}
+
+//--------------------------------------------------------------------------------------
+// Get surface information for a particular format
+//--------------------------------------------------------------------------------------
+static void GetSurfaceInfo( size_t width,
+                            size_t height,
+                            DXGI_FORMAT fmt,
+                            size_t* outNumBytes,
+                            size_t* outRowBytes,
+                            size_t* outNumRows )
+{
+    size_t numBytes = 0;
+    size_t rowBytes = 0;
+    size_t numRows = 0;
+
+    BOOL bc = FALSE;
+    BOOL packed = FALSE;
+    BOOL planar = FALSE;
+    size_t bpe = 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;
+        bpe = 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;
+        bpe = 16;
+        break;
+
+    case DXGI_FORMAT_R8G8_B8G8_UNORM:
+    case DXGI_FORMAT_G8R8_G8B8_UNORM:
+    case DXGI_FORMAT_YUY2:
+        packed = TRUE;
+        bpe = 4;
+        break;
+
+    case DXGI_FORMAT_Y210:
+    case DXGI_FORMAT_Y216:
+        packed = TRUE;
+        bpe = 8;
+        break;
+
+    case DXGI_FORMAT_NV12:
+    case DXGI_FORMAT_420_OPAQUE:
+        planar = TRUE;
+        bpe = 2;
+        break;
+
+    case DXGI_FORMAT_P010:
+    case DXGI_FORMAT_P016:
+        planar = TRUE;
+        bpe = 4;
+        break;
+    }
+
+    if (bc)
+    {
+        size_t numBlocksWide = 0;
+        if (width > 0)
+        {
+            numBlocksWide = max( 1, (width + 3) / 4 );
+        }
+        size_t numBlocksHigh = 0;
+        if (height > 0)
+        {
+            numBlocksHigh = max( 1, (height + 3) / 4 );
+        }
+        rowBytes = numBlocksWide * bpe;
+        numRows = numBlocksHigh;
+        numBytes = rowBytes * numBlocksHigh;
+    }
+    else if (packed)
+    {
+        rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
+        numRows = height;
+        numBytes = rowBytes * height;
+    }
+    else if ( fmt == DXGI_FORMAT_NV11 )
+    {
+        rowBytes = ( ( width + 3 ) >> 2 ) * 4;
+        numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
+        numBytes = rowBytes * numRows;
+    }
+    else if (planar)
+    {
+        rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
+        numBytes = ( rowBytes * height ) + ( ( rowBytes * height + 1 ) >> 1 );
+        numRows = height + ( ( height + 1 ) >> 1 );
+    }
+    else
+    {
+        size_t bpp = BitsPerPixel( fmt );
+        rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte
+        numRows = height;
+        numBytes = rowBytes * height;
+    }
+
+    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 assume
+            // 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_BUMPDUDV)
+    {
+        if (16 == ddpf->RGBBitCount)
+        {
+            if (ISBITMASK(0x00ff, 0xff00, 0x0000, 0x0000))
+            {
+                return DXGI_FORMAT_R8G8_SNORM; // D3DX10/11 writes this out as DX10 extension
+            }
+        }
+
+        if (32 == ddpf->RGBBitCount)
+        {
+            if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000))
+            {
+                return DXGI_FORMAT_R8G8B8A8_SNORM; // D3DX10/11 writes this out as DX10 extension
+            }
+            if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))
+            {
+                return DXGI_FORMAT_R16G16_SNORM; // D3DX10/11 writes this out as DX10 extension
+            }
+
+            // No DXGI format maps to ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000) aka D3DFMT_A2W10V10U10
+        }
+    }
+    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-multiplied 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;
+        }
+
+        if (MAKEFOURCC('Y','U','Y','2') == ddpf->fourCC)
+        {
+            return DXGI_FORMAT_YUY2;
+        }
+
+        // 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 HRESULT FillInitData( size_t width,
+                             size_t height,
+                             size_t depth,
+                             size_t mipCount,
+                             size_t arraySize,
+                             DXGI_FORMAT format,
+                             size_t maxsize,
+                             size_t bitSize,
+                             const uint8_t* bitData,
+                             size_t* twidth,
+                             size_t* theight,
+                             size_t* tdepth,
+                             size_t* skipMip,
+                             D3D11_SUBRESOURCE_DATA* initData )
+{
+    if ( !bitData || !initData )
+    {
+        return E_POINTER;
+    }
+
+    *skipMip = 0;
+    *twidth = 0;
+    *theight = 0;
+    *tdepth = 0;
+
+    size_t NumBytes = 0;
+    size_t RowBytes = 0;
+    const uint8_t* pSrcBits = bitData;
+    const uint8_t* 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,
+                            NULL
+                          );
+
+            if ( (mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize) )
+            {
+                if ( !(*twidth) )
+                {
+                    *twidth = w;
+                    *theight = h;
+                    *tdepth = d;
+                }
+
+                initData[index].pSysMem = ( const void* )pSrcBits;
+                initData[index].SysMemPitch = (UINT)RowBytes;
+                initData[index].SysMemSlicePitch = (UINT)NumBytes;
+                ++index;
+            }
+            else if ( !j )
+            {
+                // Count number of skipped mipmaps (first item only)
+                ++(*skipMip);
+            }
+
+            if (pSrcBits + (NumBytes*d) > pEndBits)
+            {
+                return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
+            }
+  
+            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;
+            }
+        }
+    }
+
+    return (index > 0) ? S_OK : E_FAIL;
+}
+
+
+//--------------------------------------------------------------------------------------
+static HRESULT CreateD3DResources( ID3D11Device* d3dDevice,
+                                   uint32_t resDim,
+                                   size_t width,
+                                   size_t height,
+                                   size_t depth,
+                                   size_t mipCount,
+                                   size_t arraySize,
+                                   DXGI_FORMAT format,
+                                   D3D11_USAGE usage,
+                                   unsigned int bindFlags,
+                                   unsigned int cpuAccessFlags,
+                                   unsigned int miscFlags,
+                                   BOOL forceSRGB,
+                                   BOOL isCubeMap,
+                                   D3D11_SUBRESOURCE_DATA* initData,
+                                   ID3D11Resource** texture,
+                                   ID3D11ShaderResourceView** textureView )
+{
+    if ( !d3dDevice )
+        return E_POINTER;
+
+    HRESULT hr = E_FAIL;
+
+    if ( forceSRGB )
+    {
+        format = MakeSRGB( format );
+    }
+
+    switch ( resDim ) 
+    {
+        case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+            {
+                D3D11_TEXTURE1D_DESC desc;
+                desc.Width = (UINT)width; 
+                desc.MipLevels = (UINT)mipCount;
+                desc.ArraySize = (UINT)arraySize;
+                desc.Format = format;
+                desc.Usage = usage;
+                desc.BindFlags = bindFlags;
+                desc.CPUAccessFlags = cpuAccessFlags;
+                desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
+
+                ID3D11Texture1D* tex = NULL;
+                hr = d3dDevice->lpVtbl->CreateTexture1D( d3dDevice, &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 = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
+                            SRVDesc.Texture1DArray.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
+                            SRVDesc.Texture1DArray.ArraySize = (UINT) arraySize;
+                        }
+                        else
+                        {
+                            SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+                            SRVDesc.Texture1D.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
+                        }
+
+                        hr = d3dDevice->lpVtbl->CreateShaderResourceView(d3dDevice, (ID3D11Resource*)tex,
+                                                                  &SRVDesc,
+                                                                  textureView
+                                                                );
+                        if ( FAILED(hr) )
+                        {
+                            tex->lpVtbl->Release(tex);
+                            return hr;
+                        }
+                    }
+
+                    if (texture != 0)
+                    {
+                        *texture = (ID3D11Resource*)tex;
+                    }
+                    else
+                    {
+                        tex->lpVtbl->Release(tex);
+                    }
+                }
+            }
+           break;
+
+        case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+            {
+                D3D11_TEXTURE2D_DESC desc;
+                desc.Width = (UINT)width;
+                desc.Height = (UINT)height;
+                desc.MipLevels = (UINT)mipCount;
+                desc.ArraySize = (UINT)arraySize;
+                desc.Format = format;
+                desc.SampleDesc.Count = 1;
+                desc.SampleDesc.Quality = 0;
+                desc.Usage = usage;
+                desc.BindFlags = bindFlags;
+                desc.CPUAccessFlags = cpuAccessFlags;
+                if ( isCubeMap )
+                {
+                    desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE;
+                }
+                else
+                {
+                    desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
+                }
+
+                ID3D11Texture2D* tex = NULL;
+                hr = d3dDevice->lpVtbl->CreateTexture2D( d3dDevice, &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 = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
+                                SRVDesc.TextureCubeArray.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
+
+                                // Earlier we set arraySize to (NumCubes * 6)
+                                SRVDesc.TextureCubeArray.NumCubes = (UINT)( arraySize / 6 );
+                            }
+                            else
+                            {
+                                SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+                                SRVDesc.TextureCube.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
+                            }
+                        }
+                        else if (arraySize > 1)
+                        {
+                            SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+                            SRVDesc.Texture2DArray.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
+                            SRVDesc.Texture2DArray.ArraySize = (UINT)arraySize;
+                        }
+                        else
+                        {
+                            SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+                            SRVDesc.Texture2D.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
+                        }
+
+                        hr = d3dDevice->lpVtbl->CreateShaderResourceView(d3dDevice, (ID3D11Resource*)tex,
+                                                                  &SRVDesc,
+                                                                  textureView
+                                                                );
+                        if ( FAILED(hr) )
+                        {
+                            tex->lpVtbl->Release(tex);
+                            return hr;
+                        }
+                    }
+
+                    if (texture != 0)
+                    {
+                        *texture = (ID3D11Resource*)tex;
+                    }
+                    else
+                    {
+                        tex->lpVtbl->Release(tex);
+                    }
+                }
+            }
+            break;
+
+        case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+            {
+                D3D11_TEXTURE3D_DESC desc;
+                desc.Width = (UINT)width;
+                desc.Height = (UINT)height ;
+                desc.Depth = (UINT)depth;
+                desc.MipLevels = (UINT)mipCount;
+                desc.Format = format;
+                desc.Usage = usage;
+                desc.BindFlags = bindFlags;
+                desc.CPUAccessFlags = cpuAccessFlags;
+                desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
+
+                ID3D11Texture3D* tex = NULL;
+                hr = d3dDevice->lpVtbl->CreateTexture3D(d3dDevice, &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 = D3D11_SRV_DIMENSION_TEXTURE3D;
+                        SRVDesc.Texture3D.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
+
+                        hr = d3dDevice->lpVtbl->CreateShaderResourceView(d3dDevice, (ID3D11Resource*)tex,
+                                                                  &SRVDesc,
+                                                                  textureView
+                                                                );
+                        if ( FAILED(hr) )
+                        {
+                            tex->lpVtbl->Release(tex);
+                            return hr;
+                        }
+                    }
+
+                    if (texture != 0)
+                    {
+                        *texture = (ID3D11Resource*)tex;
+                    }
+                    else
+                    {
+                        tex->lpVtbl->Release(tex);
+                    }
+                }
+            }
+            break; 
+    }
+
+    return hr;
+}
+
+
+//--------------------------------------------------------------------------------------
+static HRESULT CreateTextureFromDDS( ID3D11Device* d3dDevice,
+                                     ID3D11DeviceContext* d3dContext,
+                                     const DDS_HEADER* header,
+                                     const uint8_t* bitData,
+                                     size_t bitSize,
+                                     size_t maxsize,
+                                     D3D11_USAGE usage,
+                                     unsigned int bindFlags,
+                                     unsigned int cpuAccessFlags,
+                                     unsigned int miscFlags,
+                                     BOOL forceSRGB,
+                                     ID3D11Resource** texture,
+                                     ID3D11ShaderResourceView** textureView )
+{
+    HRESULT hr = S_OK;
+
+    UINT width = header->width;
+    UINT height = header->height;
+    UINT depth = header->depth;
+
+    uint32_t resDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+    UINT 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 ))
+    {
+        const DDS_HEADER_DXT10* d3d10ext = (const DDS_HEADER_DXT10*)( (const char*)header + sizeof(DDS_HEADER) );
+
+        arraySize = d3d10ext->arraySize;
+        if (arraySize == 0)
+        {
+           return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
+        }
+
+        switch( d3d10ext->dxgiFormat )
+        {
+        case DXGI_FORMAT_AI44:
+        case DXGI_FORMAT_IA44:
+        case DXGI_FORMAT_P8:
+        case DXGI_FORMAT_A8P8:
+            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+        default:
+            if ( BitsPerPixel( d3d10ext->dxgiFormat ) == 0 )
+            {
+                return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+            }
+        }
+           
+        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)
+            {
+                return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
+            }
+            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))
+            {
+                return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
+            }
+
+            if (arraySize > 1)
+            {
+                return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+            }
+            break;
+
+        default:
+            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+        }
+
+        resDim = d3d10ext->resourceDimension;
+    }
+    else
+    {
+        format = GetDXGIFormat( &(header->ddspf) );
+
+        if (format == DXGI_FORMAT_UNKNOWN)
+        {
+           return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+        }
+
+        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)
+                {
+                    return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+                }
+
+                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
+        }
+    }
+
+    // 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)
+    {
+        return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+    }
+
+    switch ( resDim )
+    {
+    case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+        if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||
+            (width > D3D11_REQ_TEXTURE1D_U_DIMENSION) )
+        {
+            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+        }
+        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))
+            {
+                return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+            }
+        }
+        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))
+        {
+            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+        }
+        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) )
+        {
+            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+        }
+        break;
+
+    default:
+        return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+    }
+
+    BOOL autogen = FALSE;
+    if ( mipCount == 1 && d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps
+    {
+        // See if format is supported for auto-gen mipmaps (varies by feature level)
+        UINT fmtSupport = 0;
+        hr = d3dDevice->lpVtbl->CheckFormatSupport(d3dDevice, format, &fmtSupport );
+        if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) )
+        {
+            // 10level9 feature levels do not support auto-gen mipgen for volume textures
+            if ( ( resDim != D3D11_RESOURCE_DIMENSION_TEXTURE3D )
+                 || ( d3dDevice->lpVtbl->GetFeatureLevel(d3dDevice) >= D3D_FEATURE_LEVEL_10_0 ) )
+            {
+                autogen = TRUE;
+            }
+        }
+    }
+
+    if ( autogen )
+    {
+        // Create texture with auto-generated mipmaps
+        ID3D11Resource* tex = NULL;
+        hr = CreateD3DResources( d3dDevice, resDim, width, height, depth, 0, arraySize,
+                                 format, usage,
+                                 bindFlags | D3D11_BIND_RENDER_TARGET,
+                                 cpuAccessFlags,
+                                 miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS, forceSRGB,
+                                 isCubeMap, NULL, &tex, textureView );
+        if ( SUCCEEDED(hr) )
+        {
+            size_t numBytes = 0;
+            size_t rowBytes = 0;
+            GetSurfaceInfo( width, height, format, &numBytes, &rowBytes, NULL );
+
+            if ( numBytes > bitSize )
+            {
+                (*textureView)->lpVtbl->Release(*textureView);
+                *textureView = NULL;
+                tex->lpVtbl->Release(tex);
+                return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
+            }
+
+            D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+            (*textureView)->lpVtbl->GetDesc(*textureView, &desc );
+
+            UINT mipLevels = 1;
+
+            switch( desc.ViewDimension )
+            {
+            case D3D_SRV_DIMENSION_TEXTURE1D:       mipLevels = desc.Texture1D.MipLevels; break;
+            case D3D_SRV_DIMENSION_TEXTURE1DARRAY:  mipLevels = desc.Texture1DArray.MipLevels; break;
+            case D3D_SRV_DIMENSION_TEXTURE2D:       mipLevels = desc.Texture2D.MipLevels; break;
+            case D3D_SRV_DIMENSION_TEXTURE2DARRAY:  mipLevels = desc.Texture2DArray.MipLevels; break;
+            case D3D_SRV_DIMENSION_TEXTURECUBE:     mipLevels = desc.TextureCube.MipLevels; break;
+            case D3D_SRV_DIMENSION_TEXTURECUBEARRAY:mipLevels = desc.TextureCubeArray.MipLevels; break;
+            case D3D_SRV_DIMENSION_TEXTURE3D:       mipLevels = desc.Texture3D.MipLevels; break;
+            default:
+                (*textureView)->lpVtbl->Release(*textureView);
+                *textureView = NULL;
+                tex->lpVtbl->Release(tex);
+                return E_UNEXPECTED;
+            }
+
+            if ( arraySize > 1 )
+            {
+                const uint8_t* pSrcBits = bitData;
+                const uint8_t* pEndBits = bitData + bitSize;
+                for( UINT item = 0; item < arraySize; ++item )
+                {
+                    if ( (pSrcBits + numBytes) > pEndBits )
+                    {
+                        (*textureView)->lpVtbl->Release(*textureView);
+                        *textureView = NULL;
+                        tex->lpVtbl->Release(tex);
+                        return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
+                    }
+
+                    UINT res = item * mipLevels;
+                    d3dContext->lpVtbl->UpdateSubresource(d3dContext, tex, res, NULL, pSrcBits, (UINT)rowBytes, (UINT)numBytes );
+                    pSrcBits += numBytes;
+                }
+            }
+            else
+            {
+                d3dContext->lpVtbl->UpdateSubresource(d3dContext, tex, 0, NULL, bitData, (UINT)rowBytes, (UINT)numBytes );
+            }
+
+            d3dContext->lpVtbl->GenerateMips(d3dContext, *textureView );
+
+            if ( texture )
+            {
+                *texture = (ID3D11Resource*)tex;
+            }
+            else
+            {
+                tex->lpVtbl->Release(tex);
+            }
+        }
+    }
+    else
+    {
+        // Create the texture
+        D3D11_SUBRESOURCE_DATA* initData = malloc(sizeof(D3D11_SUBRESOURCE_DATA) * mipCount * arraySize);
+        if ( !initData )
+        {
+            return E_OUTOFMEMORY;
+        }
+
+        size_t skipMip = 0;
+        size_t twidth = 0;
+        size_t theight = 0;
+        size_t tdepth = 0;
+        hr = FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
+                           &twidth, &theight, &tdepth, &skipMip, initData);
+
+        if ( SUCCEEDED(hr) )
+        {
+            hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,
+                                     format, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
+                                     isCubeMap, initData, texture, textureView );
+
+            if ( FAILED(hr) && !maxsize && (mipCount > 1) )
+            {
+                // Retry with a maxsize determined by feature level
+                switch( d3dDevice->lpVtbl->GetFeatureLevel(d3dDevice) )
+                {
+                case D3D_FEATURE_LEVEL_9_1:
+                case D3D_FEATURE_LEVEL_9_2:
+                    if ( isCubeMap )
+                    {
+                        maxsize = 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/;
+                    }
+                    else
+                    {
+                        maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+                                  ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
+                                  : 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
+                    }
+                    break;
+
+                case D3D_FEATURE_LEVEL_9_3:
+                    maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+                              ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
+                              : 4096 /*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)
+                              ? 2048 /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
+                              : 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
+                    break;
+                }
+
+                hr = FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
+                                   &twidth, &theight, &tdepth, &skipMip, initData );
+                if ( SUCCEEDED(hr) )
+                {
+                    hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,
+                                             format, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
+                                             isCubeMap, initData, texture, textureView );
+                }
+            }
+        }
+        
+        free(initData);
+    }
+
+    return hr;
+}
+
+
+//--------------------------------------------------------------------------------------
+static DDS_ALPHA_MODE GetAlphaMode( const DDS_HEADER* header )
+{
+    if ( header->ddspf.flags & DDS_FOURCC )
+    {
+        if ( MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC )
+        {
+            const DDS_HEADER_DXT10* d3d10ext = (const DDS_HEADER_DXT10*)( (const char*)header + sizeof(DDS_HEADER) );
+            DDS_ALPHA_MODE mode = (DDS_ALPHA_MODE)( d3d10ext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK );
+            switch( mode )
+            {
+            case DDS_ALPHA_MODE_STRAIGHT:
+            case DDS_ALPHA_MODE_PREMULTIPLIED:
+            case DDS_ALPHA_MODE_OPAQUE:
+            case DDS_ALPHA_MODE_CUSTOM:
+                return mode;
+            }
+        }
+        else if ( ( MAKEFOURCC( 'D', 'X', 'T', '2' ) == header->ddspf.fourCC )
+                  || ( MAKEFOURCC( 'D', 'X', 'T', '4' ) == header->ddspf.fourCC ) )
+        {
+            return DDS_ALPHA_MODE_PREMULTIPLIED;
+        }
+    }
+
+    return DDS_ALPHA_MODE_UNKNOWN;
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CreateDDSTextureFromMemory( ID3D11Device* d3dDevice,
+                                             const uint8_t* ddsData,
+                                             size_t ddsDataSize,
+                                             ID3D11Resource** texture,
+                                             ID3D11ShaderResourceView** textureView,
+                                             size_t maxsize,
+                                             DDS_ALPHA_MODE* alphaMode )
+{
+    return CreateDDSTextureFromMemoryExMipMap( d3dDevice, NULL, ddsData, ddsDataSize, maxsize,
+                                         D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, FALSE,
+                                         texture, textureView, alphaMode );
+}
+
+HRESULT CreateDDSTextureFromMemoryMipMap( ID3D11Device* d3dDevice,
+                                             ID3D11DeviceContext* d3dContext,
+                                             const uint8_t* ddsData,
+                                             size_t ddsDataSize,
+                                             ID3D11Resource** texture,
+                                             ID3D11ShaderResourceView** textureView,
+                                             size_t maxsize,
+                                             DDS_ALPHA_MODE* alphaMode )
+{
+    return CreateDDSTextureFromMemoryExMipMap( d3dDevice, d3dContext, ddsData, ddsDataSize, maxsize,
+                                         D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, FALSE,
+                                         texture, textureView, alphaMode );
+}
+
+HRESULT CreateDDSTextureFromMemoryEx( ID3D11Device* d3dDevice,
+                                               const uint8_t* ddsData,
+                                               size_t ddsDataSize,
+                                               size_t maxsize,
+                                               D3D11_USAGE usage,
+                                               unsigned int bindFlags,
+                                               unsigned int cpuAccessFlags,
+                                               unsigned int miscFlags,
+                                               BOOL forceSRGB,
+                                               ID3D11Resource** texture,
+                                               ID3D11ShaderResourceView** textureView,
+                                               DDS_ALPHA_MODE* alphaMode )
+{
+    return CreateDDSTextureFromMemoryExMipMap( d3dDevice, NULL, ddsData, ddsDataSize, maxsize,
+                                         usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
+                                         texture, textureView, alphaMode );
+}
+
+HRESULT CreateDDSTextureFromMemoryExMipMap( ID3D11Device* d3dDevice,
+                                               ID3D11DeviceContext* d3dContext,
+                                               const uint8_t* ddsData,
+                                               size_t ddsDataSize,
+                                               size_t maxsize,
+                                               D3D11_USAGE usage,
+                                               unsigned int bindFlags,
+                                               unsigned int cpuAccessFlags,
+                                               unsigned int miscFlags,
+                                               BOOL forceSRGB,
+                                               ID3D11Resource** texture,
+                                               ID3D11ShaderResourceView** textureView,
+                                               DDS_ALPHA_MODE* alphaMode )
+{
+    if ( texture )
+    {
+        *texture = NULL;
+    }
+    if ( textureView )
+    {
+        *textureView = NULL;
+    }
+    if ( alphaMode )
+    {
+        *alphaMode = DDS_ALPHA_MODE_UNKNOWN;
+    }
+
+    if (!d3dDevice || !ddsData || (!texture && !textureView))
+    {
+        return E_INVALIDARG;
+    }
+
+    // Validate DDS file in memory
+    if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER)))
+    {
+        return E_FAIL;
+    }
+
+    uint32_t dwMagicNumber = *( const uint32_t* )( ddsData );
+    if (dwMagicNumber != DDS_MAGIC)
+    {
+        return E_FAIL;
+    }
+
+    const DDS_HEADER* header = (const DDS_HEADER*)( ddsData + sizeof( uint32_t ) );
+
+    // Verify header to validate DDS file
+    if (header->size != sizeof(DDS_HEADER) ||
+        header->ddspf.size != sizeof(DDS_PIXELFORMAT))
+    {
+        return E_FAIL;
+    }
+
+    // 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_t) + sizeof(DDS_HEADER_DXT10)))
+        {
+            return E_FAIL;
+        }
+
+        bDXT10Header = TRUE;
+    }
+
+    ptrdiff_t offset = sizeof( uint32_t )
+                       + sizeof( DDS_HEADER )
+                       + (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0);
+
+    HRESULT hr = CreateTextureFromDDS( d3dDevice, d3dContext, header,
+                                       ddsData + offset, ddsDataSize - offset, maxsize,
+                                       usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
+                                       texture, textureView );
+    if ( SUCCEEDED(hr) )
+    {
+        if ( alphaMode )
+            *alphaMode = GetAlphaMode( header );
+    }
+
+    return hr;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CreateDDSTextureFromFile( ID3D11Device* d3dDevice,
+                                           const wchar_t* fileName,
+                                           ID3D11Resource** texture,
+                                           ID3D11ShaderResourceView** textureView,
+                                           size_t maxsize,
+                                           DDS_ALPHA_MODE* alphaMode )
+{
+    return CreateDDSTextureFromFileExMipMap( d3dDevice, NULL, fileName, maxsize,
+                                       D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, FALSE,
+                                       texture, textureView, alphaMode );
+}
+
+HRESULT CreateDDSTextureFromFileMipMap( ID3D11Device* d3dDevice,
+                                           ID3D11DeviceContext* d3dContext,
+                                           const wchar_t* fileName,
+                                           ID3D11Resource** texture,
+                                           ID3D11ShaderResourceView** textureView,
+                                           size_t maxsize,
+                                           DDS_ALPHA_MODE* alphaMode )
+{
+    return CreateDDSTextureFromFileExMipMap( d3dDevice, d3dContext, fileName, maxsize,
+                                       D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, FALSE,
+                                       texture, textureView, alphaMode );
+}
+
+HRESULT CreateDDSTextureFromFileEx( ID3D11Device* d3dDevice,
+                                             const wchar_t* fileName,
+                                             size_t maxsize,
+                                             D3D11_USAGE usage,
+                                             unsigned int bindFlags,
+                                             unsigned int cpuAccessFlags,
+                                             unsigned int miscFlags,
+                                             BOOL forceSRGB,
+                                             ID3D11Resource** texture,
+                                             ID3D11ShaderResourceView** textureView,
+                                             DDS_ALPHA_MODE* alphaMode )
+{
+    return CreateDDSTextureFromFileExMipMap( d3dDevice, NULL, fileName, maxsize,
+                                       usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
+                                       texture, textureView, alphaMode );
+}
+
+HRESULT CreateDDSTextureFromFileExMipMap( ID3D11Device* d3dDevice,
+                                             ID3D11DeviceContext* d3dContext,
+                                             const wchar_t* fileName,
+                                             size_t maxsize,
+                                             D3D11_USAGE usage,
+                                             unsigned int bindFlags,
+                                             unsigned int cpuAccessFlags,
+                                             unsigned int miscFlags,
+                                             BOOL forceSRGB,
+                                             ID3D11Resource** texture,
+                                             ID3D11ShaderResourceView** textureView,
+                                             DDS_ALPHA_MODE* alphaMode )
+{
+    if ( texture )
+    {
+        *texture = NULL;
+    }
+    if ( textureView )
+    {
+        *textureView = NULL;
+    }
+    if ( alphaMode )
+    {
+        *alphaMode = DDS_ALPHA_MODE_UNKNOWN;
+    }
+
+    if (!d3dDevice || !fileName || (!texture && !textureView))
+    {
+        return E_INVALIDARG;
+    }
+
+    DDS_HEADER* header = NULL;
+    uint8_t* bitData = NULL;
+    size_t bitSize = 0;
+
+    uint8_t* ddsData;
+    HRESULT hr = LoadTextureDataFromFile( fileName,
+                                          &ddsData,
+                                          &header,
+                                          &bitData,
+                                          &bitSize
+                                        );
+    if (FAILED(hr))
+    {
+        free(ddsData);
+        return hr;
+    }
+
+    hr = CreateTextureFromDDS( d3dDevice, d3dContext, header,
+                               bitData, bitSize, maxsize,
+                               usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
+                               texture, textureView );
+
+    if ( SUCCEEDED(hr) )
+    {
+#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
+        if (texture != 0 || textureView != 0)
+        {
+            CHAR strFileA[MAX_PATH];
+            int result = WideCharToMultiByte( CP_ACP,
+                                              WC_NO_BEST_FIT_CHARS,
+                                              fileName,
+                                              -1,
+                                              strFileA,
+                                              MAX_PATH,
+                                              NULL,
+                                              FALSE
+                               );
+            if ( result > 0 )
+            {
+                const CHAR* pstrName = strrchr( strFileA, '\\' );
+                if (!pstrName)
+                {
+                    pstrName = strFileA;
+                }
+                else
+                {
+                    pstrName++;
+                }
+
+                if (texture != 0 && *texture != 0)
+                {
+                    (*texture)->lpVtbl->SetPrivateData(*texture, &WKPDID_D3DDebugObjectName,
+                                                (UINT)strnlen_s(pstrName, MAX_PATH),
+                                                pstrName
+                                              );
+                }
+
+                if (textureView != 0 && *textureView != 0 )
+                {
+                    (*textureView)->lpVtbl->SetPrivateData(*textureView, &WKPDID_D3DDebugObjectName,
+                                                    (UINT)strnlen_s(pstrName, MAX_PATH),
+                                                    pstrName
+                                                  );
+                }
+            }
+        }
+#endif
+
+        if ( alphaMode )
+            *alphaMode = GetAlphaMode( header );
+    }
+
+    free(ddsData);
+    return hr;
+}
csource/wrapper.c view
@@ -236,4 +236,30 @@   UINT8 Stencil)
 {
   return This->lpVtbl->ClearDepthStencilView(This, pDepthStencilView, ClearFlags, Depth, Stencil);
+}
+
+HRESULT CreateSamplerState(
+  ID3D11Device* This,
+  const D3D11_SAMPLER_DESC *pSamplerDesc,
+  ID3D11SamplerState **ppSamplerState)
+{
+  return This->lpVtbl->CreateSamplerState(This, pSamplerDesc, ppSamplerState);
+}
+
+void PSSetShaderResources(
+  ID3D11DeviceContext* This,
+  UINT StartSlot,
+  UINT NumViews,
+  ID3D11ShaderResourceView *const *ppShaderResourceViews)
+{
+  This->lpVtbl->PSSetShaderResources(This, StartSlot, NumViews, ppShaderResourceViews);
+}
+
+void STDMETHODCALLTYPE PSSetSamplers( 
+  ID3D11DeviceContext* This,
+  UINT StartSlot,
+  UINT NumSamplers,
+  ID3D11SamplerState *const *ppSamplers)
+{
+  This->lpVtbl->PSSetSamplers(This, StartSlot, NumSamplers, ppSamplers);
 }
d3d11binding.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                d3d11binding
-version:             0.0.0.6
+version:             0.0.0.7
 synopsis:            A raw binding for the directX 11
 description:         A raw binding for the directX 11   
 homepage:            https://github.com/jwvg0425/d3d11binding
@@ -38,6 +38,9 @@     Graphics.D3D11Binding.Interface.D3D11InputLayout
     Graphics.D3D11Binding.Interface.D3D11RenderTargetView
     Graphics.D3D11Binding.Interface.D3D11Resource
+    Graphics.D3D11Binding.Interface.D3D11ShaderResourceView
+    Graphics.D3D11Binding.Interface.D3D11SamplerState
+    
     Graphics.D3D11Binding.Interface.D3DBlob
     Graphics.D3D11Binding.Interface.D3DInclude
     Graphics.D3D11Binding.Interface.D3D11Texture2D
@@ -64,11 +67,13 @@     Graphics.D3D11Binding.GUID
   -- other-modules:       
   other-extensions: ForeignFunctionInterface, CPP   
+  
   build-depends:       
     base >=4.8 && < 5,
     Win32 >= 2.3.0.0,
     c-storable-deriving >= 0.1.3,
     vect >= 0.4.7
+   
   hs-source-dirs:      src
   default-language:    Haskell2010
   extra-libraries:
@@ -83,8 +88,14 @@     D3D11.h
     d3d11shader.h
     D3DCompiler.h
+    include/DDSTextureLoader.h
+  install-includes:
+    include/DDSTextureLoader.h
+  include-dirs:
+    include
   c-sources:
     csource/wrapper.c
+    csource/DDSTextureLoader.c
 
 executable D3D11Binding-Triangle
   main-is: Triangle.hs
@@ -127,6 +138,20 @@   
 executable D3D11Binding-Lighting
   main-is: Lighting.hs
+  -- other-modules:
+  -- other-extensions:
+  build-depends:
+    base >= 4.8 && < 5,
+    Win32 >= 2.3.0.0,
+    d3d11binding,
+    c-storable-deriving >= 0.1.3,
+    vect >= 0.4.7
+    
+  hs-source-dirs: examples
+  default-language: Haskell2010
+
+executable D3D11Binding-Texture
+  main-is: Texture.hs
   -- other-modules:
   -- other-extensions:
   build-depends:
+ examples/Texture.hs view
@@ -0,0 +1,419 @@+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Main where
+import GHC.Generics (Generic)
+  
+import System.Exit
+  
+import Data.Int
+import Data.Word
+import Data.Vect.Float
+import System.CPUTime
+
+import Control.Exception
+import Control.Monad
+
+import Foreign (peekByteOff)
+import Foreign.CStorable
+import Foreign.Storable
+import Foreign.Ptr
+
+import Graphics.Win32
+import System.Win32.DLL (getModuleHandle)
+
+import Graphics.D3D11Binding
+
+foreign import stdcall "PostQuitMessage" postQuitMessage :: Int32 -> IO ()
+
+data SimpleVertex = SimpleVertex Vertex3 Vertex2 deriving (Generic)
+
+instance CStorable SimpleVertex
+instance Storable SimpleVertex where
+  sizeOf = cSizeOf
+  alignment = cAlignment
+  poke = cPoke
+  peek = cPeek
+  
+instance HasSubresourceData SimpleVertex
+
+data CBNeverChanges = CBNeverChanges 
+  { view :: Mat4 
+  , projection :: Mat4
+  } deriving (Generic)
+
+instance CStorable CBNeverChanges
+instance Storable CBNeverChanges where
+  sizeOf = cSizeOf
+  alignment = cAlignment
+  poke = cPoke
+  peek = cPeek
+  
+instance HasSubresourceData CBNeverChanges
+
+
+data CBChangesEveryFrame = CBChangesEveryFrame 
+  { world :: Mat4 
+  , meshColor :: Color
+  } deriving (Generic)
+
+instance CStorable CBChangesEveryFrame
+instance Storable CBChangesEveryFrame where
+  sizeOf = cSizeOf
+  alignment = cAlignment
+  poke = cPoke
+  peek = cPeek
+
+instance HasSubresourceData CBChangesEveryFrame
+
+instance HasSubresourceData Word16
+
+
+windowWidth :: (Num a) => a
+windowWidth = 640
+
+windowHeight :: (Num a) => a
+windowHeight = 480
+
+main :: IO ()
+main = do
+  hWnd <- createDefaultWindow windowWidth windowHeight wndProc
+  useDevice hWnd $ \swapChain device deviceContext renderTargetView depthStencilView -> do
+    vb <- compileShaderFromFile "fx/Texture.fx" "VS" "vs_4_0"
+    (il, vs) <- use vb $ \vsBlob -> do
+      pointer <- getBufferPointer vsBlob
+      size <- getBufferSize vsBlob
+      Right vertexShader <- createVertexShader 
+                              device
+                              pointer
+                              size
+                              nullPtr
+      
+      Right inputLayout <- createInputLayout
+                              device
+                              [ D3D11InputElementDesc 
+                                  "POSITION" 
+                                  (fromIntegral 0)
+                                  DxgiFormatR32G32B32Float
+                                  (fromIntegral 0)
+                                  (fromIntegral 0)
+                                  D3D11InputPerVertexData
+                                  (fromIntegral 0)
+                              , D3D11InputElementDesc
+                                  "TEXCOORD"
+                                  (fromIntegral 0)
+                                  DxgiFormatR32G32Float
+                                  (fromIntegral 0)
+                                  (fromIntegral 12)
+                                  D3D11InputPerVertexData
+                                  (fromIntegral 0) ]
+                              pointer
+                              size
+      iaSetInputLayout deviceContext inputLayout
+      return (inputLayout, vertexShader)
+    
+    pb <- compileShaderFromFile "fx/Texture.fx" "PS" "ps_4_0"
+    (idb, ps) <- use pb $ \psBlob -> do
+      pointer <- getBufferPointer psBlob
+      size <- getBufferSize psBlob
+      Right pixelShader <- createPixelShader
+                            device
+                            pointer
+                            size
+                            nullPtr
+      
+      let bd = D3D11BufferDesc
+                { byteWidth = fromIntegral $ 24 * sizeOf (undefined :: SimpleVertex)
+                , usage = D3D11UsageDefault
+                , bindFlags = d3d11BindFlags [D3D11BindVertexBuffer]
+                , cpuAccessFlags = 0
+                , miscFlags = 0
+                , structureByteStride = 0 }
+                
+      Right buffer <- createBuffer
+                        device
+                        bd
+                        [ SimpleVertex (Vertex3 (-1.0) 1.0 (-1.0)) (Vertex2 0.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 1.0 (-1.0)) (Vertex2 1.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 1.0 1.0) (Vertex2 1.0 1.0)
+                        , SimpleVertex (Vertex3 (-1.0) 1.0 1.0) (Vertex2 0.0 1.0)
+                        
+                        , SimpleVertex (Vertex3 (-1.0) (-1.0) (-1.0)) (Vertex2 0.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 (-1.0) (-1.0)) (Vertex2 1.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 (-1.0) 1.0) (Vertex2 1.0 1.0)
+                        , SimpleVertex (Vertex3 (-1.0) (-1.0) 1.0) (Vertex2 0.0 1.0)
+                        
+                        , SimpleVertex (Vertex3 (-1.0) (-1.0) 1.0) (Vertex2 0.0 0.0)
+                        , SimpleVertex (Vertex3 (-1.0) (-1.0) (-1.0)) (Vertex2 1.0 0.0)
+                        , SimpleVertex (Vertex3 (-1.0) 1.0 (-1.0)) (Vertex2 1.0 1.0)
+                        , SimpleVertex (Vertex3 (-1.0) 1.0 1.0) (Vertex2 0.0 1.0)
+                      
+                        , SimpleVertex (Vertex3 1.0 (-1.0) 1.0) (Vertex2 0.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 (-1.0) (-1.0)) (Vertex2 1.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 1.0 (-1.0)) (Vertex2 1.0 1.0)
+                        , SimpleVertex (Vertex3 1.0 1.0 1.0) (Vertex2 0.0 1.0)
+                        
+                        , SimpleVertex (Vertex3 (-1.0) (-1.0) (-1.0)) (Vertex2 0.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 (-1.0) (-1.0)) (Vertex2 1.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 1.0 (-1.0)) (Vertex2 1.0 1.0)
+                        , SimpleVertex (Vertex3 (-1.0) 1.0 (-1.0)) (Vertex2 0.0 1.0)
+                      
+                        , SimpleVertex (Vertex3 (-1.0) (-1.0) 1.0) (Vertex2 0.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 (-1.0) 1.0) (Vertex2 1.0 0.0)
+                        , SimpleVertex (Vertex3 1.0 1.0 1.0) (Vertex2 1.0 1.0)
+                        , SimpleVertex (Vertex3 (-1.0) 1.0 1.0) (Vertex2 0.0 1.0) ]
+                        
+      iaSetVertexBuffers deviceContext 0 [(buffer, fromIntegral $ sizeOf (undefined :: SimpleVertex), 0)]
+      
+      let indexBd = D3D11BufferDesc
+                { byteWidth = fromIntegral $ 36 * sizeOf (undefined :: Word16)
+                , usage = D3D11UsageDefault
+                , bindFlags = d3d11BindFlags [D3D11BindIndexBuffer]
+                , cpuAccessFlags = 0
+                , miscFlags = 0
+                , structureByteStride = 0 }
+      Right indexBuffer <- createBuffer
+                             device
+                             indexBd
+                             ([ 3,1,0,
+                                2,1,3,
+
+                                6,4,5,
+                                7,4,6,
+
+                                11,9,8,
+                                10,9,11,
+
+                                14,12,13,
+                                15,12,14,
+
+                                19,17,16,
+                                18,17,19,
+
+                                22,20,21,
+                                23,20,22 ] :: [Word16])
+      
+      iaSetIndexBuffer deviceContext indexBuffer DxgiFormatR16Uint 0
+      iaSetPrimitiveTopology deviceContext D3D11PrimitiveTopologyTrianglelist
+      return (indexBuffer, pixelShader)
+    
+    let cbnDesc = D3D11BufferDesc
+                { byteWidth = fromIntegral $ sizeOf (undefined :: CBNeverChanges)
+                , usage = D3D11UsageDefault
+                , bindFlags = d3d11BindFlags [D3D11BindConstantBuffer]
+                , cpuAccessFlags = 0
+                , miscFlags = 0
+                , structureByteStride = 0 }
+    
+    Right cbn <- createBuffer device cbnDesc ([] :: [CBNeverChanges])
+    
+    let cbeDesc = cbnDesc { byteWidth = fromIntegral $ sizeOf (undefined :: CBChangesEveryFrame) }
+    Right cbe <- createBuffer device cbeDesc ([] :: [CBChangesEveryFrame])
+    
+    Right t <- createDDSTextureFromFile device "texture/test.dds"
+    
+    let samplerDesc = D3D11SamplerDesc
+                    { samplerFilter = D3D11FilterMinMagMipLinear
+                    , samplerAddressU = D3D11TextureAddressWrap
+                    , samplerAddressV = D3D11TextureAddressWrap
+                    , samplerAddressW = D3D11TextureAddressWrap
+                    , samplerMipLODBias = 0
+                    , samplerMaxAnisotropy = 0
+                    , samplerComparisonFunc = D3D11ComparisonNever
+                    , samplerBorderColor = Color 0 0 0 0
+                    , samplerMinLOD = 0
+                    , samplerMaxLOD = d3d11Float32Max }
+    
+    Right smp <- createSamplerState device samplerDesc
+    
+    let eye = Vec3 0.0 3.0 (-6.0)
+    let at = Vec3 0.0 1.0 0.0
+    let up = Vec3 0.0 1.0 0.0
+    
+    let view = lookAtLH eye at up
+    let projection = perspectiveFovLH (pi / 4) (windowWidth / windowHeight) 0.01 100
+    
+    updateSubresource deviceContext cbn 0 Nothing (CBNeverChanges (transpose view) (transpose projection)) 0 0
+    
+    use cbn $ \cbNeverChange -> use cbe $ \cbChangesEveryFrame -> use il $ \inputLayout -> use smp $ \sampler ->
+      use vs $ \vertexShader -> use idb $ \ indexBuffer -> use ps $ \pixelShader -> use t $ \texture -> do
+        messagePump 
+          hWnd 
+          deviceContext 
+          swapChain 
+          renderTargetView 
+          depthStencilView 
+          vertexShader 
+          pixelShader 
+          cbNeverChange
+          cbChangesEveryFrame
+          texture
+          sampler
+
+useDevice hWnd proc = do
+  (s, d, dc, r, ds) <- initDevice hWnd
+  use s $ \swapChain -> use d $ \device -> use dc $ \deviceContext -> use r $ \renderTargetView -> use ds $ \depthStencilView ->
+    proc swapChain device deviceContext renderTargetView depthStencilView
+  
+wndProc :: WindowClosure
+wndProc hWnd msg wParam lParam
+  | msg == wM_DESTROY = postQuitMessage 0 >> return 0
+  | otherwise = defWindowProc (Just hWnd) msg wParam lParam
+
+initDevice :: HWND ->
+   IO (Ptr IDxgiSwapChain, Ptr ID3D11Device, Ptr ID3D11DeviceContext, Ptr ID3D11RenderTargetView, Ptr ID3D11DepthStencilView)
+initDevice hWnd = do
+  let bd = DxgiModeDesc 
+            windowWidth 
+            windowHeight 
+            (DxgiRational 60 1) 
+            DxgiFormatR8G8B8A8Unorm 
+            DxgiModeScanlineOrderUnspecified 
+            DxgiModeScalingUnspecified
+  
+  let sd = DxgiSwapChainDesc
+            bd
+            (DxgiSampleDesc 1 0)
+            dxgiUsageRenderTargetOutput
+            1
+            hWnd
+            True
+            DxgiSwapEffectDiscard
+            0
+  
+  Right (swapChain, device, featureLevel, deviceContext) <- d3d11CreateDeviceAndSwapChain
+          nullPtr 
+          D3DDriverTypeHardware
+          nullPtr
+          [D3D11CreateDeviceDebug]
+          [D3DFeatureLevel11_0, D3DFeatureLevel10_1, D3DFeatureLevel10_0]
+          sd
+  
+  Right (backBuffer :: Ptr ID3D11Texture2D) <- getBuffer swapChain (fromIntegral 0)
+  Right renderTargetView <- use backBuffer $ \b -> createRenderTargetView device b Nothing
+  
+  let td = D3D11Texture2DDesc
+            windowWidth
+            windowHeight
+            1
+            1
+            DxgiFormatD24UnormS8Uint
+            (DxgiSampleDesc 1 0)
+            D3D11UsageDefault
+            (d3d11BindFlags [D3D11BindDepthStencil])
+            0
+            0
+  Right depthStencil <- createTexture2D device td ([]::[Word16])
+  
+  let descDsv = D3D11DepthStencilViewDesc
+                  DxgiFormatD24UnormS8Uint
+                  D3D11DsvDimensionTexture2D
+                  0
+                  (tex2dDsv 0)
+  
+  Right depthStencilView <- createDepthStencilView device depthStencil (Just descDsv)
+            
+  omSetRenderTargets deviceContext [renderTargetView] depthStencilView
+  rsSetViewports deviceContext [D3D11Viewport 0 0 windowWidth windowHeight 0 1]
+  
+  return (swapChain, device, deviceContext, renderTargetView, depthStencilView)
+
+compileShaderFromFile :: String -> String -> String -> IO (Ptr ID3DBlob)
+compileShaderFromFile fileName entryPoint shaderModel = do
+  Right res <- d3dCompileFromFile 
+      fileName
+      Nothing
+      Nothing
+      nullPtr
+      (Just entryPoint)
+      shaderModel
+      [d3dCompileEnableStrictness]
+      []
+  return res
+
+createDefaultWindow :: Int -> Int -> WindowClosure -> IO HWND
+createDefaultWindow width height wndProc = do
+  let winClass = mkClassName "Texture Window"
+  icon         <- loadIcon   Nothing iDI_APPLICATION
+  cursor       <- loadCursor Nothing iDC_ARROW
+  bgBrush      <- createSolidBrush (rgb 255 255 255)
+  mainInstance <- getModuleHandle Nothing
+  registerClass
+    ( cS_VREDRAW + cS_HREDRAW
+    , mainInstance
+    , Just icon
+    , Just cursor
+    , Just bgBrush
+    , Nothing
+    , winClass )
+  w <- createWindow
+       winClass
+       "Texture"
+       wS_OVERLAPPEDWINDOW
+       Nothing Nothing
+       (Just width)
+       (Just height)
+       Nothing
+       Nothing
+       mainInstance
+       wndProc
+  
+  showWindow w sW_SHOWNORMAL
+  updateWindow w
+  return w
+
+pM_NOREMOVE, pM_REMOVE, pM_NOYIELD :: UINT
+pM_NOREMOVE = 0x0000
+pM_REMOVE = 0x0001
+pM_NOYIELD = 0x0002
+
+messagePump 
+  :: HWND -> Ptr ID3D11DeviceContext -> 
+     Ptr IDxgiSwapChain -> Ptr ID3D11RenderTargetView -> Ptr ID3D11DepthStencilView ->
+     Ptr ID3D11VertexShader -> Ptr ID3D11PixelShader -> 
+     Ptr ID3D11Buffer -> Ptr ID3D11Buffer ->
+     Ptr ID3D11ShaderResourceView -> Ptr ID3D11SamplerState -> IO ()
+messagePump hwnd deviceContext swapChain renderTargetView depthStencilView vs ps cbn cbe texture sampler = 
+  Graphics.Win32.allocaMessage $ \ msg ->
+    let pump = do
+          m <- peekByteOff msg 4 :: IO WindowMessage
+          when (m /= wM_QUIT) $ do
+            r <- c_PeekMessage msg (maybePtr Nothing) 0 0 pM_REMOVE
+            if r /= 0
+            then do
+              translateMessage msg
+              dispatchMessage msg
+              return ()
+            else do
+              render deviceContext swapChain renderTargetView depthStencilView vs ps cbn cbe texture sampler
+            pump
+    in pump
+  
+render 
+  :: Ptr ID3D11DeviceContext -> Ptr IDxgiSwapChain -> Ptr ID3D11RenderTargetView -> Ptr ID3D11DepthStencilView -> 
+     Ptr ID3D11VertexShader -> Ptr ID3D11PixelShader ->
+     Ptr ID3D11Buffer -> Ptr ID3D11Buffer ->
+     Ptr ID3D11ShaderResourceView -> Ptr ID3D11SamplerState -> IO ()
+render deviceContext swapChain renderTargetView depthStencilView vs ps cbn cbe texture sampler = do
+  clearRenderTargetView deviceContext renderTargetView $ Color 0.0 0.125 0.3 1.0
+  clearDepthStencilView deviceContext depthStencilView [D3D11ClearDepth] 1 0
+  
+  t <- getCPUTime
+  let d = (fromIntegral t) / 1000000000000
+  
+  let world = rotationY d
+  let meshColor = Color ((sin d + 1) * 0.5) ((cos (d*3) + 1) * 0.5) ((sin (d*5) + 1) * 0.5) 1
+  
+  updateSubresource deviceContext cbe 0 Nothing (CBChangesEveryFrame (transpose world) meshColor) 0 0
+  
+  vsSetShader deviceContext vs []
+  vsSetConstantBuffers deviceContext 0 [cbn]
+  vsSetConstantBuffers deviceContext 1 [cbe]
+  psSetShader deviceContext ps []
+  psSetConstantBuffers deviceContext 1 [cbe]
+  psSetShaderResources deviceContext 0 [texture]
+  psSetSamplers deviceContext 0 [sampler]
+  
+  drawIndexed deviceContext 36 0 0
+  
+  present swapChain 0 0
+  return ()
+ include/DDSTextureLoader.h view
@@ -0,0 +1,107 @@+#include <d3d11_1.h>
+#include <stdint.h>
+
+typedef 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,
+} DDS_ALPHA_MODE;
+
+// Standard version
+HRESULT CreateDDSTextureFromMemory( ID3D11Device* d3dDevice,
+                                    const uint8_t* ddsData,
+                                    size_t ddsDataSize,
+                                    ID3D11Resource** texture,
+                                    ID3D11ShaderResourceView** textureView,
+                                    size_t maxsize,
+                                    DDS_ALPHA_MODE* alphaMode
+                                      );
+
+HRESULT CreateDDSTextureFromFile( ID3D11Device* d3dDevice,
+                                  const wchar_t* szFileName,
+                                  ID3D11Resource** texture,
+                                  ID3D11ShaderResourceView** textureView,
+                                  size_t maxsize,
+                                  DDS_ALPHA_MODE* alphaMode
+                                    );
+
+// Standard version with optional auto-gen mipmap support
+HRESULT CreateDDSTextureFromMemoryMipMap( ID3D11Device* d3dDevice,
+                                    ID3D11DeviceContext* d3dContext,
+                                    const uint8_t* ddsData,
+                                    size_t ddsDataSize,
+                                    ID3D11Resource** texture,
+                                    ID3D11ShaderResourceView** textureView,
+                                    size_t maxsize,
+                                    DDS_ALPHA_MODE* alphaMode
+                                      );
+
+HRESULT CreateDDSTextureFromFileMipMap( ID3D11Device* d3dDevice,
+                                  ID3D11DeviceContext* d3dContext,
+                                  const wchar_t* szFileName,
+                                  ID3D11Resource** texture,
+                                  ID3D11ShaderResourceView** textureView,
+                                  size_t maxsize,
+                                  DDS_ALPHA_MODE* alphaMode
+                                    );
+
+// Extended version
+HRESULT CreateDDSTextureFromMemoryEx( ID3D11Device* d3dDevice,
+                                      const uint8_t* ddsData,
+                                      size_t ddsDataSize,
+                                      size_t maxsize,
+                                      D3D11_USAGE usage,
+                                      unsigned int bindFlags,
+                                      unsigned int cpuAccessFlags,
+                                      unsigned int miscFlags,
+                                      BOOL forceSRGB,
+                                      ID3D11Resource** texture,
+                                      ID3D11ShaderResourceView** textureView,
+                                      DDS_ALPHA_MODE* alphaMode
+                                      );
+
+HRESULT CreateDDSTextureFromFileEx( ID3D11Device* d3dDevice,
+                                    const wchar_t* szFileName,
+                                    size_t maxsize,
+                                    D3D11_USAGE usage,
+                                    unsigned int bindFlags,
+                                    unsigned int cpuAccessFlags,
+                                    unsigned int miscFlags,
+                                    BOOL forceSRGB,
+                                    ID3D11Resource** texture,
+                                    ID3D11ShaderResourceView** textureView,
+                                    DDS_ALPHA_MODE* alphaMode
+                                    );
+
+// Extended version with optional auto-gen mipmap support
+HRESULT CreateDDSTextureFromMemoryExMipMap( ID3D11Device* d3dDevice,
+                                      ID3D11DeviceContext* d3dContext,
+                                      const uint8_t* ddsData,
+                                      size_t ddsDataSize,
+                                      size_t maxsize,
+                                      D3D11_USAGE usage,
+                                      unsigned int bindFlags,
+                                      unsigned int cpuAccessFlags,
+                                      unsigned int miscFlags,
+                                      BOOL forceSRGB,
+                                      ID3D11Resource** texture,
+                                      ID3D11ShaderResourceView** textureView,
+                                      DDS_ALPHA_MODE* alphaMode
+                                      );
+
+HRESULT CreateDDSTextureFromFileExMipMap( ID3D11Device* d3dDevice,
+                                    ID3D11DeviceContext* d3dContext,
+                                    const wchar_t* szFileName,
+                                    size_t maxsize,
+                                    D3D11_USAGE usage,
+                                    unsigned int bindFlags,
+                                    unsigned int cpuAccessFlags,
+                                    unsigned int miscFlags,
+                                    BOOL forceSRGB,
+                                    ID3D11Resource** texture,
+                                    ID3D11ShaderResourceView** textureView,
+                                    DDS_ALPHA_MODE* alphaMode
+                                    );
src/Graphics/D3D11Binding.hs view
@@ -7,6 +7,7 @@ , module Graphics.D3D11Binding.Utils
 , module Graphics.D3D11Binding.Math
 , d3d11CreateDeviceAndSwapChain
+, createDDSTextureFromFile
 ) where
 
 import Data.Word
@@ -26,6 +27,7 @@ import Foreign.Marshal.Array
 import Foreign.Marshal.Alloc
 import Foreign.Storable
+import Foreign.C.String
 
 type PIDxgiAdapter = Ptr IDxgiAdapter
 type PD3DFeatureLevel = Ptr D3DFeatureLevel
@@ -71,4 +73,17 @@       peekDevice <- peek device
       peekFeature <- peek feature
       peekContext <- peek context
-      return $ Right (peekSwapChain, peekDevice, peekFeature, peekContext)+      return $ Right (peekSwapChain, peekDevice, peekFeature, peekContext)
+      
+foreign import stdcall "CreateDDSTextureFromFile" c_createDDSTextureFromFile
+  :: Ptr ID3D11Device -> CWString -> Ptr (Ptr ID3D11Resource) -> 
+     Ptr (Ptr ID3D11ShaderResourceView) -> Word32 -> Ptr DDSAlphaMode -> IO HRESULT
+  
+createDDSTextureFromFile :: Ptr ID3D11Device -> String -> IO (Either HRESULT (Ptr ID3D11ShaderResourceView))
+createDDSTextureFromFile device fileName = 
+  alloca $ \pResource -> withCWString fileName $ \wFileName ->  do
+    hr <- c_createDDSTextureFromFile device wFileName nullPtr pResource 0 nullPtr
+    if hr < 0 then do 
+      print hr 
+      return (Left hr)
+    else Right <$> peek pResource
src/Graphics/D3D11Binding/Enums.hs view
@@ -472,4 +472,182 @@   fromEnum D3D11ClearStencil = 2
   toEnum 1 = D3D11ClearDepth
   toEnum 2 = D3D11ClearStencil
-  toEnum unmatched = error ("D3D11ClearFlag.toEnum: cannot match " ++ show unmatched)+  toEnum unmatched = error ("D3D11ClearFlag.toEnum: cannot match " ++ show unmatched)
+
+data DDSAlphaMode = DDSAlphaModeUnknown
+                  | DDSAlphaModeStraight
+                  | DDSAlphaModePremultiplied
+                  | DDSAlphaModeOpaque
+                  | DDSAlphaModeCustom
+                  deriving (Eq, Show)
+                  
+instance Enum DDSAlphaMode where
+  fromEnum DDSAlphaModeUnknown = 0
+  fromEnum DDSAlphaModeStraight = 1
+  fromEnum DDSAlphaModePremultiplied = 2
+  fromEnum DDSAlphaModeOpaque = 3
+  fromEnum DDSAlphaModeCustom = 4
+  toEnum 0 = DDSAlphaModeUnknown
+  toEnum 1 = DDSAlphaModeStraight
+  toEnum 2 = DDSAlphaModePremultiplied
+  toEnum 3 = DDSAlphaModeOpaque
+  toEnum 4 = DDSAlphaModeCustom
+  toEnum unmatched =  error ("DDSAlphaMode.toEnum: cannot match " ++ show unmatched)
+  
+instance Storable DDSAlphaMode where
+  sizeOf e = sizeOf ((fromIntegral $ fromEnum e) :: Int32)
+  alignment e = alignment ((fromIntegral $ fromEnum e) :: Int32)
+  peek ptr = peekByteOff (castPtr ptr :: Ptr Int32) 0 >>= (return . toEnum)
+  poke ptr val = pokeByteOff (castPtr ptr :: Ptr Int32) 0 (fromEnum val)
+  
+instance CStorable DDSAlphaMode where
+  cSizeOf = sizeOf
+  cAlignment = alignment
+  cPeek = peek
+  cPoke = poke
+  
+data D3D11Filter = D3D11FilterMinMagMipPoint
+                 | D3D11FilterMinMagPointMipLinear
+                 | D3D11FilterMinPointMagLinearMipPoint
+                 | D3D11FilterMinPointMagMipLinear
+                 | D3D11FilterMinLinearMagMipPoint
+                 | D3D11FilterMinLinearMagPointMipLinear
+                 | D3D11FilterMinMagLinearMipPoint
+                 | D3D11FilterMinMagMipLinear
+                 | D3D11FilterAnisotropic
+                 | D3D11FilterComparisonMinMagMipPoint
+                 | D3D11FilterComparisonMinMagPointMipLinear
+                 | D3D11FilterComparisonMinPointMagLinearMipPoint
+                 | D3D11FilterComparisonMinPointMagMipLinear
+                 | D3D11FilterComparisonMinLinearMagMipPoint
+                 | D3D11FilterComparisonMinLinearMagPointMipLinear
+                 | D3D11FilterComparisonMinMagLinearMipPoint
+                 | D3D11FilterComparisonMinMagMipLinear
+                 | D3D11FilterComparisonAnisotropic
+                 deriving (Eq, Show)
+                 
+instance Enum D3D11Filter where
+  fromEnum D3D11FilterMinMagMipPoint = 0
+  fromEnum D3D11FilterMinMagPointMipLinear = 0x1
+  fromEnum D3D11FilterMinPointMagLinearMipPoint = 0x4
+  fromEnum D3D11FilterMinPointMagMipLinear = 0x5
+  fromEnum D3D11FilterMinLinearMagMipPoint = 0x10
+  fromEnum D3D11FilterMinLinearMagPointMipLinear = 0x11
+  fromEnum D3D11FilterMinMagLinearMipPoint = 0x14
+  fromEnum D3D11FilterMinMagMipLinear = 0x15
+  fromEnum D3D11FilterAnisotropic = 0x55
+  fromEnum D3D11FilterComparisonMinMagMipPoint = 0x80
+  fromEnum D3D11FilterComparisonMinMagPointMipLinear = 0x81
+  fromEnum D3D11FilterComparisonMinPointMagLinearMipPoint = 0x84
+  fromEnum D3D11FilterComparisonMinPointMagMipLinear = 0x85
+  fromEnum D3D11FilterComparisonMinLinearMagMipPoint = 0x90
+  fromEnum D3D11FilterComparisonMinLinearMagPointMipLinear = 0x91
+  fromEnum D3D11FilterComparisonMinMagLinearMipPoint = 0x94
+  fromEnum D3D11FilterComparisonMinMagMipLinear = 0x95
+  fromEnum D3D11FilterComparisonAnisotropic = 0xd5
+  
+  toEnum 0 = D3D11FilterMinMagMipPoint
+  toEnum 0x1 = D3D11FilterMinMagPointMipLinear
+  toEnum 0x4 = D3D11FilterMinPointMagLinearMipPoint
+  toEnum 0x5 = D3D11FilterMinPointMagMipLinear
+  toEnum 0x10 = D3D11FilterMinLinearMagMipPoint
+  toEnum 0x11 = D3D11FilterMinLinearMagPointMipLinear
+  toEnum 0x14 = D3D11FilterMinMagLinearMipPoint
+  toEnum 0x15 = D3D11FilterMinMagMipLinear
+  toEnum 0x55 = D3D11FilterAnisotropic
+  toEnum 0x80 = D3D11FilterComparisonMinMagMipPoint
+  toEnum 0x81 = D3D11FilterComparisonMinMagPointMipLinear
+  toEnum 0x84 = D3D11FilterComparisonMinPointMagLinearMipPoint
+  toEnum 0x85 = D3D11FilterComparisonMinPointMagMipLinear
+  toEnum 0x90 = D3D11FilterComparisonMinLinearMagMipPoint
+  toEnum 0x91 = D3D11FilterComparisonMinLinearMagPointMipLinear
+  toEnum 0x94 = D3D11FilterComparisonMinMagLinearMipPoint
+  toEnum 0x95 = D3D11FilterComparisonMinMagMipLinear
+  toEnum 0xd5 = D3D11FilterComparisonAnisotropic
+  toEnum unmatched =  error ("D3D11Filter.toEnum: cannot match " ++ show unmatched)
+
+instance Storable D3D11Filter where
+  sizeOf e = sizeOf ((fromIntegral $ fromEnum e) :: Int32)
+  alignment e = alignment ((fromIntegral $ fromEnum e) :: Int32)
+  peek ptr = peekByteOff (castPtr ptr :: Ptr Int32) 0 >>= (return . toEnum)
+  poke ptr val = pokeByteOff (castPtr ptr :: Ptr Int32) 0 (fromEnum val)
+  
+instance CStorable D3D11Filter where
+  cSizeOf = sizeOf
+  cAlignment = alignment
+  cPeek = peek
+  cPoke = poke
+
+data D3D11TextureAddressMode = D3D11TextureAddressWrap
+                             | D3D11TextureAddressMirror
+                             | D3D11TextureAddressClamp
+                             | D3D11TextureAddressBorder
+                             | D3D11TextureAddressMirrorOnce
+                             deriving (Eq, Show)
+
+instance Enum D3D11TextureAddressMode where
+  fromEnum D3D11TextureAddressWrap = 1
+  fromEnum D3D11TextureAddressMirror = 2
+  fromEnum D3D11TextureAddressClamp = 3
+  fromEnum D3D11TextureAddressBorder = 4
+  fromEnum D3D11TextureAddressMirrorOnce = 5
+  toEnum 1 = D3D11TextureAddressWrap
+  toEnum 2 = D3D11TextureAddressMirror
+  toEnum 3 = D3D11TextureAddressClamp
+  toEnum 4 = D3D11TextureAddressBorder
+  toEnum 5 = D3D11TextureAddressMirrorOnce
+  toEnum unmatched =  error ("D3D11TextureAddressMode.toEnum: cannot match " ++ show unmatched)
+  
+instance Storable D3D11TextureAddressMode where
+  sizeOf e = sizeOf ((fromIntegral $ fromEnum e) :: Int32)
+  alignment e = alignment ((fromIntegral $ fromEnum e) :: Int32)
+  peek ptr = peekByteOff (castPtr ptr :: Ptr Int32) 0 >>= (return . toEnum)
+  poke ptr val = pokeByteOff (castPtr ptr :: Ptr Int32) 0 (fromEnum val)
+  
+instance CStorable D3D11TextureAddressMode where
+  cSizeOf = sizeOf
+  cAlignment = alignment
+  cPeek = peek
+  cPoke = poke
+  
+data D3D11ComparisonFunc = D3D11ComparisonNever
+                         | D3D11ComparisonLess
+                         | D3D11ComparisonEqual
+                         | D3D11ComparisonLessEqual
+                         | D3D11ComparisonGreater
+                         | D3D11ComparisonNotEqual
+                         | D3D11ComparisonGreaterEqual
+                         | D3D11ComparisonAlways
+                         deriving (Eq, Show)
+                         
+instance Enum D3D11ComparisonFunc where
+  fromEnum D3D11ComparisonNever = 1
+  fromEnum D3D11ComparisonLess = 2
+  fromEnum D3D11ComparisonEqual = 3
+  fromEnum D3D11ComparisonLessEqual = 4
+  fromEnum D3D11ComparisonGreater = 5
+  fromEnum D3D11ComparisonNotEqual = 6
+  fromEnum D3D11ComparisonGreaterEqual = 7
+  fromEnum D3D11ComparisonAlways = 8
+  
+  toEnum 0 = D3D11ComparisonNever
+  toEnum 1 = D3D11ComparisonLess
+  toEnum 2 = D3D11ComparisonEqual
+  toEnum 3 = D3D11ComparisonLessEqual
+  toEnum 4 = D3D11ComparisonGreater
+  toEnum 5 = D3D11ComparisonNotEqual
+  toEnum 6 = D3D11ComparisonGreaterEqual
+  toEnum 7 = D3D11ComparisonAlways
+  toEnum unmatched =  error ("D3D11ComparisonFunc.toEnum: cannot match " ++ show unmatched)
+                         
+instance Storable D3D11ComparisonFunc where
+  sizeOf e = sizeOf ((fromIntegral $ fromEnum e) :: Int32)
+  alignment e = alignment ((fromIntegral $ fromEnum e) :: Int32)
+  peek ptr = peekByteOff (castPtr ptr :: Ptr Int32) 0 >>= (return . toEnum)
+  poke ptr val = pokeByteOff (castPtr ptr :: Ptr Int32) 0 (fromEnum val)
+  
+instance CStorable D3D11ComparisonFunc where
+  cSizeOf = sizeOf
+  cAlignment = alignment
+  cPeek = peek
+  cPoke = poke
src/Graphics/D3D11Binding/Interface.hs view
@@ -7,6 +7,9 @@ , module Graphics.D3D11Binding.Interface.D3D11InputLayout
 , module Graphics.D3D11Binding.Interface.D3D11RenderTargetView
 , module Graphics.D3D11Binding.Interface.D3D11Resource
+, module Graphics.D3D11Binding.Interface.D3D11ShaderResourceView
+, module Graphics.D3D11Binding.Interface.D3D11SamplerState
+
 , module Graphics.D3D11Binding.Interface.D3DBlob
 , module Graphics.D3D11Binding.Interface.D3DInclude
 , module Graphics.D3D11Binding.Interface.D3D11Texture2D
@@ -25,6 +28,9 @@ import Graphics.D3D11Binding.Interface.D3D11InputLayout
 import Graphics.D3D11Binding.Interface.D3D11RenderTargetView
 import Graphics.D3D11Binding.Interface.D3D11Resource
+import Graphics.D3D11Binding.Interface.D3D11ShaderResourceView
+import Graphics.D3D11Binding.Interface.D3D11SamplerState
+
 import Graphics.D3D11Binding.Interface.D3DBlob
 import Graphics.D3D11Binding.Interface.D3DInclude
 import Graphics.D3D11Binding.Interface.D3D11Texture2D
src/Graphics/D3D11Binding/Interface/D3D11Device.hs view
@@ -19,6 +19,7 @@ import Graphics.D3D11Binding.Interface.D3D11ClassLinkage
 import Graphics.D3D11Binding.Interface.D3D11InputLayout
 import Graphics.D3D11Binding.Interface.D3D11Texture2D
+import Graphics.D3D11Binding.Interface.D3D11SamplerState
 
 import Graphics.D3D11Binding.Shader.D3D11VertexShader
 import Graphics.D3D11Binding.Shader.D3D11PixelShader
@@ -44,6 +45,9 @@ foreign import stdcall "CreateDepthStencilView" c_createDepthStencilView
   :: Ptr ID3D11Device -> Ptr ID3D11Resource -> Ptr D3D11DepthStencilViewDesc -> Ptr (Ptr ID3D11DepthStencilView) -> IO HRESULT
 
+foreign import stdcall "CreateSamplerState" c_createSamplerState
+  :: Ptr ID3D11Device -> Ptr D3D11SamplerDesc -> Ptr (Ptr ID3D11SamplerState) -> IO HRESULT
+
 class (UnknownInterface interface) => D3D11DeviceInterface interface where
   createRenderTargetView
     :: (D3D11ResourceInterface resource) => 
@@ -101,7 +105,8 @@         if hr < 0 then return (Left hr) else Right <$> peek ppBuffer
 
   createTexture2D
-    :: (HasSubresourceData resource) => Ptr interface -> D3D11Texture2DDesc -> [resource] -> IO (Either HRESULT (Ptr ID3D11Texture2D))
+    :: (HasSubresourceData resource) => Ptr interface -> D3D11Texture2DDesc -> [resource] ->
+       IO (Either HRESULT (Ptr ID3D11Texture2D))
   createTexture2D this desc resource =
     alloca $ \ppTexture2D -> alloca $ \pDesc -> do
       poke pDesc desc
@@ -114,6 +119,14 @@         poke pResource resource'
         hr <- c_createTexture2D (castPtr this) pDesc pResource ppTexture2D
         if hr < 0 then return (Left hr) else Right <$> peek ppTexture2D
+  
+  createSamplerState
+    :: Ptr interface -> D3D11SamplerDesc -> IO (Either HRESULT (Ptr ID3D11SamplerState))
+  createSamplerState this desc =
+    alloca $ \pDesc -> alloca $ \ppState -> do
+      poke pDesc desc
+      hr <- c_createSamplerState (castPtr this) pDesc ppState
+      if hr < 0 then return (Left hr) else Right <$> peek ppState
       
 data ID3D11Device = ID3D11Device
 
src/Graphics/D3D11Binding/Interface/D3D11DeviceContext.hs view
@@ -20,6 +20,8 @@ import Graphics.D3D11Binding.Interface.D3D11DepthStencilView
 import Graphics.D3D11Binding.Interface.D3D11InputLayout
 import Graphics.D3D11Binding.Interface.D3D11ClassInstance
+import Graphics.D3D11Binding.Interface.D3D11ShaderResourceView
+import Graphics.D3D11Binding.Interface.D3D11SamplerState
 
 import Graphics.D3D11Binding.Shader.D3D11VertexShader
 import Graphics.D3D11Binding.Shader.D3D11PixelShader
@@ -68,7 +70,13 @@ 
 foreign import stdcall "DrawIndexed" c_drawIndexed
   :: Ptr ID3D11DeviceContext -> Word32 -> Word32 -> Word32 -> IO ()
+  
+foreign import stdcall "PSSetShaderResources" c_psSetShaderResources
+  :: Ptr ID3D11DeviceContext -> Word32 -> Word32 -> Ptr (Ptr ID3D11ShaderResourceView) -> IO ()
 
+foreign import stdcall "PSSetSamplers" c_psSetSamplers
+  :: Ptr ID3D11DeviceContext -> Word32 -> Word32 -> Ptr (Ptr ID3D11SamplerState) -> IO ()
+
 class (UnknownInterface interface) => D3D11DeviceContextInterface interface where
   omSetRenderTargets :: Ptr interface -> [Ptr ID3D11RenderTargetView] -> Ptr ID3D11DepthStencilView -> IO ()
   omSetRenderTargets ptr renderTargetViews depthStencilView = alloca $ \pRenderTargetViews -> do
@@ -135,6 +143,16 @@   psSetShader ptr pixelShader classInstances = maybePokeArray classInstances $ \pClassInstances -> do
     let classInstanceNum = fromIntegral $ length classInstances
     c_psSetShader (castPtr ptr) pixelShader pClassInstances classInstanceNum
+  
+  psSetShaderResources :: Ptr interface -> Word32 -> [Ptr ID3D11ShaderResourceView] -> IO ()
+  psSetShaderResources ptr startSlot resources = alloca $ \pResources -> do
+    pokeArray pResources resources
+    c_psSetShaderResources (castPtr ptr) startSlot (fromIntegral $ length resources) pResources
+    
+  psSetSamplers :: Ptr interface -> Word32 -> [Ptr ID3D11SamplerState] -> IO ()
+  psSetSamplers ptr startSlot samplers = alloca $ \pSamplers -> do
+    pokeArray pSamplers samplers
+    c_psSetSamplers (castPtr ptr) startSlot (fromIntegral $ length samplers) pSamplers
   
   draw :: Ptr interface -> Word32 -> Word32 -> IO ()
   draw ptr vertexCount startVertexLocation = c_draw (castPtr ptr) vertexCount startVertexLocation
+ src/Graphics/D3D11Binding/Interface/D3D11SamplerState.hs view
@@ -0,0 +1,7 @@+module Graphics.D3D11Binding.Interface.D3D11SamplerState where
+
+import Graphics.D3D11Binding.Interface.Unknown
+
+data ID3D11SamplerState = ID3D11SamplerState
+
+instance UnknownInterface ID3D11SamplerState
+ src/Graphics/D3D11Binding/Interface/D3D11ShaderResourceView.hs view
@@ -0,0 +1,7 @@+module Graphics.D3D11Binding.Interface.D3D11ShaderResourceView where
+
+import Graphics.D3D11Binding.Interface.Unknown
+
+data ID3D11ShaderResourceView = ID3D11ShaderResourceView
+
+instance UnknownInterface ID3D11ShaderResourceView
src/Graphics/D3D11Binding/Types.hs view
@@ -323,3 +323,26 @@ 
 tex2dMsArrayDsv :: Word32 -> Word32 -> Dsv
 tex2dMsArrayDsv firstArraySlice arraySize = Dsv firstArraySlice arraySize (fromIntegral 0)
+
+data D3D11SamplerDesc = D3D11SamplerDesc
+  { samplerFilter :: D3D11Filter
+  , samplerAddressU :: D3D11TextureAddressMode
+  , samplerAddressV :: D3D11TextureAddressMode
+  , samplerAddressW :: D3D11TextureAddressMode
+  , samplerMipLODBias :: Float
+  , samplerMaxAnisotropy :: Word32
+  , samplerComparisonFunc :: D3D11ComparisonFunc
+  , samplerBorderColor :: Color
+  , samplerMinLOD :: Float
+  , samplerMaxLOD :: Float
+  } deriving (Generic)
+  
+instance CStorable D3D11SamplerDesc
+instance Storable D3D11SamplerDesc where
+  sizeOf = cSizeOf
+  alignment = cAlignment
+  poke = cPoke
+  peek = cPeek
+  
+d3d11Float32Max :: Float
+d3d11Float32Max = 3402823466e+38