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 +1794/−0
- csource/wrapper.c +26/−0
- d3d11binding.cabal +26/−1
- examples/Texture.hs +419/−0
- include/DDSTextureLoader.h +107/−0
- src/Graphics/D3D11Binding.hs +16/−1
- src/Graphics/D3D11Binding/Enums.hs +179/−1
- src/Graphics/D3D11Binding/Interface.hs +6/−0
- src/Graphics/D3D11Binding/Interface/D3D11Device.hs +14/−1
- src/Graphics/D3D11Binding/Interface/D3D11DeviceContext.hs +18/−0
- src/Graphics/D3D11Binding/Interface/D3D11SamplerState.hs +7/−0
- src/Graphics/D3D11Binding/Interface/D3D11ShaderResourceView.hs +7/−0
- src/Graphics/D3D11Binding/Types.hs +23/−0
+ 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