diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2017-05-20 20:20:23 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2017-05-20 20:20:23 +0000 |
| commit | cdd751dc2f5bf0851c795587aab4fd547e95b6a8 (patch) | |
| tree | c20f440a9a092ec8f655e38f30cab522a4933f93 /Projects/Asteroids/src | |
| parent | Updated submodules (diff) | |
| download | DiligentEngine-cdd751dc2f5bf0851c795587aab4fd547e95b6a8.tar.gz DiligentEngine-cdd751dc2f5bf0851c795587aab4fd547e95b6a8.zip | |
Added asteroids sample
Diffstat (limited to 'Projects/Asteroids/src')
42 files changed, 9762 insertions, 0 deletions
diff --git a/Projects/Asteroids/src/DDSTextureLoader.cpp b/Projects/Asteroids/src/DDSTextureLoader.cpp new file mode 100644 index 0000000..97e1064 --- /dev/null +++ b/Projects/Asteroids/src/DDSTextureLoader.cpp @@ -0,0 +1,1103 @@ +//-------------------------------------------------------------------------------------- +// File: DDSTextureLoader.cpp +// +// Functions for loading a DDS texture without using D3DX +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +//#include "DXUT.h" +#include "DDSTextureLoader.h" +#include <d3d9.h> // For D3DFMT stuff + +#include <assert.h> +#include <algorithm> +using std::max; +using std::min; + +#define SAFE_DELETE_ARRAY(a) if(a) { delete[] a; a=nullptr; } +#define SAFE_RELEASE(a) if(a) { a->Release(); a=nullptr; } + + +// From DXUT +//-------------------------------------------------------------------------------------- +// Helper functions to create SRGB formats from typeless formats and vice versa +//-------------------------------------------------------------------------------------- +DXGI_FORMAT MAKE_SRGB( _In_ DXGI_FORMAT format ) +{ + switch( format ) + { + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + }; + + return format; +} + + +//-------------------------------------------------------------------------------------- +HRESULT LoadTextureDataFromFile( __in_z const WCHAR* szFileName, BYTE** ppHeapData, + DDS_HEADER** ppHeader, + BYTE** ppBitData, UINT* pBitSize ) +{ + // open the file + HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, NULL ); + if( INVALID_HANDLE_VALUE == hFile ) + return HRESULT_FROM_WIN32( GetLastError() ); + + // Get the file size + LARGE_INTEGER FileSize = {0}; + GetFileSizeEx( hFile, &FileSize ); + + // File is too big for 32-bit allocation, so reject read + if( FileSize.HighPart > 0 ) + { + CloseHandle( 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(DWORD)) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // create enough space for the file data + *ppHeapData = new BYTE[ FileSize.LowPart ]; + if( !( *ppHeapData ) ) + { + CloseHandle( hFile ); + return E_OUTOFMEMORY; + } + + // read the data in + DWORD BytesRead = 0; + if( !ReadFile( hFile, *ppHeapData, FileSize.LowPart, &BytesRead, NULL ) ) + { + CloseHandle( hFile ); + SAFE_DELETE_ARRAY( *ppHeapData ); + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if( BytesRead < FileSize.LowPart ) + { + CloseHandle( hFile ); + SAFE_DELETE_ARRAY( *ppHeapData ); + return E_FAIL; + } + + // DDS files always start with the same magic number ("DDS ") + DWORD dwMagicNumber = *( DWORD* )( *ppHeapData ); + if( dwMagicNumber != DDS_MAGIC ) + { + CloseHandle( hFile ); + SAFE_DELETE_ARRAY( *ppHeapData ); + return E_FAIL; + } + + DDS_HEADER* pHeader = reinterpret_cast<DDS_HEADER*>( *ppHeapData + sizeof( DWORD ) ); + + // Verify header to validate DDS file + if( pHeader->dwSize != sizeof(DDS_HEADER) + || pHeader->ddspf.dwSize != sizeof(DDS_PIXELFORMAT) ) + { + CloseHandle( hFile ); + SAFE_DELETE_ARRAY( *ppHeapData ); + return E_FAIL; + } + + // Check for DX10 extension + bool bDXT10Header = false; + if ( (pHeader->ddspf.dwFlags & DDS_FOURCC) + && (MAKEFOURCC( 'D', 'X', '1', '0' ) == pHeader->ddspf.dwFourCC) ) + { + // Must be long enough for both headers and magic value + if( FileSize.LowPart < (sizeof(DDS_HEADER)+sizeof(DWORD)+sizeof(DDS_HEADER_DXT10)) ) + { + CloseHandle( hFile ); + SAFE_DELETE_ARRAY( *ppHeapData ); + return E_FAIL; + } + + bDXT10Header = true; + } + + // setup the pointers in the process request + *ppHeader = pHeader; + INT offset = sizeof( DWORD ) + sizeof( DDS_HEADER ) + + (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0); + *ppBitData = *ppHeapData + offset; + *pBitSize = FileSize.LowPart - offset; + + CloseHandle( hFile ); + + return S_OK; +} + + +static UINT BitsPerPixel( DXGI_FORMAT fmt ) +{ + switch( fmt ) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 96; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return 64; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return 32; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + return 16; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return 8; + + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 4; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + + default: + return 0; + } +} + + +static void GetSurfaceInfo( UINT width, UINT height, DXGI_FORMAT fmt, UINT* pNumBytes, UINT* pRowBytes, UINT* pNumRows ) +{ + UINT numBytes = 0; + UINT rowBytes = 0; + UINT numRows = 0; + + bool bc = false; + bool packed = false; + UINT bcnumBytesPerBlock = 0; + switch (fmt) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + bc=true; + bcnumBytesPerBlock = 8; + break; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + bc = true; + bcnumBytesPerBlock = 16; + break; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + packed = true; + break; + } + + if( bc ) + { + int numBlocksWide = 0; + if( width > 0 ) + numBlocksWide = max( 1U, (width + 3) / 4 ); + int numBlocksHigh = 0; + if( height > 0 ) + numBlocksHigh = max( 1U, (height + 3) / 4 ); + rowBytes = numBlocksWide * bcnumBytesPerBlock; + numRows = numBlocksHigh; + } + else if ( packed ) + { + rowBytes = ( ( width + 1 ) >> 1 ) * 4; + numRows = height; + } + else + { + UINT bpp = BitsPerPixel( fmt ); + rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte + numRows = height; + } + + numBytes = rowBytes * numRows; + if( pNumBytes != NULL ) + *pNumBytes = numBytes; + if( pRowBytes != NULL ) + *pRowBytes = rowBytes; + if( pNumRows != NULL ) + *pNumRows = numRows; +} + + +//-------------------------------------------------------------------------------------- +#define ISBITMASK( r,g,b,a ) ( ddpf.dwRBitMask == r && ddpf.dwGBitMask == g && ddpf.dwBBitMask == b && ddpf.dwABitMask == a ) + +//-------------------------------------------------------------------------------------- +static D3DFORMAT GetD3D9Format( const DDS_PIXELFORMAT& ddpf ) +{ + if( ddpf.dwFlags & DDS_RGB ) + { + switch (ddpf.dwRGBBitCount) + { + case 32: + if( ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0xff000000) ) + return D3DFMT_A8R8G8B8; + if( ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000) ) + return D3DFMT_X8R8G8B8; + if( ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000) ) + return D3DFMT_A8B8G8R8; + if( ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) ) + return D3DFMT_X8B8G8R8; + + // Note that many common DDS reader/writers (including D3DX) swap the + // the RED/BLUE masks for 10:10:10:2 formats. We assumme + // below that the 'incorrect' header mask is being used + + // For 'correct' writers this should be 0x3ff00000,0x000ffc00,0x000003ff for BGR data + if( ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) ) + return D3DFMT_A2R10G10B10; + + // For 'correct' writers this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data + if( ISBITMASK(0x3ff00000,0x000ffc00,0x000003ff,0xc0000000) ) + return D3DFMT_A2B10G10R10; + + if( ISBITMASK(0x0000ffff,0xffff0000,0x00000000,0x00000000) ) + return D3DFMT_G16R16; + if( ISBITMASK(0xffffffff,0x00000000,0x00000000,0x00000000) ) + return D3DFMT_R32F; // D3DX writes this out as a FourCC of 114 + break; + + case 24: + if( ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000) ) + return D3DFMT_R8G8B8; + break; + + case 16: + if( ISBITMASK(0x0000f800,0x000007e0,0x0000001f,0x00000000) ) + return D3DFMT_R5G6B5; + if( ISBITMASK(0x00007c00,0x000003e0,0x0000001f,0x00008000) ) + return D3DFMT_A1R5G5B5; + if( ISBITMASK(0x00007c00,0x000003e0,0x0000001f,0x00000000) ) + return D3DFMT_X1R5G5B5; + if( ISBITMASK(0x00000f00,0x000000f0,0x0000000f,0x0000f000) ) + return D3DFMT_A4R4G4B4; + if( ISBITMASK(0x00000f00,0x000000f0,0x0000000f,0x00000000) ) + return D3DFMT_X4R4G4B4; + + // 3:3:2, 3:3:2:8, and paletted texture formats are typically not supported on modern video cards + break; + } + } + else if( ddpf.dwFlags & DDS_LUMINANCE ) + { + if( 8 == ddpf.dwRGBBitCount ) + { + if( ISBITMASK(0x0000000f,0x00000000,0x00000000,0x000000f0) ) + return D3DFMT_A4L4; + if( ISBITMASK(0x000000ff,0x00000000,0x00000000,0x00000000) ) + return D3DFMT_L8; + } + + if( 16 == ddpf.dwRGBBitCount ) + { + if( ISBITMASK(0x0000ffff,0x00000000,0x00000000,0x00000000) ) + return D3DFMT_L16; + if( ISBITMASK(0x000000ff,0x00000000,0x00000000,0x0000ff00) ) + return D3DFMT_A8L8; + } + } + else if( ddpf.dwFlags & DDS_ALPHA ) + { + if( 8 == ddpf.dwRGBBitCount ) + { + return D3DFMT_A8; + } + } + else if( ddpf.dwFlags & DDS_FOURCC ) + { + if( MAKEFOURCC( 'D', 'X', 'T', '1' ) == ddpf.dwFourCC ) + return D3DFMT_DXT1; + if( MAKEFOURCC( 'D', 'X', 'T', '2' ) == ddpf.dwFourCC ) + return D3DFMT_DXT2; + if( MAKEFOURCC( 'D', 'X', 'T', '3' ) == ddpf.dwFourCC ) + return D3DFMT_DXT3; + if( MAKEFOURCC( 'D', 'X', 'T', '4' ) == ddpf.dwFourCC ) + return D3DFMT_DXT4; + if( MAKEFOURCC( 'D', 'X', 'T', '5' ) == ddpf.dwFourCC ) + return D3DFMT_DXT5; + + if( MAKEFOURCC( 'R', 'G', 'B', 'G' ) == ddpf.dwFourCC ) + return D3DFMT_R8G8_B8G8; + if( MAKEFOURCC( 'G', 'R', 'G', 'B' ) == ddpf.dwFourCC ) + return D3DFMT_G8R8_G8B8; + + if( MAKEFOURCC( 'U', 'Y', 'V', 'Y' ) == ddpf.dwFourCC ) + return D3DFMT_UYVY; + if( MAKEFOURCC( 'Y', 'U', 'Y', '2' ) == ddpf.dwFourCC ) + return D3DFMT_YUY2; + + // Check for D3DFORMAT enums being set here + switch( ddpf.dwFourCC ) + { + case D3DFMT_A16B16G16R16: + case D3DFMT_Q16W16V16U16: + case D3DFMT_R16F: + case D3DFMT_G16R16F: + case D3DFMT_A16B16G16R16F: + case D3DFMT_R32F: + case D3DFMT_G32R32F: + case D3DFMT_A32B32G32R32F: + case D3DFMT_CxV8U8: + return (D3DFORMAT)ddpf.dwFourCC; + } + } + + return D3DFMT_UNKNOWN; +} + +//-------------------------------------------------------------------------------------- +DXGI_FORMAT GetDXGIFormat( const DDS_PIXELFORMAT& ddpf ) +{ + if( ddpf.dwFlags & DDS_RGB ) + { + switch (ddpf.dwRGBBitCount) + { + case 32: + // DXGI_FORMAT_B8G8R8A8_UNORM_SRGB & DXGI_FORMAT_B8G8R8X8_UNORM_SRGB should be + // written using the DX10 extended header instead since these formats require + // DXGI 1.1 + // + // This code will use the fallback to swizzle BGR to RGB in memory for standard + // DDS files which works on 10 and 10.1 devices with WDDM 1.0 drivers + // + // NOTE: We don't use DXGI_FORMAT_B8G8R8X8_UNORM or DXGI_FORMAT_B8G8R8X8_UNORM + // here because they were defined for DXGI 1.0 but were not required for D3D10/10.1 + + if( ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000) ) + return DXGI_FORMAT_R8G8B8A8_UNORM; + + // No D3DFMT_X8B8G8R8 in DXGI. We'll deal with it in a swizzle case to ensure + // alpha channel is 255 (don't care formats could contain garbage) + + // Note that many common DDS reader/writers (including D3DX) swap the + // the RED/BLUE masks for 10:10:10:2 formats. We assumme + // below that the 'backwards' header mask is being used since it is most + // likely written by D3DX. The more robust solution is to use the 'DX10' + // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly + + // For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data + if( ISBITMASK(0x3ff00000,0x000ffc00,0x000003ff,0xc0000000) ) + return DXGI_FORMAT_R10G10B10A2_UNORM; + + 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 + break; + + case 16: + // 5:5:5 & 5:6:5 formats are defined for DXGI, but are deprecated for D3D10, 10.0, and 11 + + // No 4bpp, 3:3:2, 3:3:2:8, or paletted DXGI formats + break; + } + } + else if( ddpf.dwFlags & DDS_LUMINANCE ) + { + if( 8 == ddpf.dwRGBBitCount ) + { + if( ISBITMASK(0x000000ff,0x00000000,0x00000000,0x00000000) ) + return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension + + // No 4bpp DXGI formats + } + + if( 16 == ddpf.dwRGBBitCount ) + { + 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.dwFlags & DDS_ALPHA ) + { + if( 8 == ddpf.dwRGBBitCount ) + { + return DXGI_FORMAT_A8_UNORM; + } + } + else if( ddpf.dwFlags & DDS_FOURCC ) + { + if( MAKEFOURCC( 'D', 'X', 'T', '1' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC1_UNORM; + if( MAKEFOURCC( 'D', 'X', 'T', '3' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC2_UNORM; + if( MAKEFOURCC( 'D', 'X', 'T', '5' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC3_UNORM; + + // While pre-mulitplied alpha isn't directly supported by the DXGI formats, + // they are basically the same as these BC formats so they can be mapped + if( MAKEFOURCC( 'D', 'X', 'T', '2' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC2_UNORM; + if( MAKEFOURCC( 'D', 'X', 'T', '4' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC3_UNORM; + + if( MAKEFOURCC( 'A', 'T', 'I', '1' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC4_UNORM; + if( MAKEFOURCC( 'B', 'C', '4', 'U' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC4_UNORM; + if( MAKEFOURCC( 'B', 'C', '4', 'S' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC4_SNORM; + + if( MAKEFOURCC( 'A', 'T', 'I', '2' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC5_UNORM; + if( MAKEFOURCC( 'B', 'C', '5', 'U' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC5_UNORM; + if( MAKEFOURCC( 'B', 'C', '5', 'S' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_BC5_SNORM; + + if( MAKEFOURCC( 'R', 'G', 'B', 'G' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_R8G8_B8G8_UNORM; + if( MAKEFOURCC( 'G', 'R', 'G', 'B' ) == ddpf.dwFourCC ) + return DXGI_FORMAT_G8R8_G8B8_UNORM; + + // Check for D3DFORMAT enums being set here + switch( ddpf.dwFourCC ) + { + case D3DFMT_A16B16G16R16: // 36 + return DXGI_FORMAT_R16G16B16A16_UNORM; + + case D3DFMT_Q16W16V16U16: // 110 + return DXGI_FORMAT_R16G16B16A16_SNORM; + + case D3DFMT_R16F: // 111 + return DXGI_FORMAT_R16_FLOAT; + + case D3DFMT_G16R16F: // 112 + return DXGI_FORMAT_R16G16_FLOAT; + + case D3DFMT_A16B16G16R16F: // 113 + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + case D3DFMT_R32F: // 114 + return DXGI_FORMAT_R32_FLOAT; + + case D3DFMT_G32R32F: // 115 + return DXGI_FORMAT_R32G32_FLOAT; + + case D3DFMT_A32B32G32R32F: // 116 + return DXGI_FORMAT_R32G32B32A32_FLOAT; + } + } + + return DXGI_FORMAT_UNKNOWN; +} + + +//-------------------------------------------------------------------------------------- +static HRESULT CreateTextureFromDDS( ID3D11Device* pDev, DDS_HEADER* pHeader, __inout_bcount(BitSize) BYTE* pBitData, + UINT BitSize, __out ID3D11ShaderResourceView** ppSRV, bool bSRGB ) +{ + HRESULT hr = S_OK; + + UINT iWidth = pHeader->dwWidth; + UINT iHeight = pHeader->dwHeight; + UINT iDepth = pHeader->dwDepth; + + UINT resDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + UINT arraySize = 1; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + bool isCubeMap = false; + + UINT iMipCount = pHeader->dwMipMapCount; + if( 0 == iMipCount ) + iMipCount = 1; + + bool swaprgb = false; + bool seta = false; + + if ((pHeader->ddspf.dwFlags & DDS_FOURCC) + && (MAKEFOURCC( 'D', 'X', '1', '0' ) == pHeader->ddspf.dwFourCC ) ) + { + DDS_HEADER_DXT10* d3d10ext = (DDS_HEADER_DXT10*)( (char*)pHeader + sizeof(DDS_HEADER) ); + + arraySize = d3d10ext->arraySize; + if ( arraySize == 0 ) + return HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + + if ( BitsPerPixel( d3d10ext->dxgiFormat ) == 0 ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + + format = d3d10ext->dxgiFormat; + + switch ( d3d10ext->resourceDimension ) + { + case DDS_DIMENSION_TEXTURE1D: + // D3DX writes 1D textures with a fixed Height of 1 + if ( (pHeader->dwFlags & DDS_HEIGHT) && iHeight != 1 ) + return HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + iHeight = iDepth = 1; + break; + + case DDS_DIMENSION_TEXTURE2D: + if ( d3d10ext->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE ) + { + arraySize *= 6; + isCubeMap = true; + } + iDepth = 1; + break; + + case DDS_DIMENSION_TEXTURE3D: + if ( !(pHeader->dwFlags & 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( pHeader->ddspf ); + + if ( pHeader->dwFlags & DDS_HEADER_FLAGS_VOLUME ) + { + resDim = DDS_DIMENSION_TEXTURE3D; + } + else + { + if ( pHeader->dwCaps2 & DDS_CUBEMAP ) + { + // We require all six faces to be defined + if ( (pHeader->dwCaps2 & DDS_CUBEMAP_ALLFACES ) != DDS_CUBEMAP_ALLFACES ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + + arraySize = 6; + isCubeMap = true; + } + + iDepth = 1; + resDim = DDS_DIMENSION_TEXTURE2D; + + // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture + } + + if ( format == DXGI_FORMAT_UNKNOWN ) + { + D3DFORMAT fmt = GetD3D9Format( pHeader->ddspf ); + + switch( fmt ) + { + case D3DFMT_X8R8G8B8: + format = DXGI_FORMAT_B8G8R8A8_UNORM; // NOTE: DXGI1.1 requirement is fine here + seta = true; + break; + + case D3DFMT_A8R8G8B8: + format = DXGI_FORMAT_B8G8R8A8_UNORM; // NOTE: DXGI1.1 requirement is fine here + break; + + case D3DFMT_X8B8G8R8: + format = DXGI_FORMAT_R8G8B8A8_UNORM; + seta = true; + break; + + case D3DFMT_A2R10G10B10: + format = DXGI_FORMAT_R10G10B10A2_UNORM; + swaprgb = TRUE; + break; + + // Would need temp memory to expand other formats (24bpp, 4bpp, 16-bit (5:6:5, 5:5:5, 5:5:5:1), 3:3:2, 3:3:2:8) + + default: + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + } + + assert( BitsPerPixel( format ) != 0 ); + } + + // Bound sizes + if ( iMipCount > D3D11_REQ_MIP_LEVELS ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + + switch ( resDim ) + { + case DDS_DIMENSION_TEXTURE1D: + if ( (arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D11_REQ_TEXTURE1D_U_DIMENSION) ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + break; + + case DDS_DIMENSION_TEXTURE2D: + if ( isCubeMap ) + { + // This is the right bound because we set arraySize to (NumCubes*6) above + if ( (arraySize > D3D11_REQ_TEXTURECUBE_DIMENSION) + || (iWidth > D3D11_REQ_TEXTURECUBE_DIMENSION) + || (iHeight > D3D11_REQ_TEXTURECUBE_DIMENSION)) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + else if ( (arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) + || (iHeight > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + { + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + break; + + case DDS_DIMENSION_TEXTURE3D: + if ( (arraySize > 1) + || (iWidth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iHeight > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iDepth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + break; + } + + + if ( bSRGB ) + format = MAKE_SRGB( format ); + + // Create the texture + D3D11_SUBRESOURCE_DATA* pInitData = new D3D11_SUBRESOURCE_DATA[ iMipCount * arraySize ]; + if( !pInitData ) + return E_OUTOFMEMORY; + + UINT NumBytes = 0; + UINT RowBytes = 0; + UINT NumRows = 0; + BYTE* pSrcBits = pBitData; + const BYTE *pEndBits = pBitData + BitSize; + + UINT index = 0; + for( UINT j = 0; j < arraySize; j++ ) + { + UINT w = iWidth; + UINT h = iHeight; + UINT d = iDepth; + for( UINT i = 0; i < iMipCount; i++ ) + { + GetSurfaceInfo( w, h, format, &NumBytes, &RowBytes, &NumRows ); + + pInitData[index].pSysMem = ( void* )pSrcBits; + pInitData[index].SysMemPitch = RowBytes; + pInitData[index].SysMemSlicePitch = NumBytes; + ++index; + + if ( pSrcBits + (NumBytes*d) > pEndBits ) + { + SAFE_DELETE_ARRAY( pInitData ); + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + if ( swaprgb || seta ) + { + switch( format ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + BYTE *sptr = pSrcBits; + for ( UINT slice = 0; slice < d; ++slice ) + { + BYTE *rptr = sptr; + for ( UINT row = 0; row < NumRows; ++row ) + { + BYTE *ptr = rptr; + for( UINT x = 0; x < w; ++x, ptr += 4 ) + { + if ( ptr + 4 <= pEndBits ) + { + if ( swaprgb ) + { + BYTE a = ptr[0]; + ptr[0] = ptr[2]; + ptr[2] = a; + } + if ( seta ) + ptr[3] = 255; + } + } + rptr += RowBytes; + } + sptr += NumBytes; + } + } + break; + + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + BYTE *sptr = pSrcBits; + for ( UINT slice = 0; slice < d; ++slice ) + { + const BYTE *rptr = sptr; + for ( UINT row = 0; row < NumRows; ++row ) + { + DWORD *ptr = (DWORD*)rptr; + for( UINT x = 0; x < w; ++x, ++ptr ) + { + if ( ptr + 1 <= (DWORD*)pEndBits ) + { + DWORD t = *ptr; + DWORD u = (t & 0x3ff00000) >> 20; + DWORD v = (t & 0x000003ff) << 20; + *ptr = ( t & ~0x3ff003ff ) | u | v; + } + } + rptr += RowBytes; + } + sptr += NumBytes; + } + } + break; + } + } + + 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; + } + } + + switch ( resDim ) + { + case DDS_DIMENSION_TEXTURE1D: + { + D3D11_TEXTURE1D_DESC desc; + desc.Width = iWidth; + desc.MipLevels = iMipCount; + desc.ArraySize = arraySize; + desc.Format = format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + ID3D11Texture1D* pTex = NULL; + hr = pDev->CreateTexture1D( &desc, pInitData, &pTex ); + if( SUCCEEDED( hr ) && pTex ) + { +#if defined(DEBUG) || defined(PROFILE) + pTex->SetPrivateData( WKPDID_D3DDebugObjectName, sizeof("DDSTextureLoader")-1, "DDSTextureLoader" ); +#endif + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + memset( &SRVDesc, 0, sizeof( SRVDesc ) ); + SRVDesc.Format = format; + + if ( arraySize > 1 ) + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY; + SRVDesc.Texture1DArray.MipLevels = desc.MipLevels; + SRVDesc.Texture1DArray.ArraySize = arraySize; + } + else + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D; + SRVDesc.Texture1D.MipLevels = desc.MipLevels; + } + + hr = pDev->CreateShaderResourceView( pTex, &SRVDesc, ppSRV ); + SAFE_RELEASE( pTex ); + } + } + break; + + case DDS_DIMENSION_TEXTURE2D: + { + D3D11_TEXTURE2D_DESC desc; + desc.Width = iWidth; + desc.Height = iHeight; + desc.MipLevels = iMipCount; + desc.ArraySize = arraySize; + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = (isCubeMap) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0; + + ID3D11Texture2D* pTex = NULL; + hr = pDev->CreateTexture2D( &desc, pInitData, &pTex ); + if( SUCCEEDED( hr ) && pTex ) + { +#if defined(DEBUG) || defined(PROFILE) + pTex->SetPrivateData( WKPDID_D3DDebugObjectName, sizeof("DDSTextureLoader")-1, "DDSTextureLoader" ); +#endif + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + memset( &SRVDesc, 0, sizeof( SRVDesc ) ); + SRVDesc.Format = format; + + if ( isCubeMap ) + { + if ( arraySize > 6 ) + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY; + SRVDesc.TextureCubeArray.MipLevels = desc.MipLevels; + + // Earlier we set arraySize to (NumCubes * 6) + SRVDesc.TextureCubeArray.NumCubes = arraySize / 6; + } + else + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE; + SRVDesc.TextureCube.MipLevels = desc.MipLevels; + } + } + else if ( arraySize > 1 ) + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY; + SRVDesc.Texture2DArray.MipLevels = desc.MipLevels; + SRVDesc.Texture2DArray.ArraySize = arraySize; + } + else + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MipLevels = desc.MipLevels; + } + + hr = pDev->CreateShaderResourceView( pTex, &SRVDesc, ppSRV ); + SAFE_RELEASE( pTex ); + } + } + break; + + case DDS_DIMENSION_TEXTURE3D: + { + D3D11_TEXTURE3D_DESC desc; + desc.Width = iWidth; + desc.Height = iHeight; + desc.Depth = iDepth; + desc.MipLevels = iMipCount; + desc.Format = format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + ID3D11Texture3D* pTex = NULL; + hr = pDev->CreateTexture3D( &desc, pInitData, &pTex ); + if( SUCCEEDED( hr ) && pTex ) + { +#if defined(DEBUG) || defined(PROFILE) + pTex->SetPrivateData( WKPDID_D3DDebugObjectName, sizeof("DDSTextureLoader")-1, "DDSTextureLoader" ); +#endif + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + memset( &SRVDesc, 0, sizeof( SRVDesc ) ); + SRVDesc.Format = format; + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D; + SRVDesc.Texture3D.MipLevels = desc.MipLevels; + + hr = pDev->CreateShaderResourceView( pTex, &SRVDesc, ppSRV ); + SAFE_RELEASE( pTex ); + } + } + break; + } + + SAFE_DELETE_ARRAY( pInitData ); + + return hr; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CreateDDSTextureFromFile( __in ID3D11Device* pDev, __in_z const WCHAR* szFileName, __out_opt ID3D11ShaderResourceView** ppSRV, bool sRGB ) +{ + if ( !pDev || !szFileName || !ppSRV ) + return E_INVALIDARG; + + BYTE* pHeapData = NULL; + DDS_HEADER* pHeader = NULL; + BYTE* pBitData = NULL; + UINT BitSize = 0; + + HRESULT hr = LoadTextureDataFromFile( szFileName, &pHeapData, &pHeader, &pBitData, &BitSize ); + if(FAILED(hr)) + { + SAFE_DELETE_ARRAY( pHeapData ); + return hr; + } + + hr = CreateTextureFromDDS( pDev, pHeader, pBitData, BitSize, ppSRV, sRGB ); + SAFE_DELETE_ARRAY( pHeapData ); + +#if defined(DEBUG) || defined(PROFILE) + if ( *ppSRV ) + { + CHAR strFileA[MAX_PATH]; + WideCharToMultiByte( CP_ACP, 0, szFileName, -1, strFileA, MAX_PATH, NULL, FALSE ); + CHAR* pstrName = strrchr( strFileA, '\\' ); + if( pstrName == NULL ) + pstrName = strFileA; + else + pstrName++; + + (*ppSRV)->SetPrivateData( WKPDID_D3DDebugObjectName, lstrlenA(pstrName), pstrName ); + } +#endif + + return hr; +} diff --git a/Projects/Asteroids/src/DDSTextureLoader.h b/Projects/Asteroids/src/DDSTextureLoader.h new file mode 100644 index 0000000..5bca4c6 --- /dev/null +++ b/Projects/Asteroids/src/DDSTextureLoader.h @@ -0,0 +1,18 @@ +//-------------------------------------------------------------------------------------- +// File: DDSTextureLoader.h +// +// Functions for loading a DDS texture without using D3DX +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "DDS.h" +#include <d3d11.h> + +HRESULT CreateDDSTextureFromFile( __in ID3D11Device* pDev, __in_z const WCHAR* szFileName, __out_opt ID3D11ShaderResourceView** ppSRV, bool sRGB = false ); + +// INTEL: Exposed this from the internals so we can load the data into D3D12, etc. +DXGI_FORMAT GetDXGIFormat( const DDS_PIXELFORMAT& ddpf ); +HRESULT LoadTextureDataFromFile(__in_z const WCHAR* szFileName, BYTE** ppHeapData, + DDS_HEADER** ppHeader, + BYTE** ppBitData, UINT* pBitSize); diff --git a/Projects/Asteroids/src/WinWrapper.cpp b/Projects/Asteroids/src/WinWrapper.cpp new file mode 100644 index 0000000..ffb0f6d --- /dev/null +++ b/Projects/Asteroids/src/WinWrapper.cpp @@ -0,0 +1,616 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#define WIN32_LEAN_AND_MEAN +#include <sdkddkver.h> +#include <windows.h> +#include <windowsx.h> +#include <shellapi.h> // must be after windows.h +#include <ShellScalingApi.h> +#include <interactioncontext.h> +#include <mmsystem.h> +#include <map> +#include <vector> +#include <iostream> + +#include "asteroids_d3d11.h" +#include "asteroids_d3d12.h" +#include "asteroids_DE.h" +#include "camera.h" +#include "gui.h" + +using namespace DirectX; + +namespace { + +// Global demo state +Settings gSettings; +OrbitCamera gCamera; + +IDXGIFactory2* gDXGIFactory = nullptr; + +AsteroidsD3D11::Asteroids* gWorkloadD3D11 = nullptr; +AsteroidsD3D12::Asteroids* gWorkloadD3D12 = nullptr; +AsteroidsDE::Asteroids* gWorkloadDE = nullptr; +bool gd3d11Available = false; +bool gd3d12Available = false; +Settings::RenderMode gLastFrameRenderMode = static_cast<Settings::RenderMode>(-1); + +GUI gGUI; +GUIText* gFPSControl; + +enum +{ + basicStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE, + windowedStyle = basicStyle | WS_OVERLAPPEDWINDOW, + fullscreenStyle = basicStyle +}; + +bool CheckDll(char const* dllName) +{ + auto hModule = LoadLibrary(dllName); + if (hModule == NULL) { + return false; + } + FreeLibrary(hModule); + return true; +} + + +UINT SetupDPI() +{ + // Just do system DPI awareness for now for simplicity... scale the 3D content + SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE); + + UINT dpiX = 0, dpiY; + POINT pt = {1, 1}; + auto hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) { + return dpiX; + } else { + return 96; // default + } +} + + +void ResetCameraView() +{ + auto center = XMVectorSet(0.0f, -0.4f*SIM_DISC_RADIUS, 0.0f, 0.0f); + auto radius = SIM_ORBIT_RADIUS + SIM_DISC_RADIUS + 10.f; + auto minRadius = SIM_ORBIT_RADIUS - 3.0f * SIM_DISC_RADIUS; + auto maxRadius = SIM_ORBIT_RADIUS + 3.0f * SIM_DISC_RADIUS; + auto longAngle = 4.50f; + auto latAngle = 1.45f; + gCamera.View(center, radius, minRadius, maxRadius, longAngle, latAngle); +} + +void ToggleFullscreen(HWND hWnd) +{ + static WINDOWPLACEMENT prevPlacement = { sizeof(prevPlacement) }; + DWORD dwStyle = (DWORD)GetWindowLongPtr(hWnd, GWL_STYLE); + if ((dwStyle & windowedStyle) == windowedStyle) + { + MONITORINFO mi = { sizeof(mi) }; + if (GetWindowPlacement(hWnd, &prevPlacement) && + GetMonitorInfo(MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY), &mi)) + { + SetWindowLong(hWnd, GWL_STYLE, fullscreenStyle); + SetWindowPos(hWnd, HWND_TOP, + mi.rcMonitor.left, mi.rcMonitor.top, + mi.rcMonitor.right - mi.rcMonitor.left, + mi.rcMonitor.bottom - mi.rcMonitor.top, + SWP_NOOWNERZORDER | SWP_FRAMECHANGED); + } + } else { + SetWindowLong(hWnd, GWL_STYLE, windowedStyle); + SetWindowPlacement(hWnd, &prevPlacement); + SetWindowPos(hWnd, NULL, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | + SWP_NOOWNERZORDER | SWP_FRAMECHANGED); + } +} + + +} // namespace + + + +LRESULT CALLBACK WindowProc( + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + switch (message) { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + case WM_SIZE: { + UINT ww = LOWORD(lParam); + UINT wh = HIWORD(lParam); + + // Ignore resizing to minimized + if (ww == 0 || wh == 0) return 0; + + gSettings.windowWidth = (int)ww; + gSettings.windowHeight = (int)wh; + gSettings.renderWidth = (UINT)(double(gSettings.windowWidth) * gSettings.renderScale); + gSettings.renderHeight = (UINT)(double(gSettings.windowHeight) * gSettings.renderScale); + + // Update camera projection + float aspect = (float)gSettings.renderWidth / (float)gSettings.renderHeight; + gCamera.Projection(XM_PIDIV2 * 0.8f * 3 / 2, aspect); + + // Resize currently active swap chain + switch (gSettings.mode) + { + case Settings::RenderMode::NativeD3D11: + if(gWorkloadD3D11) + gWorkloadD3D11->ResizeSwapChain(gDXGIFactory, hWnd, gSettings.renderWidth, gSettings.renderHeight); + break; + + case Settings::RenderMode::NativeD3D12: + if(gWorkloadD3D12) + gWorkloadD3D12->ResizeSwapChain(gDXGIFactory, hWnd, gSettings.renderWidth, gSettings.renderHeight); + break; + + case Settings::RenderMode::DiligentD3D11: + case Settings::RenderMode::DiligentD3D12: + case Settings::RenderMode::DiligentGL: + if(gWorkloadDE) + gWorkloadDE->ResizeSwapChain(hWnd, gSettings.renderWidth, gSettings.renderHeight); + break; + } + + return 0; + } + + case WM_KEYDOWN: + if (lParam & (1 << 30)) { + // Ignore repeats + return 0; + } + switch (wParam) { + case VK_SPACE: + gSettings.animate = !gSettings.animate; + std::cout << "Animate: " << gSettings.animate << std::endl; + return 0; + + /* Disabled for demo setup */ + case 'V': + gSettings.vsync = !gSettings.vsync; + std::cout << "Vsync: " << gSettings.vsync << std::endl; + return 0; + case 'M': + gSettings.multithreadedRendering = !gSettings.multithreadedRendering; + std::cout << "Multithreaded Rendering: " << gSettings.multithreadedRendering << std::endl; + return 0; + case 'I': + gSettings.executeIndirect = !gSettings.executeIndirect; + std::cout << "ExecuteIndirect Rendering: " << gSettings.executeIndirect << std::endl; + return 0; + case 'S': + gSettings.submitRendering = !gSettings.submitRendering; + std::cout << "Submit Rendering: " << gSettings.submitRendering << std::endl; + return 0; + + case VK_ADD: + case VK_OEM_PLUS: + gSettings.numThreads = std::min(gSettings.numThreads+1, 16); + gLastFrameRenderMode = static_cast<Settings::RenderMode>(-1); + return 0; + case VK_SUBTRACT: + case VK_OEM_MINUS: + gSettings.numThreads = std::max(gSettings.numThreads-1, 2); + gLastFrameRenderMode = static_cast<Settings::RenderMode>(-1); + return 0; + + case '1': gSettings.mode = gd3d11Available ? Settings::RenderMode::NativeD3D11 : gSettings.mode; return 0; + case '2': gSettings.mode = gd3d12Available ? Settings::RenderMode::NativeD3D12 : gSettings.mode; return 0; + case '3': gSettings.mode = gd3d11Available ? Settings::RenderMode::DiligentD3D11 : gSettings.mode; return 0; + case '4': gSettings.mode = gd3d12Available ? Settings::RenderMode::DiligentD3D12 : gSettings.mode; return 0; + case '5': gSettings.mode = Settings::RenderMode::DiligentGL; return 0; + + case VK_ESCAPE: + SendMessage(hWnd, WM_CLOSE, 0, 0); + return 0; + } // Switch on key code + return 0; + + case WM_SYSKEYDOWN: + if (lParam & (1 << 30)) { + // Ignore repeats + return 0; + } + switch (wParam) { + case VK_RETURN: + ToggleFullscreen(hWnd); + break; + } + return 0; + + case WM_MOUSEWHEEL: { + auto delta = GET_WHEEL_DELTA_WPARAM(wParam); + gCamera.ZoomRadius(-0.07f * delta); + return 0; + } + + case WM_POINTERDOWN: + case WM_POINTERUPDATE: + case WM_POINTERUP: { + auto pointerId = GET_POINTERID_WPARAM(wParam); + POINTER_INFO pointerInfo; + if (GetPointerInfo(pointerId, &pointerInfo)) { + if (message == WM_POINTERDOWN) { + // Compute pointer position in render units + POINT p = pointerInfo.ptPixelLocation; + ScreenToClient(hWnd, &p); + RECT clientRect; + GetClientRect(hWnd, &clientRect); + p.x = p.x * gSettings.renderWidth / (clientRect.right - clientRect.left); + p.y = p.y * gSettings.renderHeight / (clientRect.bottom - clientRect.top); + + auto guiControl = gGUI.HitTest(p.x, p.y); + if (guiControl == gFPSControl) { + gSettings.lockFrameRate = !gSettings.lockFrameRate; + } else { // Camera manipulation + gCamera.AddPointer(pointerId); + } + } + + // Otherwise send it to the camera controls + gCamera.ProcessPointerFrames(pointerId, &pointerInfo); + if (message == WM_POINTERUP) gCamera.RemovePointer(pointerId); + } + return 0; + } + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } +} + +int InitWorkload(HWND hWnd, AsteroidsSimulation &asteroids) +{ + delete gWorkloadD3D11; + gWorkloadD3D11 = nullptr; + delete gWorkloadD3D12; + gWorkloadD3D12 = nullptr; + delete gWorkloadDE; + gWorkloadDE = nullptr; + switch (gSettings.mode) + { + case Settings::RenderMode::NativeD3D11: + if (gd3d11Available) { + gWorkloadD3D11 = new AsteroidsD3D11::Asteroids(&asteroids, &gGUI, gSettings.warp); + } + + gWorkloadD3D11->ResizeSwapChain(gDXGIFactory, hWnd, gSettings.renderWidth, gSettings.renderHeight); + break; + + case Settings::RenderMode::NativeD3D12: + if (gd3d12Available) { + // If requested, enumerate the warp adapter + // TODO: Allow picking from multiple hardware adapters + IDXGIAdapter1* adapter = nullptr; + + if (gSettings.warp) { + IDXGIFactory4* DXGIFactory4 = nullptr; + if (FAILED(gDXGIFactory->QueryInterface(&DXGIFactory4))) { + fprintf(stderr, "error: WARP requires IDXGIFactory4 interface which is not present on this system!\n"); + return -1; + } + + auto hr = DXGIFactory4->EnumWarpAdapter(IID_PPV_ARGS(&adapter)); + DXGIFactory4->Release(); + + if (FAILED(hr)) { + fprintf(stderr, "error: WARP adapter not present on this system!\n"); + return -1; + } + } + + gWorkloadD3D12 = new AsteroidsD3D12::Asteroids(&asteroids, &gGUI, gSettings.numThreads, adapter); + } + + gWorkloadD3D12->ResizeSwapChain(gDXGIFactory, hWnd, gSettings.renderWidth, gSettings.renderHeight); + break; + + case Settings::RenderMode::DiligentD3D11: + gWorkloadDE = new AsteroidsDE::Asteroids(gSettings.numThreads, &asteroids, &gGUI, hWnd, Diligent::DeviceType::D3D11); + break; + + case Settings::RenderMode::DiligentD3D12: + gWorkloadDE = new AsteroidsDE::Asteroids(gSettings.numThreads, &asteroids, &gGUI, hWnd, Diligent::DeviceType::D3D12); + break; + + case Settings::RenderMode::DiligentGL: + gWorkloadDE = new AsteroidsDE::Asteroids(gSettings.numThreads, &asteroids, &gGUI, hWnd, Diligent::DeviceType::OpenGL); + break; + } + + return 0; +} + +int main(int argc, char** argv) +{ +#if defined(_DEBUG) || defined(DEBUG) + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); +#endif + + gd3d11Available = CheckDll("d3d11.dll"); + gd3d12Available = CheckDll("d3d12.dll"); + + // Must be done before any windowing-system-like things or else virtualization will kick in + auto dpi = SetupDPI(); + // By default render at the lower resolution and scale up based on system settings + gSettings.renderScale = 96.0 / double(dpi); + + // Scale default window size based on dpi + gSettings.windowWidth *= dpi / 96; + gSettings.windowHeight *= dpi / 96; + + for (int a = 1; a < argc; ++a) { + if (_stricmp(argv[a], "-close_after") == 0 && a + 1 < argc) { + gSettings.closeAfterSeconds = atof(argv[++a]); + } else if (_stricmp(argv[a], "-nod3d11") == 0) { + gd3d11Available = false; + } else if (_stricmp(argv[a], "-warp") == 0) { + gSettings.warp = true; + } else if (_stricmp(argv[a], "-nod3d12") == 0) { + gd3d12Available = false; + } else if (_stricmp(argv[a], "-indirect") == 0) { + gSettings.executeIndirect = true; + } else if (_stricmp(argv[a], "-fullscreen") == 0) { + gSettings.windowed = false; + } else if (_stricmp(argv[a], "-window") == 0 && a + 2 < argc) { + gSettings.windowWidth = atoi(argv[++a]); + gSettings.windowHeight = atoi(argv[++a]); + } else if (_stricmp(argv[a], "-render_scale") == 0 && a + 1 < argc) { + gSettings.renderScale = atof(argv[++a]); + } else if (_stricmp(argv[a], "-locked_fps") == 0 && a + 1 < argc) { + gSettings.lockedFrameRate = atoi(argv[++a]); + } else if (_stricmp(argv[a], "-threads") == 0 && a + 1 < argc) { + gSettings.numThreads = atoi(argv[++a]); + } else { + fprintf(stderr, "error: unrecognized argument '%s'\n", argv[a]); + fprintf(stderr, "usage: asteroids_d3d12 [options]\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -close_after [seconds]\n"); + fprintf(stderr, " -nod3d11\n"); + fprintf(stderr, " -nod3d12\n"); + fprintf(stderr, " -fullscreen\n"); + fprintf(stderr, " -window [width] [height]\n"); + fprintf(stderr, " -render_scale [scale]\n"); + fprintf(stderr, " -locked_fps [fps]\n"); + fprintf(stderr, " -warp\n"); + return -1; + } + } + + if (gSettings.numThreads == 0) + { + gSettings.numThreads = std::max(std::thread::hardware_concurrency()-1, 2u); + } + + //if (!d3d11Available && !d3d12Available) { + // fprintf(stderr, "error: neither D3D11 nor D3D12 available.\n"); + // return -1; + //} + + // DXGI Factory + ThrowIfFailed(CreateDXGIFactory2(0, IID_PPV_ARGS(&gDXGIFactory))); + + // Setup GUI + gFPSControl = gGUI.AddText(150, 10); + + ResetCameraView(); + // Camera projection set up in WM_SIZE + + AsteroidsSimulation asteroids(1337, NUM_ASTEROIDS, NUM_UNIQUE_MESHES, MESH_MAX_SUBDIV_LEVELS, NUM_UNIQUE_TEXTURES); + + + gSettings.mode = Settings::RenderMode::DiligentD3D12; + + + // init window class + WNDCLASSEX windowClass; + ZeroMemory(&windowClass, sizeof(WNDCLASSEX)); + windowClass.cbSize = sizeof(WNDCLASSEX); + windowClass.style = CS_HREDRAW | CS_VREDRAW; + windowClass.lpfnWndProc = WindowProc; + windowClass.hInstance = GetModuleHandle(NULL); + windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); + windowClass.lpszClassName = "AsteroidsD3D12WindowClass"; + RegisterClassEx(&windowClass); + + RECT windowRect = { 0, 0, gSettings.windowWidth, gSettings.windowHeight }; + AdjustWindowRect(&windowRect, windowedStyle, FALSE); + + // create the window and store a handle to it + auto hWnd = CreateWindowEx( + WS_EX_APPWINDOW, + "AsteroidsD3D12WindowClass", + "Asteroids", + windowedStyle, + 0, // CW_USE_DEFAULT + 0, // CW_USE_DEFAULT + windowRect.right - windowRect.left, + windowRect.bottom - windowRect.top, + NULL, + NULL, + windowClass.hInstance, + NULL); + + if (!gSettings.windowed) { + ToggleFullscreen(hWnd); + } + + SetForegroundWindow(hWnd); + + // Initialize performance counters + UINT64 perfCounterFreq = 0; + UINT64 lastPerfCount = 0; + QueryPerformanceFrequency((LARGE_INTEGER*)&perfCounterFreq); + QueryPerformanceCounter((LARGE_INTEGER*)&lastPerfCount); + + // main loop + double elapsedTime = 0.0; + double frameTime = 0.0; + int lastMouseX = 0; + int lastMouseY = 0; + POINTER_INFO pointerInfo = {}; + + timeBeginPeriod(1); + EnableMouseInPointer(TRUE); + + float filteredUpdateTime = 0.0f; + float filteredRenderTime = 0.0f; + float filteredFrameTime = 0.0f; + for (;;) + { + MSG msg = {}; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) { + // Cleanup + delete gWorkloadD3D11; + delete gWorkloadD3D12; + delete gWorkloadDE; + SafeRelease(&gDXGIFactory); + timeEndPeriod(1); + EnableMouseInPointer(FALSE); + return (int)msg.wParam; + }; + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + // If we swap to a new API we need to recreate swap chains + if (gLastFrameRenderMode != gSettings.mode) { + InitWorkload(hWnd, asteroids); + gLastFrameRenderMode = gSettings.mode; + } + + // Still need to process inertia even when no interaction is happening + gCamera.ProcessInertia(); + + // In D3D12 we'll wait on the GPU before taking the timestamp (more consistent) + if (gSettings.mode == Settings::RenderMode::NativeD3D12) { + gWorkloadD3D12->WaitForReadyToRender(); + } + + // Get time delta + UINT64 count; + QueryPerformanceCounter((LARGE_INTEGER*)&count); + auto rawFrameTime = (double)(count - lastPerfCount) / perfCounterFreq; + elapsedTime += rawFrameTime; + lastPerfCount = count; + + // Maintaining absolute time sync is not important in this demo so we can err on the "smoother" side + double alpha = 0.2f; + frameTime = alpha * rawFrameTime + (1.0f - alpha) * frameTime; + + // Update GUI + { + const char *ModeStr = nullptr; + float updateTime = 0; + float renderTime = 0; + switch (gSettings.mode) + { + case Settings::RenderMode::NativeD3D11: + ModeStr = "Native D3D11"; + gWorkloadD3D11->GetPerfCounters(updateTime, renderTime); + break; + + case Settings::RenderMode::NativeD3D12: + ModeStr = "Native D3D12"; + gWorkloadD3D12->GetPerfCounters(updateTime, renderTime); + break; + + case Settings::RenderMode::DiligentD3D11: + ModeStr = "Diligent D3D11"; + gWorkloadDE->GetPerfCounters(updateTime, renderTime); + break; + + case Settings::RenderMode::DiligentD3D12: + ModeStr = "Diligent D3D12"; + gWorkloadDE->GetPerfCounters(updateTime, renderTime); + break; + + case Settings::RenderMode::DiligentGL: + ModeStr = "Diligent GL"; + gWorkloadDE->GetPerfCounters(updateTime, renderTime); + break; + } + float filterScale = 0.05f; + filteredUpdateTime = filteredUpdateTime * (1.f - filterScale) + filterScale * updateTime; + filteredRenderTime = filteredRenderTime * (1.f - filterScale) + filterScale * renderTime; + filteredFrameTime = filteredFrameTime * (1.f - filterScale) + filterScale * (float)frameTime; + + char buffer[256]; + sprintf(buffer, "Asteroids %s (%dt) - %4.2f ms (%4.2f ms / %4.2f ms)", ModeStr, gSettings.multithreadedRendering ? gSettings.numThreads : 1, + 1000.f * filteredFrameTime, 1000.f * filteredUpdateTime, 1000.f * filteredRenderTime); + + SetWindowText(hWnd, buffer); + + if (gSettings.lockFrameRate) { + sprintf(buffer, "(Locked)"); + } else { + sprintf(buffer, "%.0f fps", 1.0f / filteredFrameTime); + } + gFPSControl->Text(buffer); + } + + switch (gSettings.mode) + { + case Settings::RenderMode::NativeD3D11: + if(gWorkloadD3D11) + gWorkloadD3D11->Render((float)frameTime, gCamera, gSettings); + break; + + case Settings::RenderMode::NativeD3D12: + if(gWorkloadD3D12) + gWorkloadD3D12->Render((float)frameTime, gCamera, gSettings); + break; + + case Settings::RenderMode::DiligentD3D11: + case Settings::RenderMode::DiligentD3D12: + case Settings::RenderMode::DiligentGL: + if(gWorkloadDE) + gWorkloadDE->Render((float)frameTime, gCamera, gSettings); + break; + } + + if (gSettings.lockFrameRate) { + + UINT64 afterRenderCount; + QueryPerformanceCounter((LARGE_INTEGER*)&afterRenderCount); + double renderTime = (double)(afterRenderCount - count) / perfCounterFreq; + + double targetRenderTime = 1.0 / double(gSettings.lockedFrameRate); + double deltaMs = (targetRenderTime - renderTime) * 1000.0; + if (deltaMs > 1.0) { + Sleep((DWORD)deltaMs); + } + + } + + // All done? + if (gSettings.closeAfterSeconds > 0.0 && elapsedTime > gSettings.closeAfterSeconds) { + SendMessage(hWnd, WM_CLOSE, 0, 0); + break; + } + } + + // Shouldn't get here + return 1; +} diff --git a/Projects/Asteroids/src/asteroid_ps.hlsl b/Projects/Asteroids/src/asteroid_ps.hlsl new file mode 100644 index 0000000..c645486 --- /dev/null +++ b/Projects/Asteroids/src/asteroid_ps.hlsl @@ -0,0 +1,50 @@ +#include "asteroid_vs.hlsl" +#include "common_defines.h" + +// Apparently tools don't like unbounded/bindless texture arrays, so use the real constant for now +Texture2DArray<float4> Tex[NUM_UNIQUE_TEXTURES] : register(t0); +sampler Sampler : register(s0); + +float4 asteroid_ps(in float4 position : SV_Position, + in VSOut vs_output) : SV_Target +{ + // Tweaking + float3 lightPos = float3(0.5, -0.25, -1); + bool applyNoise = true; + bool applyLight = true; + bool applyCoverage = true; + + float3 normal = normalize(vs_output.normalWorld); + + // Triplanar projection + float3 blendWeights = abs(normalize(vs_output.positionModel)); + float3 uvw = vs_output.positionModel * 0.5f + 0.5f; + // Tighten up the blending zone + blendWeights = saturate((blendWeights - 0.2f) * 7.0f); + blendWeights /= (blendWeights.x + blendWeights.y + blendWeights.z).xxx; + + float3 coords1 = float3(uvw.yz, 0); + float3 coords2 = float3(uvw.zx, 1); + float3 coords3 = float3(uvw.xy, 2); + + // TODO: Should really branch out zero'd weight ones, but FXC is being a pain + // and forward substituting the above and then refusing to compile "divergent" + // coordinates... + float3 detailTex = 0.0f; + detailTex += blendWeights.x * Tex[mTextureIndex].Sample(Sampler, coords1).xyz; + detailTex += blendWeights.y * Tex[mTextureIndex].Sample(Sampler, coords2).xyz; + detailTex += blendWeights.z * Tex[mTextureIndex].Sample(Sampler, coords3).xyz; + + float wrap = 0.0f; + float wrap_diffuse = saturate((dot(normal, normalize(lightPos)) + wrap) / (1.0f + wrap)); + float light = 3.0f * wrap_diffuse + 0.06f; + + // Approximate partial coverage on distant asteroids (by fading them out) + float coverage = saturate(position.z * 4000.0f); + + float3 color = vs_output.albedo; + [flatten] if (applyNoise) color = color * (2.0f * detailTex); + [flatten] if (applyLight) color = color * light; + [flatten] if (applyCoverage) color = color * coverage; + return float4(color, 1.0f); +} diff --git a/Projects/Asteroids/src/asteroid_ps_d3d11.hlsl b/Projects/Asteroids/src/asteroid_ps_d3d11.hlsl new file mode 100644 index 0000000..69ebc33 --- /dev/null +++ b/Projects/Asteroids/src/asteroid_ps_d3d11.hlsl @@ -0,0 +1,56 @@ +#include "common_defines.h" + +struct VSOut +{ + float3 positionModel : POSITIONMODEL; + float3 normalWorld : NORMAL; + float3 albedo : ALBEDO; // Alternatively, can pass just "ao" to PS and read cbuffer in PS +}; + +Texture2DArray<float4> Tex;// : register(t0); +SamplerState Tex_sampler;// : register(s0); + +void asteroid_ps_d3d11(in float4 position : SV_Position, + in VSOut vs_output, + out float4 color : SV_Target) +{ + // Tweaking + float3 lightPos = float3(0.5, -0.25, -1); + bool applyNoise = true; + bool applyLight = true; + bool applyCoverage = true; + + float3 normal = normalize(vs_output.normalWorld); + + // Triplanar projection + float3 blendWeights = abs(normalize(vs_output.positionModel)); + float3 uvw = vs_output.positionModel * 0.5f + 0.5f; + // Tighten up the blending zone + blendWeights = saturate((blendWeights - 0.2f) * 7.0f); + blendWeights /= (blendWeights.x + blendWeights.y + blendWeights.z).xxx; + + float3 coords1 = float3(uvw.yz, 0); + float3 coords2 = float3(uvw.zx, 1); + float3 coords3 = float3(uvw.xy, 2); + + // TODO: Should really branch out zero'd weight ones, but FXC is being a pain + // and forward substituting the above and then refusing to compile "divergent" + // coordinates... + float3 detailTex = float3(0.0, 0.0, 0.0); + detailTex += blendWeights.x * Tex.Sample(Tex_sampler, coords1).xyz; + detailTex += blendWeights.y * Tex.Sample(Tex_sampler, coords2).xyz; + detailTex += blendWeights.z * Tex.Sample(Tex_sampler, coords3).xyz; + + float wrap = 0.0f; + float wrap_diffuse = saturate((dot(normal, normalize(lightPos)) + wrap) / (1.0f + wrap)); + float light = 3.0f * wrap_diffuse + 0.06f; + + // Approximate partial coverage on distant asteroids (by fading them out) + float coverage = saturate(position.z * 4000.0f); + + color.rgb = vs_output.albedo.rgb; + [flatten] if (applyNoise) color.rgb = color.rgb * (2.0f * detailTex); + [flatten] if (applyLight) color.rgb = color.rgb * light; + [flatten] if (applyCoverage) color.rgb = color.rgb * coverage; + color.a = 1.0; +} diff --git a/Projects/Asteroids/src/asteroid_vs.hlsl b/Projects/Asteroids/src/asteroid_vs.hlsl new file mode 100644 index 0000000..772137c --- /dev/null +++ b/Projects/Asteroids/src/asteroid_vs.hlsl @@ -0,0 +1,36 @@ +cbuffer DrawConstantBuffer// : register(b0) +{ + float4x4 mWorld; + float4x4 mViewProjection; + float4 mSurfaceColor; + float4 mDeepColor; + uint mTextureIndex; +}; + +struct VSOut +{ + float3 positionModel : POSITIONMODEL; + float3 normalWorld : NORMAL; + float3 albedo : ALBEDO; // Alternatively, can pass just "ao" to PS and read cbuffer in PS +}; + +float linstep(float min, float max, float s) +{ + return saturate((s - min) / (max - min)); +} + + +void asteroid_vs(in float3 in_pos : ATTRIB0, + in float3 in_normal : ATTRIB1, + out float4 position : SV_Position, + out VSOut vs_output) +{ + float3 positionWorld = mul(mWorld, float4(in_pos, 1.0f)).xyz; + position = mul(mViewProjection, float4(positionWorld, 1.0f)); + + vs_output.positionModel = in_pos; + vs_output.normalWorld = mul(mWorld, float4(in_normal, 0.0f)).xyz; // No non-uniform scaling + + float depth = linstep(0.5f, 0.7f, length(in_pos.xyz)); + vs_output.albedo = lerp(mDeepColor.xyz, mSurfaceColor.xyz, depth); +} diff --git a/Projects/Asteroids/src/asteroids_DE.cpp b/Projects/Asteroids/src/asteroids_DE.cpp new file mode 100644 index 0000000..0cb3ddf --- /dev/null +++ b/Projects/Asteroids/src/asteroids_DE.cpp @@ -0,0 +1,870 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#include <directxmath.h> +#include <math.h> + +#include <iostream> +#include <algorithm> +#include <vector> +#include <future> +#include <limits> +#include <random> +#include <locale> +#include <codecvt> + +#include "asteroids_DE.h" +#include "RenderDeviceFactoryD3D11.h" +#include "RenderDeviceFactoryD3D12.h" +#include "RenderDeviceFactoryOpenGL.h" +#include "BasicShaderSourceStreamFactory.h" +#include "MapHelper.h" + +#include "util.h" +#include "mesh.h" +#include "noise.h" +#include "texture.h" +#include "StringTools.h" +#include "TextureUtilities.h" + +using namespace Diligent; + +namespace Diligent +{ +#ifdef ENGINE_DLL + CreateDeviceAndContextsD3D11Type CreateDeviceAndContextsD3D11 = nullptr; + CreateSwapChainD3D11Type CreateSwapChainD3D11 = nullptr; + + CreateDeviceAndContextsD3D12Type CreateDeviceAndContextsD3D12 = nullptr; + CreateSwapChainD3D12Type CreateSwapChainD3D12 = nullptr; + + CreateDeviceAndSwapChainGLType CreateDeviceAndSwapChainGL = nullptr; +#endif +} + +namespace AsteroidsDE { + + +// Create Direct3D device and swap chain +void Asteroids::InitDevice(HWND hWnd, DeviceType DevType) +{ + EngineCreationAttribs EngineCreationAttribs; + EngineCreationAttribs.strShaderCachePath = "bin\\tmp\\ShaderCache"; + SwapChainDesc SwapChainDesc; + SwapChainDesc.SamplesCount = 1; + SwapChainDesc.BufferCount = NUM_SWAP_CHAIN_BUFFERS; + SwapChainDesc.ColorBufferFormat = TEX_FORMAT_RGBA8_UNORM_SRGB; + SwapChainDesc.DepthBufferFormat = TEX_FORMAT_D32_FLOAT; + SwapChainDesc.DefaultDepthValue = 0.f; + switch (DevType) + { + case DeviceType::D3D12: + case DeviceType::D3D11: + { + std::vector<IDeviceContext*> ppContexts(mNumSubsets); + if(DevType == DeviceType::D3D11) + { + EngineD3D11Attribs DeviceAttribs; + DeviceAttribs.DebugFlags = (Uint32)EngineD3D11DebugFlags::VerifyCommittedShaderResources | + (Uint32)EngineD3D11DebugFlags::VerifyCommittedResourceRelevance; + +#ifdef ENGINE_DLL + if(!CreateDeviceAndContextsD3D11 || !CreateSwapChainD3D11) + LoadGraphicsEngineD3D11(CreateDeviceAndContextsD3D11, CreateSwapChainD3D11); +#endif + CreateDeviceAndContextsD3D11( DeviceAttribs, &mDevice, ppContexts.data(), mNumSubsets-1 ); + CreateSwapChainD3D11( mDevice, ppContexts[0], SwapChainDesc, hWnd, &mSwapChain ); + } + else + { + EngineD3D12Attribs Attribs; + Attribs.GPUDescriptorHeapDynamicSize[0] = 65536*4; + Attribs.GPUDescriptorHeapSize[0] = 65536*4; +#ifndef _DEBUG + Attribs.DynamicDescriptorAllocationChunkSize[0] = 4*2048; +#endif +#ifdef ENGINE_DLL + if(!CreateDeviceAndContextsD3D12 || !CreateSwapChainD3D12) + LoadGraphicsEngineD3D12(CreateDeviceAndContextsD3D12, CreateSwapChainD3D12); +#endif + CreateDeviceAndContextsD3D12( Attribs, &mDevice, ppContexts.data(), mNumSubsets-1 ); + CreateSwapChainD3D12( mDevice, ppContexts[0], SwapChainDesc, hWnd, &mSwapChain ); + } + + mDeviceCtxt.Attach(ppContexts[0]); + mDeferredCtxt.resize(mNumSubsets-1); + for(size_t ctx=0; ctx < mNumSubsets-1; ++ctx) + mDeferredCtxt[ctx].Attach(ppContexts[1+ctx]); + } + break; + + case DeviceType::OpenGL: +#ifdef ENGINE_DLL + if(!CreateDeviceAndSwapChainGL) + LoadGraphicsEngineOpenGL(CreateDeviceAndSwapChainGL); +#endif + CreateDeviceAndSwapChainGL( + EngineCreationAttribs, &mDevice, &mDeviceCtxt, SwapChainDesc, hWnd, &mSwapChain ); + break; + + default: + LOG_ERROR_AND_THROW("Unknown device type"); + break; + } +} + +Asteroids::Asteroids(UINT NumThreads, AsteroidsSimulation* asteroids, GUI* gui, HWND hWnd, Diligent::DeviceType DevType) + : mAsteroids(asteroids) + , mGUI(gui) +{ + QueryPerformanceFrequency((LARGE_INTEGER*)&mPerfCounterFreq); + + mNumSubsets = std::max(NumThreads,1u); + mNumSubsets = std::min(NumThreads,32u); + + InitDevice(hWnd, DevType); + + mCmdLists.resize(mDeferredCtxt.size()); + mWorkerThreads.resize(mNumSubsets-1); + for(auto &thread : mWorkerThreads) + { + thread = std::thread(WorkerThreadFunc, this, (Uint32)(&thread-mWorkerThreads.data()) ); + } + + const char *spriteFile = nullptr; + switch(DevType) + { + case DeviceType::D3D11: spriteFile = "DiligentD3D11.dds"; break; + case DeviceType::D3D12: spriteFile = "DiligentD3D12.dds"; break; + case DeviceType::OpenGL: spriteFile = "DiligentGL.dds"; break; + } + mSprite.reset( new GUISprite(5, 10, 140, 50, spriteFile) ); + + BasicShaderSourceStreamFactory BasicSSSFactory({"src"}); + + mBackBufferWidth = mSwapChain->GetDesc().Width; + mBackBufferHeight = mSwapChain->GetDesc().Height; + // Create draw constant buffer + { + BufferDesc desc; + desc.Name = "draw constant buffer (dynamic)"; + desc.Usage = USAGE_DYNAMIC; + desc.uiSizeInBytes = (Uint32) sizeof(DrawConstantBuffer); + desc.BindFlags = BIND_UNIFORM_BUFFER; + desc.CPUAccessFlags = CPU_ACCESS_WRITE; + mDevice->CreateBuffer(desc, BufferData(), &mDrawConstantBuffer); + } + + // create pipeline state + { + PipelineStateDesc PSODesc; + LayoutElement inputDesc[] = { + LayoutElement( 0, 0, 3, VT_FLOAT32), + LayoutElement( 1, 0, 3, VT_FLOAT32) + }; + + PSODesc.GraphicsPipeline.InputLayout.LayoutElements = inputDesc; + PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof(inputDesc); + + PSODesc.GraphicsPipeline.DepthStencilDesc.DepthFunc = COMPARISON_FUNC_GREATER_EQUAL; + + RefCntAutoPtr<IShader> vs, ps; + { + ShaderCreationAttribs attribs; + attribs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_STATIC; + attribs.Desc.ShaderType = SHADER_TYPE_VERTEX; + attribs.Desc.Name = "Asteroids VS"; + attribs.EntryPoint = "asteroid_vs"; + attribs.FilePath = "asteroid_vs.hlsl"; + attribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; + attribs.pShaderSourceStreamFactory = &BasicSSSFactory; + mDevice->CreateShader(attribs, &vs); + vs->GetShaderVariable("DrawConstantBuffer")->Set(mDrawConstantBuffer); + } + + { + ShaderCreationAttribs attribs; + attribs.Desc.DefaultVariableType = m_BindingMode == BindingMode::Dynamic ? SHADER_VARIABLE_TYPE_DYNAMIC : SHADER_VARIABLE_TYPE_MUTABLE; + attribs.Desc.ShaderType = SHADER_TYPE_PIXEL; + attribs.Desc.Name = "Asteroids PS"; + attribs.EntryPoint = "asteroid_ps_d3d11"; + attribs.FilePath = "asteroid_ps_d3d11.hlsl"; + attribs.pShaderSourceStreamFactory = &BasicSSSFactory; + attribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; + + StaticSamplerDesc samDesc; + samDesc.Desc.MagFilter = FILTER_TYPE_ANISOTROPIC; + samDesc.Desc.MinFilter = FILTER_TYPE_ANISOTROPIC; + samDesc.Desc.MipFilter = FILTER_TYPE_ANISOTROPIC; + samDesc.Desc.AddressU = TEXTURE_ADDRESS_WRAP; + samDesc.Desc.AddressV = TEXTURE_ADDRESS_WRAP; + samDesc.Desc.AddressW = TEXTURE_ADDRESS_WRAP; + samDesc.Desc.MinLOD = -D3D11_FLOAT32_MAX; + samDesc.Desc.MaxLOD = D3D11_FLOAT32_MAX; + samDesc.Desc.MipLODBias = 0.0f; + samDesc.Desc.MaxAnisotropy = TEXTURE_ANISO; + samDesc.Desc.ComparisonFunc = COMPARISON_FUNC_NEVER; + samDesc.TextureName = "Tex"; + attribs.Desc.StaticSamplers = &samDesc; + attribs.Desc.NumStaticSamplers = 1; + + mDevice->CreateShader(attribs, &ps); + } + PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB; + PSODesc.GraphicsPipeline.NumRenderTargets = 1; + PSODesc.GraphicsPipeline.DSVFormat = TEX_FORMAT_D32_FLOAT; + PSODesc.GraphicsPipeline.PrimitiveTopologyType = PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + PSODesc.Name = "Asteroids PSO"; + + PSODesc.GraphicsPipeline.pVS = vs; + PSODesc.GraphicsPipeline.pPS = ps; + Uint32 NumSRBs = 0; + if(m_BindingMode == BindingMode::Dynamic) + { + NumSRBs = mNumSubsets; + } + else if(m_BindingMode == BindingMode::Mutable) + { + PSODesc.SRBAllocationGranularity = 1024; + NumSRBs = NUM_ASTEROIDS; + } + else if(m_BindingMode == BindingMode::TextureMutable) + { + PSODesc.SRBAllocationGranularity = NUM_UNIQUE_TEXTURES; + NumSRBs = NUM_UNIQUE_TEXTURES; + } + mDevice->CreatePipelineState(PSODesc, &mAsteroidsPSO); + mAsteroidsSRBs.resize(NumSRBs); + for(size_t srb = 0; srb < mAsteroidsSRBs.size(); ++srb) + { + mAsteroidsPSO->CreateShaderResourceBinding(&mAsteroidsSRBs[srb]); + } + } + + + // Load textures + { + TextureLoadInfo loadInfo; + loadInfo.IsSRGB = true; + RefCntAutoPtr<ITexture> skybox; + CreateTextureFromFile("starbox_1024.dds", loadInfo, mDevice, &skybox); + mSkyboxSRV = skybox->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); + } + + // Create skybox constant buffer + { + BufferDesc desc; + desc.Name = "skybox constant buffer (dynamic)"; + desc.Usage = USAGE_DYNAMIC; + desc.uiSizeInBytes = sizeof(SkyboxConstantBuffer); + desc.BindFlags = BIND_UNIFORM_BUFFER; + desc.CPUAccessFlags = CPU_ACCESS_WRITE; + mDevice->CreateBuffer(desc, BufferData(), &mSkyboxConstantBuffer); + } + + // create skybox pipeline state + { + LayoutElement inputDesc[] = { + LayoutElement( 0, 0, 3, VT_FLOAT32), + LayoutElement( 1, 0, 3, VT_FLOAT32) + }; + + RefCntAutoPtr<IShader> vs, ps; + ShaderCreationAttribs attribs; + attribs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_STATIC; + attribs.Desc.ShaderType = SHADER_TYPE_VERTEX; + attribs.Desc.Name = "Skybox VS"; + attribs.EntryPoint = "skybox_vs"; + attribs.FilePath = "skybox_vs.hlsl"; + attribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; + attribs.pShaderSourceStreamFactory = &BasicSSSFactory; + mDevice->CreateShader(attribs, &vs); + vs->GetShaderVariable("SkyboxConstantBuffer")->Set(mSkyboxConstantBuffer); + + attribs.Desc.Name = "Skybox PS"; + attribs.EntryPoint = "skybox_ps"; + attribs.FilePath = "skybox_ps.hlsl"; + attribs.Desc.ShaderType = SHADER_TYPE_PIXEL; + + StaticSamplerDesc ssdesc; + ssdesc.TextureName = "Skybox"; + ssdesc.Desc.MagFilter = FILTER_TYPE_ANISOTROPIC; + ssdesc.Desc.MinFilter = FILTER_TYPE_ANISOTROPIC; + ssdesc.Desc.MipFilter = FILTER_TYPE_ANISOTROPIC; + ssdesc.Desc.AddressU = TEXTURE_ADDRESS_WRAP; + ssdesc.Desc.AddressV = TEXTURE_ADDRESS_WRAP; + ssdesc.Desc.AddressW = TEXTURE_ADDRESS_WRAP; + ssdesc.Desc.MaxAnisotropy = TEXTURE_ANISO; + attribs.Desc.StaticSamplers = &ssdesc; + attribs.Desc.NumStaticSamplers = 1; + mDevice->CreateShader(attribs, &ps); + ps->GetShaderVariable("Skybox")->Set(mSkyboxSRV); + + PipelineStateDesc PSODesc; + PSODesc.Name = "Skybox PSO"; + PSODesc.GraphicsPipeline.InputLayout.LayoutElements = inputDesc; + PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof(inputDesc); + + PSODesc.GraphicsPipeline.DepthStencilDesc.DepthFunc = COMPARISON_FUNC_GREATER_EQUAL; + PSODesc.GraphicsPipeline.pVS = vs; + PSODesc.GraphicsPipeline.pPS = ps; + + PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB; + PSODesc.GraphicsPipeline.NumRenderTargets = 1; + PSODesc.GraphicsPipeline.DSVFormat = TEX_FORMAT_D32_FLOAT; + PSODesc.GraphicsPipeline.PrimitiveTopologyType = PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + + mDevice->CreatePipelineState(PSODesc, &mSkyboxPSO); + } + + // Create sampler + { + SamplerDesc desc; + desc.MagFilter = FILTER_TYPE_ANISOTROPIC; + desc.MinFilter = FILTER_TYPE_ANISOTROPIC; + desc.MipFilter = FILTER_TYPE_ANISOTROPIC; + desc.AddressU = TEXTURE_ADDRESS_WRAP; + desc.AddressV = TEXTURE_ADDRESS_WRAP; + desc.AddressW = TEXTURE_ADDRESS_WRAP; + desc.MinLOD = -D3D11_FLOAT32_MAX; + desc.MaxLOD = D3D11_FLOAT32_MAX; + desc.MipLODBias = 0.0f; + desc.MaxAnisotropy = TEXTURE_ANISO; + desc.ComparisonFunc = COMPARISON_FUNC_NEVER; + mDevice->CreateSampler(desc, &mSamplerState); + } + + CreateGUIResources(); + + // Sprites and fonts + { + PipelineStateDesc PSODesc; + LayoutElement inputDesc[] = { + LayoutElement( 0, 0, 2, VT_FLOAT32), + LayoutElement( 1, 0, 2, VT_FLOAT32) + }; + PSODesc.GraphicsPipeline.InputLayout.LayoutElements = inputDesc; + PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof(inputDesc); + + auto &BlendState = PSODesc.GraphicsPipeline.BlendDesc; + { + // Premultiplied over blend + BlendState.RenderTargets[0].BlendEnable = TRUE; + BlendState.RenderTargets[0].SrcBlend = BLEND_FACTOR_ONE; + BlendState.RenderTargets[0].BlendOp = BLEND_OPERATION_ADD; + BlendState.RenderTargets[0].DestBlend = BLEND_FACTOR_INV_SRC_ALPHA; + } + + PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = false; + + PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB; + PSODesc.GraphicsPipeline.NumRenderTargets = 1; + PSODesc.GraphicsPipeline.DSVFormat = TEX_FORMAT_D32_FLOAT; + PSODesc.GraphicsPipeline.PrimitiveTopologyType = PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + + RefCntAutoPtr<IShader> sprite_vs, sprite_ps, font_ps; + { + ShaderCreationAttribs attribs; + attribs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_STATIC; + attribs.Desc.ShaderType = SHADER_TYPE_VERTEX; + attribs.Desc.Name = "Sprite VS"; + attribs.EntryPoint = "sprite_vs"; + attribs.FilePath = "sprite_vs.hlsl"; + attribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; + attribs.pShaderSourceStreamFactory = &BasicSSSFactory; + mDevice->CreateShader(attribs, &sprite_vs); + } + + { + ShaderCreationAttribs attribs; + attribs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_DYNAMIC; + attribs.Desc.ShaderType = SHADER_TYPE_PIXEL; + attribs.Desc.Name = "Sprite PS"; + attribs.EntryPoint = "sprite_ps"; + attribs.FilePath = "sprite_ps.hlsl"; + attribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; + attribs.pShaderSourceStreamFactory = &BasicSSSFactory; + mDevice->CreateShader(attribs, &sprite_ps); + } + + { + ShaderCreationAttribs attribs; + attribs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_STATIC; + attribs.Desc.ShaderType = SHADER_TYPE_PIXEL; + attribs.Desc.Name = "Font PS"; + attribs.EntryPoint = "font_ps"; + attribs.FilePath = "font_ps.hlsl"; + attribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; + attribs.pShaderSourceStreamFactory = &BasicSSSFactory; + mDevice->CreateShader(attribs, &font_ps); + font_ps->GetShaderVariable("Tex")->Set(mFontTextureSRV); + } + + PSODesc.Name = "Sprite PSO"; + PSODesc.GraphicsPipeline.pVS = sprite_vs; + PSODesc.GraphicsPipeline.pPS = sprite_ps; + mDevice->CreatePipelineState(PSODesc, &mSpritePSO); + mSpritePSO->CreateShaderResourceBinding(&mSpriteSRB); + + PSODesc.Name = "Font PSO"; + PSODesc.GraphicsPipeline.pPS = font_ps; + mDevice->CreatePipelineState(PSODesc, &mFontPSO); + } + + + CreateMeshes(); + InitializeTextureData(); + if( m_BindingMode == BindingMode::Mutable ) + { + for(size_t srb = 0; srb < NUM_ASTEROIDS; ++srb) + { + auto staticData = &mAsteroids->StaticData()[srb]; + mAsteroidsSRBs[srb]->GetVariable(SHADER_TYPE_PIXEL, "Tex")->Set(mTextureSRVs[staticData->textureIndex]); + } + } + else if( m_BindingMode == BindingMode::TextureMutable ) + { + for(size_t srb = 0; srb < NUM_UNIQUE_TEXTURES; ++srb) + { + mAsteroidsSRBs[srb]->GetVariable(SHADER_TYPE_PIXEL, "Tex")->Set(mTextureSRVs[srb]); + } + } + +} + +Asteroids::~Asteroids() +{ + { + std::unique_lock<std::mutex> lk(mMutex); + mExitThreads = true; + } + mCondVar.notify_all(); + + for(auto &thread : mWorkerThreads) + { + thread.join(); + } +} + + + +void Asteroids::ResizeSwapChain(HWND outputWindow, unsigned int width, unsigned int height) +{ + mSwapChain->Resize(width, height); + mBackBufferWidth = width; + mBackBufferHeight = height; +} + + +void Asteroids::CreateMeshes() +{ + auto asteroidMeshes = mAsteroids->Meshes(); + + // create vertex buffer + { + BufferDesc desc; + desc.Name = "Asteroid Meshes Vertex Buffer"; + desc.uiSizeInBytes = (Uint32)asteroidMeshes->vertices.size() * sizeof(asteroidMeshes->vertices[0]); + desc.BindFlags = BIND_VERTEX_BUFFER; + desc.Usage = USAGE_DEFAULT; + + BufferData data; + data.pData = asteroidMeshes->vertices.data(); + data.DataSize = desc.uiSizeInBytes; + + mDevice->CreateBuffer(desc, data, &mVertexBuffer); + } + + // create index buffer + { + BufferDesc desc; + desc.Name = "Asteroid Meshes Index Buffer"; + desc.uiSizeInBytes = (Uint32)asteroidMeshes->indices.size() * sizeof(asteroidMeshes->indices[0]); + desc.BindFlags = BIND_INDEX_BUFFER; + desc.Usage = USAGE_DEFAULT; + + BufferData data; + data.pData = asteroidMeshes->indices.data(); + data.DataSize = desc.uiSizeInBytes; + + mDevice->CreateBuffer(desc, data, &mIndexBuffer); + } + + std::vector<SkyboxVertex> skyboxVertices; + CreateSkyboxMesh(&skyboxVertices); + + + // create skybox vertex buffer + { + BufferDesc desc; + desc.Name = "Skybox Vertex Buffer"; + desc.uiSizeInBytes = (Uint32)skyboxVertices.size() * sizeof(skyboxVertices[0]); + desc.BindFlags = BIND_VERTEX_BUFFER; + desc.Usage = USAGE_DEFAULT; + + BufferData data; + data.pData = skyboxVertices.data(); + data.DataSize = desc.uiSizeInBytes; + + mDevice->CreateBuffer(desc, data, &mSkyboxVertexBuffer); + } + + // create sprite vertex buffer (dynamic) + { + BufferDesc desc; + desc.Name = "sprite vertex buffer (dynamic)"; + desc.uiSizeInBytes = (Uint32)MAX_SPRITE_VERTICES_PER_FRAME * sizeof(SpriteVertex); + desc.BindFlags = BIND_VERTEX_BUFFER; + desc.Usage = USAGE_DYNAMIC; + desc.CPUAccessFlags = CPU_ACCESS_WRITE; + + mDevice->CreateBuffer(desc, BufferData(), &mSpriteVertexBuffer); + } +} + +void Asteroids::InitializeTextureData() +{ + TextureDesc textureDesc; + textureDesc.Type = RESOURCE_DIM_TEX_2D_ARRAY; + textureDesc.Width = TEXTURE_DIM; + textureDesc.Height = TEXTURE_DIM; + textureDesc.ArraySize = 3; + textureDesc.MipLevels = 0; // Full chain + textureDesc.Format = TEX_FORMAT_RGBA8_UNORM_SRGB; + textureDesc.SampleCount = 1; + textureDesc.Usage = USAGE_DEFAULT; + textureDesc.BindFlags = BIND_SHADER_RESOURCE; + + for (UINT t = 0; t < NUM_UNIQUE_TEXTURES; ++t) { + std::vector<TextureSubResData> subResData(textureDesc.ArraySize*mAsteroids->GetTextureMipLevels()); + auto *texData = mAsteroids->TextureData(t); + for(size_t subRes=0; subRes < subResData.size(); ++subRes) + { + subResData[subRes].pData = texData[subRes].pSysMem; + subResData[subRes].Stride = texData[subRes].SysMemPitch; + subResData[subRes].DepthStride = texData[subRes].SysMemSlicePitch; + } + TextureData initData; + initData.NumSubresources = (Uint32)subResData.size(); + initData.pSubResources = subResData.data(); + mDevice->CreateTexture(textureDesc, initData, &mTextures[t]); + mTextureSRVs[t] = mTextures[t]->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); + mTextureSRVs[t]->SetSampler(mSamplerState); + } +} + +void Asteroids::CreateGUIResources() +{ + auto font = mGUI->Font(); + TextureDesc textureDesc; + textureDesc.Type = RESOURCE_DIM_TEX_2D; + textureDesc.Format = TEX_FORMAT_R8_UNORM; + textureDesc.Width = font->BitmapWidth(); + textureDesc.Height = font->BitmapHeight(); + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.BindFlags = BIND_SHADER_RESOURCE; + textureDesc.Usage = USAGE_DEFAULT; + + TextureData initialData; + TextureSubResData subresources[] = { + TextureSubResData((void*)font->Pixels(), font->BitmapWidth()) + }; + initialData.pSubResources = subresources; + initialData.NumSubresources = _countof(subresources); + + RefCntAutoPtr<ITexture> texture; + mDevice->CreateTexture(textureDesc, initialData, &texture); + mFontTextureSRV = texture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); + mFontTextureSRV->SetSampler(mSamplerState); + + // Load any GUI sprite textures + for (int i = -1; i < (int)mGUI->size(); ++i) { + auto control = i >= 0 ? (*mGUI)[i] : mSprite.get(); + if (control->TextureFile().length() > 0 && mSpriteTextures.find(control->TextureFile()) == mSpriteTextures.end()) { + std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; + ID3D11ShaderResourceView* textureSRV = nullptr; + auto path = NarrowString(converter.from_bytes(control->TextureFile()).c_str()); + TextureLoadInfo loadInfo; + loadInfo.IsSRGB = true; + RefCntAutoPtr<ITexture> spriteTexture; + CreateTextureFromFile(path.c_str(), loadInfo, mDevice, &spriteTexture); + auto *pSRV = spriteTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); + pSRV->SetSampler(mSamplerState); + mSpriteTextures[control->TextureFile()] = pSRV; + } + } +} + +static_assert(sizeof(IndexType) == 2, "Expecting 16-bit index buffer"); + +void Asteroids::WorkerThreadFunc(Asteroids *pThis, Diligent::Uint32 ThreadNum) +{ + for (;;) + { + // Wait for mUpdateSubsets or mExitThreads flag on conditional variable + { + std::unique_lock<std::mutex> lk(pThis->mMutex); + pThis->mCondVar.wait(lk, [&]{return pThis->mUpdateSubsets || pThis->mExitThreads;}); + } + + if(pThis->mExitThreads) + return; + + auto SubsetSize = NUM_ASTEROIDS / pThis->mNumSubsets; + auto SubsetStart = SubsetSize * (ThreadNum+1); + auto &FrameAttribs = pThis->mFrameAttribs; + + pThis->mAsteroids->Update(FrameAttribs.frameTime, FrameAttribs.camera->Eye(), *FrameAttribs.settings, SubsetStart, SubsetSize); + + // Increment number of completed threads + ++pThis->m_NumThreadsCompleted; + + // Wait for mRenderSubsets flag on conditional variable + { + std::unique_lock<std::mutex> lk(pThis->mMutex); + pThis->mCondVar.wait(lk, [&]{return pThis->mRenderSubsets || pThis->mExitThreads;}); + } + + pThis->RenderSubset(1+ThreadNum, pThis->mDeferredCtxt[ThreadNum], *FrameAttribs.camera, SubsetStart, SubsetSize); + + RefCntAutoPtr<ICommandList> pCmdList; + pThis->mCmdLists[ThreadNum].Release(); + pThis->mDeferredCtxt[ThreadNum]->FinishCommandList(&pThis->mCmdLists[ThreadNum]); + + // Increment number of completed threads + ++pThis->m_NumThreadsCompleted; + } + +} + +void Asteroids::RenderSubset(Diligent::Uint32 SubsetNum, + IDeviceContext *pCtx, + const OrbitCamera& camera, + Uint32 startIdx, + Uint32 numAsteroids) +{ + pCtx->SetRenderTargets(0, nullptr, nullptr); + + // Frame data + auto staticAsteroidData = mAsteroids->StaticData(); + auto dynamicAsteroidData = mAsteroids->DynamicData(); + + pCtx->SetPipelineState(mAsteroidsPSO); + + { + IBuffer* ia_buffers[] = { mVertexBuffer }; + Uint32 ia_strides[] = { sizeof(Vertex) }; + Uint32 ia_offsets[] = { 0 }; + pCtx->SetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets, 0); + pCtx->SetIndexBuffer(mIndexBuffer, 0); + } + + auto pVar = m_BindingMode == BindingMode::Dynamic ? mAsteroidsSRBs[SubsetNum]->GetVariable(SHADER_TYPE_PIXEL, "Tex") : nullptr; + auto viewProjection = camera.ViewProjection(); + for (UINT drawIdx = startIdx; drawIdx < startIdx+numAsteroids; ++drawIdx) + { + auto staticData = &staticAsteroidData[drawIdx]; + auto dynamicData = &dynamicAsteroidData[drawIdx]; + + { + MapHelper<DrawConstantBuffer> drawConstants(pCtx, mDrawConstantBuffer, MAP_WRITE_DISCARD, 0); + XMStoreFloat4x4(&drawConstants->mWorld, dynamicData->world); + XMStoreFloat4x4(&drawConstants->mViewProjection, viewProjection); + drawConstants->mSurfaceColor = staticData->surfaceColor; + drawConstants->mDeepColor = staticData->deepColor; + } + if( m_BindingMode == BindingMode::Dynamic ) + { + pVar->Set(mTextureSRVs[staticData->textureIndex]); + pCtx->CommitShaderResources(mAsteroidsSRBs[SubsetNum], COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); + } + else if( m_BindingMode == BindingMode::Mutable ) + { + pCtx->CommitShaderResources(mAsteroidsSRBs[drawIdx], COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); + } + else if( m_BindingMode == BindingMode::TextureMutable ) + { + pCtx->CommitShaderResources(mAsteroidsSRBs[staticData->textureIndex], 0); + } + + DrawAttribs attribs; + attribs.Topology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + attribs.IsIndexed = true; + attribs.NumIndices = dynamicData->indexCount; + attribs.IndexType = VT_UINT16; + attribs.FirstIndexLocation = dynamicData->indexStart; + attribs.BaseVertex = staticData->vertexStart; + pCtx->Draw(attribs); + } +} + +void Asteroids::Render(float frameTime, const OrbitCamera& camera, const Settings& settings) +{ + mFrameAttribs.frameTime = frameTime; + mFrameAttribs.camera = &camera; + mFrameAttribs.settings = &settings; + + // Clear the render target + float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + mDeviceCtxt->SetRenderTargets(0, nullptr, nullptr); + mDeviceCtxt->ClearRenderTarget(nullptr, clearcol); + mDeviceCtxt->ClearDepthStencil(nullptr, CLEAR_DEPTH_FLAG, 0.0f, 0); + + if( m_BindingMode == BindingMode::TextureMutable ) + { + for(auto &srb=mAsteroidsSRBs.begin(); srb!=mAsteroidsSRBs.end(); ++srb) + { + mDeviceCtxt->TransitionShaderResources(mAsteroidsPSO, *srb); + } + } + + LONG64 currCounter; + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + mUpdateTicks = currCounter; + + auto SubsetSize = NUM_ASTEROIDS / (settings.multithreadedRendering ? mNumSubsets : 1); + + if (settings.multithreadedRendering) + { + // Set mUpdateSubsets flag + { + std::unique_lock<std::mutex> lk(mMutex); + mUpdateSubsets = true; + m_NumThreadsCompleted = 0; + } + mCondVar.notify_all(); + } + + mAsteroids->Update(frameTime, camera.Eye(), settings, 0, SubsetSize); + + if (settings.multithreadedRendering) + { + // Wait for worker threads to finish + while(m_NumThreadsCompleted < (int)mNumSubsets-1) + std::this_thread::yield(); + // Clear mUpdateSubsets flag while all threads are waiting for mRenderSubsets flag + mUpdateSubsets = false; + } + + + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + mUpdateTicks = currCounter-mUpdateTicks; + + mRenderTicks = currCounter; + + if (settings.multithreadedRendering) + { + // Set mRenderSubsets flag + { + std::unique_lock<std::mutex> lk(mMutex); + mRenderSubsets = true; + m_NumThreadsCompleted = 0; + } + mCondVar.notify_all(); + } + + RenderSubset(0, mDeviceCtxt, camera, 0, SubsetSize); + + if (settings.multithreadedRendering) + { + // Wait for worker threads to finish + while(m_NumThreadsCompleted < (int)mNumSubsets-1) + std::this_thread::yield(); + // Clear mRenderSubsets flag while all threads are waiting for mUpdateSubsets flag + mRenderSubsets = false; + + for(auto &cmdList : mCmdLists) + { + mDeviceCtxt->ExecuteCommandList(cmdList); + } + } + + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + mRenderTicks = currCounter-mRenderTicks; + + mDeviceCtxt->SetRenderTargets(0, nullptr, nullptr); + // Draw skybox + { + { + MapHelper<SkyboxConstantBuffer> skyboxConstants(mDeviceCtxt, mSkyboxConstantBuffer, MAP_WRITE_DISCARD, 0); + XMStoreFloat4x4(&skyboxConstants->mViewProjection, camera.ViewProjection()); + } + + IBuffer* ia_buffers[] = { mSkyboxVertexBuffer }; + UINT ia_strides[] = { sizeof(SkyboxVertex) }; + UINT ia_offsets[] = { 0 }; + mDeviceCtxt->SetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets, 0); + + mDeviceCtxt->SetPipelineState(mSkyboxPSO); + mDeviceCtxt->CommitShaderResources(nullptr, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); + + DrawAttribs DrawAttrs; + DrawAttrs.Topology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + DrawAttrs.NumVertices = 6*6; + mDeviceCtxt->Draw(DrawAttrs); + } + + // Draw sprites and fonts + { + // Fill in vertices (TODO: could move this vector to be a member - not a big deal) + std::vector<UINT> controlVertices; + controlVertices.reserve(mGUI->size()); + + { + MapHelper<SpriteVertex> vertexBase(mDeviceCtxt, mSpriteVertexBuffer, MAP_WRITE_DISCARD, 0); + auto vertexEnd = (SpriteVertex*)vertexBase; + + for (int i = -1; i < (int)mGUI->size(); ++i) { + auto control = i >= 0 ? (*mGUI)[i] : mSprite.get(); + controlVertices.push_back((UINT)(control->Draw((float)mBackBufferWidth, (float)mBackBufferHeight, vertexEnd) - vertexEnd)); + vertexEnd += controlVertices.back(); + } + } + + IBuffer* ia_buffers[] = { mSpriteVertexBuffer }; + Uint32 ia_strides[] = { sizeof(SpriteVertex) }; + Uint32 ia_offsets[] = { 0 }; + mDeviceCtxt->SetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets, 0); + + // Draw + UINT vertexStart = 0; + for (int i = -1; i < (int)mGUI->size(); ++i) { + auto control = i >= 0 ? (*mGUI)[i] : mSprite.get(); + if (control->Visible()) { + if (control->TextureFile().length() == 0) { // Font + mDeviceCtxt->SetPipelineState(mFontPSO); + mDeviceCtxt->CommitShaderResources(nullptr, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); + } else { // Sprite + auto textureSRV = mSpriteTextures[control->TextureFile()]; + mDeviceCtxt->SetPipelineState(mSpritePSO); + mSpriteSRB->GetVariable(SHADER_TYPE_PIXEL, "Tex")->Set(textureSRV); + mDeviceCtxt->CommitShaderResources(mSpriteSRB, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); + } + DrawAttribs DrawAttrs; + DrawAttrs.Topology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + DrawAttrs.NumVertices = controlVertices[1+i]; + DrawAttrs.StartVertexLocation = vertexStart; + mDeviceCtxt->Draw(DrawAttrs); + } + vertexStart += controlVertices[1+i]; + } + } + + mSwapChain->Present();//settings.vsync ? 1 : 0, 0); +} + +void Asteroids::GetPerfCounters(float &UpdateTime, float &RenderTime) +{ + UpdateTime = (float)mUpdateTicks/(float)mPerfCounterFreq; + RenderTime = (float)mRenderTicks/(float)mPerfCounterFreq; +} + +} // namespace AsteroidsDE diff --git a/Projects/Asteroids/src/asteroids_DE.h b/Projects/Asteroids/src/asteroids_DE.h new file mode 100644 index 0000000..271d511 --- /dev/null +++ b/Projects/Asteroids/src/asteroids_DE.h @@ -0,0 +1,123 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include "RenderDevice.h" +#include "SwapChain.h" +#include "DeviceContext.h" +#include <map> +#include <mutex> +#include <atomic> + +#include "camera.h" +#include "settings.h" +#include "simulation.h" +#include "util.h" +#include "gui.h" +#include "RefCntAutoPtr.h" + +namespace AsteroidsDE { + +struct DrawConstantBuffer { + DirectX::XMFLOAT4X4 mWorld; + DirectX::XMFLOAT4X4 mViewProjection; + DirectX::XMFLOAT3 mSurfaceColor; + float unused0; + DirectX::XMFLOAT3 mDeepColor; + float unused1; +}; + +struct SkyboxConstantBuffer { + DirectX::XMFLOAT4X4 mViewProjection; +}; + +class Asteroids { +public: + Asteroids(UINT NumThreads, AsteroidsSimulation* asteroids, GUI* gui, HWND hWnd, Diligent::DeviceType DevType); + ~Asteroids(); + + void Render(float frameTime, const OrbitCamera& camera, const Settings& settings); + + void ResizeSwapChain(HWND outputWindow, unsigned int width, unsigned int height); + + void GetPerfCounters(float &UpdateTime, float &RenderTime); + +private: + void CreateMeshes(); + void InitializeTextureData(); + void CreateGUIResources(); + void RenderSubset(Diligent::Uint32 SubsetNum, Diligent::IDeviceContext *pCtx, const OrbitCamera& camera, Diligent::Uint32 startIdx, Diligent::Uint32 numAsteroids); + void InitDevice(HWND hWnd, Diligent::DeviceType DevType); + + enum class BindingMode + { + Dynamic = 1, + Mutable = 2, + TextureMutable = 3 + }m_BindingMode = BindingMode::TextureMutable; + + AsteroidsSimulation* mAsteroids = nullptr; + GUI* mGUI = nullptr; + + Diligent::RefCntAutoPtr<Diligent::ISwapChain> mSwapChain; + Diligent::RefCntAutoPtr<Diligent::IRenderDevice> mDevice; + Diligent::RefCntAutoPtr<Diligent::IDeviceContext> mDeviceCtxt; + std::vector< Diligent::RefCntAutoPtr<Diligent::IDeviceContext> > mDeferredCtxt; + std::vector< Diligent::RefCntAutoPtr<Diligent::ICommandList> > mCmdLists; + + Diligent::Uint32 mBackBufferWidth, mBackBufferHeight; + Diligent::Uint32 mNumSubsets = 0; + std::vector<std::thread> mWorkerThreads; + + std::mutex mMutex; + std::condition_variable mCondVar; + bool mUpdateSubsets = false; + bool mRenderSubsets = false; + bool mExitThreads = false; + std::atomic_int m_NumThreadsCompleted; + static void WorkerThreadFunc(Asteroids *pThis, Diligent::Uint32 ThreadNum); + + struct FrameAttribs + { + float frameTime; + const OrbitCamera* camera; + const Settings* settings; + }mFrameAttribs; + + Diligent::RefCntAutoPtr<Diligent::IBuffer> mIndexBuffer; + Diligent::RefCntAutoPtr<Diligent::IBuffer> mVertexBuffer; + Diligent::RefCntAutoPtr<Diligent::IBuffer> mDrawConstantBuffer; + Diligent::RefCntAutoPtr<Diligent::IBuffer> mSpriteVertexBuffer; + Diligent::RefCntAutoPtr<Diligent::IBuffer> mSkyboxConstantBuffer; + Diligent::RefCntAutoPtr<Diligent::IBuffer> mSkyboxVertexBuffer; + + Diligent::RefCntAutoPtr<Diligent::IPipelineState> mAsteroidsPSO; + std::vector< Diligent::RefCntAutoPtr<Diligent::IShaderResourceBinding> > mAsteroidsSRBs; + + Diligent::RefCntAutoPtr<Diligent::IPipelineState> mFontPSO; + Diligent::RefCntAutoPtr<Diligent::IPipelineState> mSpritePSO; + Diligent::RefCntAutoPtr<Diligent::IShaderResourceBinding> mSpriteSRB; + + Diligent::RefCntAutoPtr<Diligent::IPipelineState> mSkyboxPSO; + + std::map<std::string, Diligent::RefCntAutoPtr<Diligent::ITextureView>> mSpriteTextures; + Diligent::RefCntAutoPtr<Diligent::ITextureView> mSkyboxSRV; + Diligent::RefCntAutoPtr<Diligent::ITextureView> mFontTextureSRV; + Diligent::RefCntAutoPtr<Diligent::ITexture> mTextures[NUM_UNIQUE_TEXTURES]; + Diligent::RefCntAutoPtr<Diligent::ITextureView> mTextureSRVs[NUM_UNIQUE_TEXTURES]; + Diligent::RefCntAutoPtr<Diligent::ISampler> mSamplerState; + + std::unique_ptr<GUISprite> mSprite; + UINT64 mPerfCounterFreq = 0; + volatile LONG64 mUpdateTicks = 0, mRenderTicks = 0; +}; + +} // namespace AsteroidsD3D11 diff --git a/Projects/Asteroids/src/asteroids_d3d11.cpp b/Projects/Asteroids/src/asteroids_d3d11.cpp new file mode 100644 index 0000000..85602e5 --- /dev/null +++ b/Projects/Asteroids/src/asteroids_d3d11.cpp @@ -0,0 +1,594 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#include <d3dcompiler.h> +#include <directxmath.h> +#include <math.h> + +#include <iostream> +#include <algorithm> +#include <vector> +#include <future> +#include <limits> +#include <random> +#include <locale> +#include <codecvt> + +#include "asteroids_d3d11.h" +#include "util.h" +#include "mesh.h" +#include "noise.h" +#include "texture.h" +#include "DDSTextureLoader.h" + +#include "asteroid_vs.h" +#include "asteroid_ps_d3d11.h" +#include "skybox_vs.h" +#include "skybox_ps.h" +#include "sprite_vs.h" +#include "sprite_ps.h" +#include "font_ps.h" + +using namespace DirectX; + +namespace AsteroidsD3D11 { + +Asteroids::Asteroids(AsteroidsSimulation* asteroids, GUI* gui, bool warp) + : mAsteroids(asteroids) + , mGUI(gui) + , mSwapChain(nullptr) + , mDevice(nullptr) + , mDeviceCtxt(nullptr) + , mRenderTarget(nullptr) + , mRenderTargetView(nullptr) + , mDepthStencilView(nullptr) + , mDepthStencilState(nullptr) + , mInputLayout(nullptr) + , mIndexBuffer(nullptr) + , mVertexBuffer(nullptr) + , mVertexShader(nullptr) + , mPixelShader(nullptr) + , mDrawConstantBuffer(nullptr) + , mSkyboxVertexShader(nullptr) + , mSkyboxPixelShader(nullptr) + , mSkyboxConstantBuffer(nullptr) + , mSamplerState(nullptr) + , mD3D11Sprite( new GUISprite(5, 10, 140, 50, "directx11.dds") ) +{ + QueryPerformanceFrequency((LARGE_INTEGER*)&mPerfCounterFreq); + + memset(&mViewPort, 0, sizeof(mViewPort)); + memset(&mScissorRect, 0, sizeof(mScissorRect)); + memset(mTextures, 0, sizeof(mTextures)); + memset(mTextureSRVs, 0, sizeof(mTextureSRVs)); + + // Create device and swap chain + { + IDXGIAdapter* adapter = nullptr; + D3D_DRIVER_TYPE driverType = ( warp ) ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_HARDWARE; + HMODULE swModule = NULL; + UINT flags = 0; + D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 }; + UINT numFeatureLevels = ARRAYSIZE(featureLevels); + UINT sdkVersion = D3D11_SDK_VERSION; + +#ifdef _DEBUG + flags = flags | D3D11_CREATE_DEVICE_DEBUG; +#endif + + auto hr = D3D11CreateDevice(adapter, driverType, swModule, + flags, featureLevels, numFeatureLevels, sdkVersion, &mDevice, nullptr, &mDeviceCtxt); + if (FAILED(hr)) { + // Try again without the debug flag... + flags = flags & ~D3D11_CREATE_DEVICE_DEBUG; + ThrowIfFailed(D3D11CreateDevice(adapter, driverType, swModule, + flags, featureLevels, numFeatureLevels, sdkVersion, &mDevice, nullptr, &mDeviceCtxt)); + } + } + + // create pipeline state + { + D3D11_INPUT_ELEMENT_DESC inputDesc[] = { + { "ATTRIB", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "ATTRIB", 1, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc), + g_asteroid_vs, sizeof(g_asteroid_vs), &mInputLayout)); + + { + D3D11_DEPTH_STENCIL_DESC desc = CD3D11_DEPTH_STENCIL_DESC(D3D11_DEFAULT); + desc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL; + ThrowIfFailed(mDevice->CreateDepthStencilState(&desc, &mDepthStencilState)); + } + { + CD3D11_BLEND_DESC desc = CD3D11_BLEND_DESC(CD3D11_DEFAULT()); + ThrowIfFailed(mDevice->CreateBlendState(&desc, &mBlendState)); + + // Premultiplied over blend + desc.RenderTarget[0].BlendEnable = TRUE; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + ThrowIfFailed(mDevice->CreateBlendState(&desc, &mSpriteBlendState)); + } + + ThrowIfFailed(mDevice->CreateVertexShader(g_asteroid_vs, sizeof(g_asteroid_vs), NULL, &mVertexShader)); + ThrowIfFailed(mDevice->CreatePixelShader(g_asteroid_ps_d3d11, sizeof(g_asteroid_ps_d3d11), NULL, &mPixelShader)); + } + // create skybox pipeline state + { + D3D11_INPUT_ELEMENT_DESC inputDesc[] = { + { "ATTRIB", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "ATTRIB", 1, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc), + g_skybox_vs, sizeof(g_skybox_vs), &mSkyboxInputLayout)); + + ThrowIfFailed(mDevice->CreateVertexShader(g_skybox_vs, sizeof(g_skybox_vs), NULL, &mSkyboxVertexShader)); + ThrowIfFailed(mDevice->CreatePixelShader(g_skybox_ps, sizeof(g_skybox_ps), NULL, &mSkyboxPixelShader)); + } + + // Sprites and fonts + { + D3D11_INPUT_ELEMENT_DESC inputDesc[] = { + { "ATTRIB", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "ATTRIB", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc), + g_sprite_vs, sizeof(g_sprite_vs), &mSpriteInputLayout)); + + ThrowIfFailed(mDevice->CreateVertexShader(g_sprite_vs, sizeof(g_sprite_vs), NULL, &mSpriteVertexShader)); + ThrowIfFailed(mDevice->CreatePixelShader(g_sprite_ps, sizeof(g_sprite_ps), NULL, &mSpritePixelShader)); + ThrowIfFailed(mDevice->CreatePixelShader(g_font_ps, sizeof(g_font_ps), NULL, &mFontPixelShader)); + } + + // Create draw constant buffer + { + D3D11_BUFFER_DESC desc = {}; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = sizeof(DrawConstantBuffer); + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + ThrowIfFailed(mDevice->CreateBuffer(&desc, nullptr, &mDrawConstantBuffer)); + } + // Create skybox constant buffer + { + D3D11_BUFFER_DESC desc = {}; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = sizeof(SkyboxConstantBuffer); + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + ThrowIfFailed(mDevice->CreateBuffer(&desc, nullptr, &mSkyboxConstantBuffer)); + } + + // Create sampler + { + D3D11_SAMPLER_DESC desc = {}; + desc.Filter = D3D11_FILTER_ANISOTROPIC; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MinLOD = -D3D11_FLOAT32_MAX; + desc.MaxLOD = D3D11_FLOAT32_MAX; + desc.MipLODBias = 0.0f; + desc.MaxAnisotropy = TEXTURE_ANISO; + desc.ComparisonFunc = D3D11_COMPARISON_NEVER; + ThrowIfFailed(mDevice->CreateSamplerState(&desc, &mSamplerState)); + } + + CreateMeshes(); + InitializeTextureData(); + CreateGUIResources(); + + // Load textures + ThrowIfFailed(CreateDDSTextureFromFile(mDevice, L"starbox_1024.dds", &mSkyboxSRV, true)); +} + +Asteroids::~Asteroids() +{ + ReleaseSwapChain(); + + SafeRelease(&mDepthStencilState); + SafeRelease(&mInputLayout); + SafeRelease(&mIndexBuffer); + SafeRelease(&mVertexBuffer); + SafeRelease(&mVertexShader); + SafeRelease(&mPixelShader); + SafeRelease(&mDrawConstantBuffer); + SafeRelease(&mSamplerState); + + SafeRelease(&mBlendState); + SafeRelease(&mSpriteBlendState); + + for (auto i : mSpriteTextures) { + i.second->Release(); + } + SafeRelease(&mSpriteInputLayout); + SafeRelease(&mSpriteVertexShader); + SafeRelease(&mSpritePixelShader); + SafeRelease(&mSpriteVertexBuffer); + + SafeRelease(&mFontPixelShader); + SafeRelease(&mFontTextureSRV); + + SafeRelease(&mSkyboxVertexShader); + SafeRelease(&mSkyboxPixelShader); + SafeRelease(&mSkyboxConstantBuffer); + SafeRelease(&mSkyboxVertexBuffer); + SafeRelease(&mSkyboxInputLayout); + SafeRelease(&mSkyboxSRV); + + for (auto& texture : mTextures) SafeRelease(&texture); + for (auto& srv : mTextureSRVs) SafeRelease(&srv); + + if (mSwapChain != nullptr) { + mSwapChain->Release(); + mSwapChain = nullptr; + } + SafeRelease(&mDeviceCtxt); + SafeRelease(&mDevice); + + delete mD3D11Sprite; +} + + +void Asteroids::ReleaseSwapChain() +{ + // Cleanup any references... + SafeRelease(&mRenderTarget); + SafeRelease(&mRenderTargetView); + SafeRelease(&mDepthStencilView); + SafeRelease(&mSwapChain); + mDeviceCtxt->ClearState(); + mDeviceCtxt->Flush(); +} + +inline void DisableDXGIWindowChanges(IUnknown* device, HWND window) +{ + IDXGIDevice * pDXGIDevice; + ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice))); + IDXGIAdapter * pDXGIAdapter; + ThrowIfFailed(pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter))); + IDXGIFactory * pIDXGIFactory; + ThrowIfFailed(pDXGIAdapter->GetParent(IID_PPV_ARGS(&pIDXGIFactory))); + + ThrowIfFailed(pIDXGIFactory->MakeWindowAssociation(window, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER)); + + pIDXGIFactory->Release(); + pDXGIAdapter->Release(); + pDXGIDevice->Release(); +} + +void Asteroids::ResizeSwapChain(IDXGIFactory2* dxgiFactory, HWND outputWindow, unsigned int width, unsigned int height) +{ + ReleaseSwapChain(); + + // Create swap chain + { + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // Can create an SRGB render target view on the swap chain buffer + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = NUM_SWAP_CHAIN_BUFFERS; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Not used + swapChainDesc.Flags = 0; + + ThrowIfFailed(dxgiFactory->CreateSwapChainForHwnd( + mDevice, outputWindow, &swapChainDesc, nullptr, nullptr, &mSwapChain)); + // MakeWindowAssociation must be called after CreateSwapChain + DisableDXGIWindowChanges(mDevice, outputWindow); + } + + // create render target view + { + ThrowIfFailed(mSwapChain->GetBuffer(0, IID_PPV_ARGS(&mRenderTarget))); + + D3D11_RENDER_TARGET_VIEW_DESC desc = {}; + desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + desc.Texture2D.MipSlice = 0; + ThrowIfFailed(mDevice->CreateRenderTargetView(mRenderTarget, &desc, &mRenderTargetView)); + } + + // create depth stencil view + { + CD3D11_TEXTURE2D_DESC desc = CD3D11_TEXTURE2D_DESC( + DXGI_FORMAT_D32_FLOAT, width, height, 1, 1, D3D11_BIND_DEPTH_STENCIL); + + ID3D11Texture2D* depthStencil = nullptr; + ThrowIfFailed(mDevice->CreateTexture2D(&desc, nullptr, &depthStencil)); + ThrowIfFailed(mDevice->CreateDepthStencilView(depthStencil, nullptr, &mDepthStencilView)); + depthStencil->Release(); + } + + // update the viewport and scissor + ZeroMemory(&mViewPort, sizeof(D3D11_VIEWPORT)); + mViewPort.TopLeftX = 0; + mViewPort.TopLeftY = 0; + mViewPort.Width = (float)width; + mViewPort.Height = (float)height; + mViewPort.MinDepth = 0.0f; + mViewPort.MaxDepth = 1.0f; + + mScissorRect.left = 0; + mScissorRect.top = 0; + mScissorRect.right = width; + mScissorRect.bottom = height; +} + + +void Asteroids::CreateMeshes() +{ + auto asteroidMeshes = mAsteroids->Meshes(); + + // create vertex buffer + { + CD3D11_BUFFER_DESC desc( + (UINT)asteroidMeshes->vertices.size() * sizeof(asteroidMeshes->vertices[0]), + D3D11_BIND_VERTEX_BUFFER, + D3D11_USAGE_DEFAULT); + + D3D11_SUBRESOURCE_DATA data = {}; + data.pSysMem = asteroidMeshes->vertices.data(); + + ThrowIfFailed(mDevice->CreateBuffer(&desc, &data, &mVertexBuffer)); + } + + // create index buffer + { + CD3D11_BUFFER_DESC desc( + (UINT)asteroidMeshes->indices.size() * sizeof(asteroidMeshes->indices[0]), + D3D11_BIND_INDEX_BUFFER, + D3D11_USAGE_DEFAULT); + + D3D11_SUBRESOURCE_DATA data = {}; + data.pSysMem = asteroidMeshes->indices.data(); + + ThrowIfFailed(mDevice->CreateBuffer(&desc, &data, &mIndexBuffer)); + } + + std::vector<SkyboxVertex> skyboxVertices; + CreateSkyboxMesh(&skyboxVertices); + + // create skybox vertex buffer + { + CD3D11_BUFFER_DESC desc( + (UINT)skyboxVertices.size() * sizeof(skyboxVertices[0]), + D3D11_BIND_VERTEX_BUFFER, + D3D11_USAGE_DEFAULT); + + D3D11_SUBRESOURCE_DATA data = {}; + data.pSysMem = skyboxVertices.data(); + + ThrowIfFailed(mDevice->CreateBuffer(&desc, &data, &mSkyboxVertexBuffer)); + } + + // create sprite vertex buffer (dynamic) + { + CD3D11_BUFFER_DESC desc( + MAX_SPRITE_VERTICES_PER_FRAME * sizeof(SpriteVertex), + D3D11_BIND_VERTEX_BUFFER, + D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); + + ThrowIfFailed(mDevice->CreateBuffer(&desc, nullptr, &mSpriteVertexBuffer)); + } +} + +void Asteroids::InitializeTextureData() +{ + D3D11_TEXTURE2D_DESC textureDesc = {}; + textureDesc.Width = TEXTURE_DIM; + textureDesc.Height = TEXTURE_DIM; + textureDesc.ArraySize = 3; + textureDesc.MipLevels = 0; // Full chain + textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + textureDesc.SampleDesc.Count = 1; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + for (UINT t = 0; t < NUM_UNIQUE_TEXTURES; ++t) { + ThrowIfFailed(mDevice->CreateTexture2D(&textureDesc, mAsteroids->TextureData(t), &mTextures[t])); + ThrowIfFailed(mDevice->CreateShaderResourceView(mTextures[t], nullptr, &mTextureSRVs[t])); + } +} + +void Asteroids::CreateGUIResources() +{ + auto font = mGUI->Font(); + D3D11_TEXTURE2D_DESC textureDesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8_UNORM, font->BitmapWidth(), font->BitmapHeight(), 1, 1); + + D3D11_SUBRESOURCE_DATA initialData = {}; + initialData.pSysMem = font->Pixels(); + initialData.SysMemPitch = font->BitmapWidth(); + + ID3D11Texture2D* texture = nullptr; + ThrowIfFailed(mDevice->CreateTexture2D(&textureDesc, &initialData, &texture)); + ThrowIfFailed(mDevice->CreateShaderResourceView(texture, nullptr, &mFontTextureSRV)); + SafeRelease(&texture); + + // Load any GUI sprite textures + for (int i = -1; i < (int)mGUI->size(); ++i) { + auto control = i >= 0 ? (*mGUI)[i] : mD3D11Sprite; + if (control->TextureFile().length() > 0 && mSpriteTextures.find(control->TextureFile()) == mSpriteTextures.end()) { + std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; + ID3D11ShaderResourceView* textureSRV = nullptr; + ThrowIfFailed(CreateDDSTextureFromFile(mDevice, converter.from_bytes(control->TextureFile()).c_str(), &textureSRV, true)); + mSpriteTextures[control->TextureFile()] = textureSRV; + } + } +} + +static_assert(sizeof(IndexType) == 2, "Expecting 16-bit index buffer"); + +void Asteroids::Render(float frameTime, const OrbitCamera& camera, const Settings& settings) +{ + LONG64 currCounter = 0; + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + + // Frame data + mAsteroids->Update(frameTime, camera.Eye(), settings); + + mTotalUpdateTicks = currCounter; + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + mTotalUpdateTicks = currCounter - mTotalUpdateTicks; + + auto staticAsteroidData = mAsteroids->StaticData(); + auto dynamicAsteroidData = mAsteroids->DynamicData(); + + // Clear the render target + float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + mDeviceCtxt->ClearRenderTargetView(mRenderTargetView, clearcol); + mDeviceCtxt->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH, 0.0f, 0); + + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + { + ID3D11Buffer* ia_buffers[] = { mVertexBuffer }; + UINT ia_strides[] = { sizeof(Vertex) }; + UINT ia_offsets[] = { 0 }; + mDeviceCtxt->IASetInputLayout(mInputLayout); + mDeviceCtxt->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets); + mDeviceCtxt->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R16_UINT, 0); + } + + mDeviceCtxt->VSSetShader(mVertexShader, nullptr, 0); + mDeviceCtxt->VSSetConstantBuffers(0, 1, &mDrawConstantBuffer); + + mDeviceCtxt->RSSetViewports(1, &mViewPort); + mDeviceCtxt->RSSetScissorRects(1, &mScissorRect); + + mDeviceCtxt->PSSetShader(mPixelShader, nullptr, 0); + mDeviceCtxt->PSSetSamplers(0, 1, &mSamplerState); + + mDeviceCtxt->OMSetRenderTargets(1, &mRenderTargetView, mDepthStencilView); + mDeviceCtxt->OMSetDepthStencilState(mDepthStencilState, 0); + mDeviceCtxt->OMSetBlendState(mBlendState, nullptr, 0xFFFFFFFF); + + auto viewProjection = camera.ViewProjection(); + for (UINT drawIdx = 0; drawIdx < NUM_ASTEROIDS; ++drawIdx) + { + auto staticData = &staticAsteroidData[drawIdx]; + auto dynamicData = &dynamicAsteroidData[drawIdx]; + + D3D11_MAPPED_SUBRESOURCE mapped = {}; + ThrowIfFailed(mDeviceCtxt->Map(mDrawConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); + + auto drawConstants = (DrawConstantBuffer*) mapped.pData; + XMStoreFloat4x4(&drawConstants->mWorld, dynamicData->world); + XMStoreFloat4x4(&drawConstants->mViewProjection, viewProjection); + drawConstants->mSurfaceColor = staticData->surfaceColor; + drawConstants->mDeepColor = staticData->deepColor; + + mDeviceCtxt->Unmap(mDrawConstantBuffer, 0); + + mDeviceCtxt->PSSetShaderResources(0, 1, &mTextureSRVs[staticData->textureIndex]); + + mDeviceCtxt->DrawIndexedInstanced(dynamicData->indexCount, 1, dynamicData->indexStart, staticData->vertexStart, 0); + } + + mTotalRenderTicks = currCounter; + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + mTotalRenderTicks = currCounter - mTotalRenderTicks; + + // Draw skybox + { + D3D11_MAPPED_SUBRESOURCE mapped = {}; + ThrowIfFailed(mDeviceCtxt->Map(mSkyboxConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); + auto skyboxConstants = (SkyboxConstantBuffer*) mapped.pData; + XMStoreFloat4x4(&skyboxConstants->mViewProjection, camera.ViewProjection()); + mDeviceCtxt->Unmap(mSkyboxConstantBuffer, 0); + + ID3D11Buffer* ia_buffers[] = { mSkyboxVertexBuffer }; + UINT ia_strides[] = { sizeof(SkyboxVertex) }; + UINT ia_offsets[] = { 0 }; + mDeviceCtxt->IASetInputLayout(mSkyboxInputLayout); + mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets); + + mDeviceCtxt->VSSetShader(mSkyboxVertexShader, nullptr, 0); + mDeviceCtxt->VSSetConstantBuffers(0, 1, &mSkyboxConstantBuffer); + + mDeviceCtxt->PSSetShader(mSkyboxPixelShader, nullptr, 0); + mDeviceCtxt->PSSetSamplers(0, 1, &mSamplerState); + mDeviceCtxt->PSSetShaderResources(0, 1, &mSkyboxSRV); + + mDeviceCtxt->Draw(6*6, 0); + } + + mDeviceCtxt->OMSetRenderTargets(1, &mRenderTargetView, 0); // No more depth buffer + + // Draw sprites and fonts + { + // Fill in vertices (TODO: could move this vector to be a member - not a big deal) + std::vector<UINT> controlVertices; + controlVertices.reserve(mGUI->size()); + + { + D3D11_MAPPED_SUBRESOURCE mapped = {}; + ThrowIfFailed(mDeviceCtxt->Map(mSpriteVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); + auto vertexBase = (SpriteVertex*)mapped.pData; + auto vertexEnd = vertexBase; + + + for (int i = -1; i < (int)mGUI->size(); ++i) { + auto control = i >= 0 ? (*mGUI)[i] : mD3D11Sprite; + controlVertices.push_back((UINT)(control->Draw(mViewPort.Width, mViewPort.Height, vertexEnd) - vertexEnd)); + vertexEnd += controlVertices.back(); + } + + mDeviceCtxt->Unmap(mSpriteVertexBuffer, 0); + } + + ID3D11Buffer* ia_buffers[] = { mSpriteVertexBuffer }; + UINT ia_strides[] = { sizeof(SpriteVertex) }; + UINT ia_offsets[] = { 0 }; + mDeviceCtxt->IASetInputLayout(mSpriteInputLayout); + mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets); + mDeviceCtxt->VSSetShader(mSpriteVertexShader, 0, 0); + mDeviceCtxt->OMSetBlendState(mSpriteBlendState, nullptr, 0xFFFFFFFF); + + // Draw + UINT vertexStart = 0; + + for (int i = -1; i < (int)mGUI->size(); ++i) { + auto control = i >= 0 ? (*mGUI)[i] : mD3D11Sprite; + if (control->Visible()) { + if (control->TextureFile().length() == 0) { // Font + mDeviceCtxt->PSSetShader(mFontPixelShader, 0, 0); + mDeviceCtxt->PSSetShaderResources(0, 1, &mFontTextureSRV); + } else { // Sprite + auto textureSRV = mSpriteTextures[control->TextureFile()]; + mDeviceCtxt->PSSetShader(mSpritePixelShader, 0, 0); + mDeviceCtxt->PSSetShaderResources(0, 1, &textureSRV); + } + mDeviceCtxt->Draw(controlVertices[1+i], vertexStart); + } + vertexStart += controlVertices[1+i]; + } + } + + mSwapChain->Present(settings.vsync ? 1 : 0, 0); +} + +void Asteroids::GetPerfCounters(float &UpdateTime, float &RenderTime) +{ + UpdateTime = (float)mTotalUpdateTicks/(float)mPerfCounterFreq; + RenderTime = (float)mTotalRenderTicks/(float)mPerfCounterFreq; +} + +} // namespace AsteroidsD3D11 diff --git a/Projects/Asteroids/src/asteroids_d3d11.h b/Projects/Asteroids/src/asteroids_d3d11.h new file mode 100644 index 0000000..da9548e --- /dev/null +++ b/Projects/Asteroids/src/asteroids_d3d11.h @@ -0,0 +1,108 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include <d3d11.h> +#include <dxgi1_2.h> +#include <directxmath.h> +#include <random> +#include <map> + +#include "camera.h" +#include "settings.h" +#include "simulation.h" +#include "util.h" +#include "gui.h" + +namespace AsteroidsD3D11 { + +struct DrawConstantBuffer { + DirectX::XMFLOAT4X4 mWorld; + DirectX::XMFLOAT4X4 mViewProjection; + DirectX::XMFLOAT3 mSurfaceColor; + float unused0; + DirectX::XMFLOAT3 mDeepColor; + float unused1; +}; + +struct SkyboxConstantBuffer { + DirectX::XMFLOAT4X4 mViewProjection; +}; + +class Asteroids { +public: + Asteroids(AsteroidsSimulation* asteroids, GUI* gui, bool warp); + ~Asteroids(); + + void Render(float frameTime, const OrbitCamera& camera, const Settings& settings); + + void ReleaseSwapChain(); + void ResizeSwapChain(IDXGIFactory2* dxgiFactory, HWND outputWindow, unsigned int width, unsigned int height); + + void GetPerfCounters(float &UpdateTime, float &RenderTime); + +private: + void CreateMeshes(); + void InitializeTextureData(); + void CreateGUIResources(); + + AsteroidsSimulation* mAsteroids = nullptr; + GUI* mGUI = nullptr; + + IDXGISwapChain1* mSwapChain = nullptr; + ID3D11Device* mDevice = nullptr; + ID3D11DeviceContext* mDeviceCtxt = nullptr; + + // These depend on the swap chain buffer size + ID3D11Texture2D* mRenderTarget = nullptr; + ID3D11RenderTargetView* mRenderTargetView = nullptr; + ID3D11DepthStencilView* mDepthStencilView = nullptr; + D3D11_VIEWPORT mViewPort; + D3D11_RECT mScissorRect; + + ID3D11DepthStencilState* mDepthStencilState = nullptr; + ID3D11BlendState* mBlendState = nullptr; + ID3D11BlendState* mSpriteBlendState = nullptr; + + ID3D11InputLayout* mInputLayout = nullptr; + ID3D11Buffer* mIndexBuffer = nullptr; + ID3D11Buffer* mVertexBuffer = nullptr; + ID3D11VertexShader* mVertexShader = nullptr; + ID3D11PixelShader* mPixelShader = nullptr; + ID3D11Buffer* mDrawConstantBuffer = nullptr; + + ID3D11VertexShader* mSpriteVertexShader = nullptr; + ID3D11PixelShader* mSpritePixelShader = nullptr; + ID3D11InputLayout* mSpriteInputLayout = nullptr; + ID3D11Buffer* mSpriteVertexBuffer = nullptr; + std::map<std::string, ID3D11ShaderResourceView*> mSpriteTextures; + + ID3D11PixelShader* mFontPixelShader = nullptr; + ID3D11ShaderResourceView* mFontTextureSRV = nullptr; + + ID3D11VertexShader* mSkyboxVertexShader = nullptr; + ID3D11PixelShader* mSkyboxPixelShader = nullptr; + ID3D11Buffer* mSkyboxConstantBuffer = nullptr; + ID3D11Buffer* mSkyboxVertexBuffer = nullptr; + ID3D11InputLayout* mSkyboxInputLayout = nullptr; + ID3D11ShaderResourceView* mSkyboxSRV = nullptr; + + ID3D11Texture2D* mTextures[NUM_UNIQUE_TEXTURES]; + ID3D11ShaderResourceView* mTextureSRVs[NUM_UNIQUE_TEXTURES]; + ID3D11SamplerState* mSamplerState = nullptr; + + GUISprite* mD3D11Sprite = nullptr; + + UINT64 mPerfCounterFreq = 0; + volatile LONG64 mTotalUpdateTicks = 0, mTotalRenderTicks = 0; +}; + +} // namespace AsteroidsD3D11 diff --git a/Projects/Asteroids/src/asteroids_d3d12.cpp b/Projects/Asteroids/src/asteroids_d3d12.cpp new file mode 100644 index 0000000..1d6fcdd --- /dev/null +++ b/Projects/Asteroids/src/asteroids_d3d12.cpp @@ -0,0 +1,938 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#include <d3dcompiler.h> +#include <directxmath.h> +#include <d3dx12.h> +#include <math.h> + +#include <iostream> +#include <algorithm> +#include <vector> +#include <limits> +#include <random> +#include <sstream> +#include <ppl.h> + +#include "asteroids_d3d12.h" +#include "util.h" +#include "mesh.h" +#include "noise.h" +#include "texture.h" + +#include "asteroid_vs.h" +#include "asteroid_ps.h" + +#include "skybox_vs.h" +#include "skybox_ps.h" + +#include "sprite_vs.h" +#include "sprite_ps.h" +#include "font_ps.h" + +using namespace DirectX; + +namespace AsteroidsD3D12 { + +enum RootParameters +{ + RP_DRAW_CBV, + RP_TEX_SRV, + RP_SMP, +}; + +Asteroids::Asteroids(AsteroidsSimulation* asteroids, GUI *gui, UINT minCmdLsts, IDXGIAdapter* adapter) + : mAsteroids(asteroids) + , mGUI(gui) + , mFenceEventHandle(CreateEvent(NULL, FALSE, FALSE, NULL)) + , mD3D12Sprite( new GUISprite(5, 10, 140, 50, "directx12.dds") ) +{ + QueryPerformanceFrequency((LARGE_INTEGER*)&mPerfCounterFreq); + + memset(&mViewPort, 0, sizeof(mViewPort)); + memset(&mScissorRect, 0, sizeof(mScissorRect)); + memset(mAsteroidTextures, 0, sizeof(mAsteroidTextures)); + memset(mIndexOffsets, 0xff, sizeof(mIndexOffsets)); + +#if defined(_DEBUG) + // Enable the D3D12 debug layer. + { + ID3D12Debug* debugController = nullptr; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) + { + debugController->EnableDebugLayer(); + debugController->Release(); + } + } +#endif + + // Create device + { + ThrowIfFailed(D3D12CreateDevice( + adapter, + D3D_FEATURE_LEVEL_11_0, + IID_PPV_ARGS(&mDevice))); + + D3D12_COMMAND_QUEUE_DESC QDesc; + QDesc.NodeMask = 1; + QDesc.Priority = 0; + QDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + QDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + ThrowIfFailed(mDevice->CreateCommandQueue(&QDesc, IID_PPV_ARGS(&mCommandQueue))); + + ThrowIfFailed(mDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence))); + } + + // General use descriptor heaps + mRTVDescs = new RTVDescriptorList(mDevice, NUM_SWAP_CHAIN_BUFFERS); + mDSVDescs = new DSVDescriptorList(mDevice, 1); + mSMPDescs = new SMPDescriptorList(mDevice, 1); + mSRVDescs = new SRVDescriptorList(mDevice, NUM_UNIQUE_TEXTURES); + + // Filled in in Resize - just take slots for them here + mDepthStencilView = mDSVDescs->Append(); + mRTVFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + mDSVFormat = DXGI_FORMAT_D32_FLOAT; + + CreatePSOs(); + CreateMeshes(); + + // Create textures + { + // TODO: Query simulation for this data? Defines good enough for now... + D3D12_RESOURCE_DESC textureDesc = + CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, TEXTURE_DIM, TEXTURE_DIM, 3, 0); + + for (UINT i = 0; i < NUM_UNIQUE_TEXTURES; ++i) { + ThrowIfFailed(mDevice->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_COMMON, + nullptr, // Clear value + IID_PPV_ARGS(&mAsteroidTextures[i]) + )); + textureDesc = mAsteroidTextures[i]->GetDesc(); + + InitializeTexture2D(mDevice, mCommandQueue, mAsteroidTextures[i], &textureDesc, 4, mAsteroids->TextureData(i)); + + // Append a descriptor to the heap + mSRVDescs->AppendSRV(mAsteroidTextures[i]); + } + + ThrowIfFailed(CreateTexture2DFromDDS_XXXX8( + mDevice, mCommandQueue, &mSkybox, "starbox_1024.dds", DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)); + } + + CreateGUIResources(); + + // Fill in general heaps + { // Samplers + D3D12_SAMPLER_DESC sampler = {}; + sampler.Filter = D3D12_FILTER_ANISOTROPIC; + sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + sampler.MaxAnisotropy = TEXTURE_ANISO; + sampler.MinLOD = -std::numeric_limits<float>::max(); + sampler.MaxLOD = std::numeric_limits<float>::max(); + mSampler = mSMPDescs->Append(&sampler); + } + + // Swap chain resources + for (UINT s = 0; s < NUM_SWAP_CHAIN_BUFFERS; s++) { + // Filled in in resize, just make a slot here + mSwapChainBuffer[s].mRenderTargetView = mRTVDescs->Append(); + } + + // Per-frame resources + for (UINT f = 0; f < NUM_FRAMES_TO_BUFFER; f++) { + auto frame = &mFrame[f]; + ThrowIfFailed(mDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&frame->mCmdAlloc))); + + frame->mDynamicUpload = new UploadHeapT<DynamicUploadHeap>(mDevice); + auto dynamicUploadWO = frame->mDynamicUpload->DataWO(); + auto dynamicUploadGPUVA = frame->mDynamicUpload->Heap()->GetGPUVirtualAddress(); + + frame->mDrawConstantBuffersGPUVA = dynamicUploadGPUVA + offsetof(DynamicUploadHeap, mDrawConstantBuffers); + + // Set any static asteroid data now + auto staticData = mAsteroids->StaticData(); + for (int j = 0; j < NUM_ASTEROIDS; ++j) { + auto constants = &dynamicUploadWO->mDrawConstantBuffers[j]; + constants->mSurfaceColor = staticData[j].surfaceColor; + constants->mDeepColor = staticData[j].deepColor; + constants->mTextureIndex = staticData[j].textureIndex; + + auto indirectDraw = &dynamicUploadWO->mIndirectArgs[j]; + indirectDraw->mConstantBuffer = frame->mDrawConstantBuffersGPUVA + sizeof(DrawConstantBuffer) * j; + indirectDraw->mDrawIndexed.InstanceCount = 1; + indirectDraw->mDrawIndexed.StartInstanceLocation = 0; + indirectDraw->mDrawIndexed.BaseVertexLocation = staticData[j].vertexStart; + } + + // Dynamic sprite vertices + { + frame->mSpriteVertexBufferView.BufferLocation = dynamicUploadGPUVA + offsetof(DynamicUploadHeap, mSpriteVertices); + frame->mSpriteVertexBufferView.StrideInBytes = sizeof(SpriteVertex); + frame->mSpriteVertexBufferView.SizeInBytes = sizeof(SpriteVertex) * MAX_SPRITE_VERTICES_PER_FRAME; + } + + // General frame SRV descriptor heap + { + // We allocate a pile of extra space for dynamic descriptors (GUI, etc) + frame->mSRVDescs = new SRVDescriptorList(mDevice, 100); + + // Skybox constants + frame->mSkyboxConstants = dynamicUploadGPUVA + offsetof(DynamicUploadHeap, mSkyboxConstants); + + // Skybox texture + { + auto textureDesc = mSkybox->GetDesc(); + + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Format = textureDesc.Format; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = 1; + srvDesc.TextureCube.MostDetailedMip = 0; + srvDesc.TextureCube.ResourceMinLODClamp = 0.0f; + + frame->mSkyboxTexture = frame->mSRVDescs->AppendSRV(mSkybox, &srvDesc); + } + + // The rest of the heap we'll use for dynamically copy descriptors into, etc. + frame->mSRVDescsDynamicStart = frame->mSRVDescs->Size(); + } + } + + // Command Lists + ThrowIfFailed(mDevice->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, mFrame[0].mCmdAlloc, mAsteroidPSO, IID_PPV_ARGS(&mPostCmdLst))); + ThrowIfFailed(mPostCmdLst->Close()); // Avoid allocator issues... command lists really should be created in a "closed" state... + ThrowIfFailed(mDevice->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, mFrame[0].mCmdAlloc, mAsteroidPSO, IID_PPV_ARGS(&mPreCmdLst))); + ThrowIfFailed(mPreCmdLst->Close()); + + // Each command list for asteroid drawing maps 1:1 with a descriptor heap + // Change heaps is "free" at cmdlst boundaries and this greatly simplifies the code + // Thus the expectation is that we have ~ #threads heaps for multithreaded rendering on most GPUs + // Need at least one draw in each heap/cmd list... + minCmdLsts = std::min(minCmdLsts, (UINT)NUM_ASTEROIDS); + CreateSubsets(minCmdLsts); + std::cout << "Using " << mSubsetCount << " subsets per frame." << std::endl; + + // Just in case + WaitForAll(); +} + +Asteroids::~Asteroids() +{ + WaitForAll(); + ReleaseSwapChain(); + + SafeRelease(&mPreCmdLst); + SafeRelease(&mPostCmdLst); + + for (UINT i = 0; i < NUM_UNIQUE_TEXTURES; ++i) { + SafeRelease(&mAsteroidTextures[i]); + } + for (auto i : mSpriteTextures) { + i.second->Release(); + } + + SafeRelease(&mAsteroidPSO); + SafeRelease(&mFontTexture); + SafeRelease(&mFontPSO); + SafeRelease(&mSpritePSO); + SafeRelease(&mSkybox); + SafeRelease(&mSkyboxPSO); + + for (UINT f = 0; f < NUM_FRAMES_TO_BUFFER; ++f) { + auto frame = &mFrame[f]; + SafeRelease(&frame->mCmdAlloc); + delete frame->mDynamicUpload; + delete frame->mSRVDescs; + } + + ReleaseSubsets(); + + delete mMeshUpload; + + delete mRTVDescs; + delete mDSVDescs; + delete mSMPDescs; + delete mSRVDescs; + + SafeRelease(&mGenericRootSignature); + SafeRelease(&mAsteroidsRootSignature); + SafeRelease(&mCommandSignature); + SafeRelease(&mFence); + + SafeRelease(&mCommandQueue); + SafeRelease(&mDevice); + + if (mFenceEventHandle != NULL) { + CloseHandle(mFenceEventHandle); + mFenceEventHandle = NULL; + } + + delete mD3D12Sprite; +} + + +void Asteroids::ReleaseSwapChain() +{ + WaitForAll(); + + for (UINT s = 0; s < NUM_SWAP_CHAIN_BUFFERS; s++) { + SafeRelease(&mSwapChainBuffer[s].mRenderTarget); + } + SafeRelease(&mDepthStencil); + SafeRelease(&mSwapChain); +} + +inline void DisableDXGIWindowChanges(IUnknown* device, HWND window) +{ + IDXGIDevice * pDXGIDevice; + ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice))); + IDXGIAdapter * pDXGIAdapter; + ThrowIfFailed(pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter))); + IDXGIFactory * pIDXGIFactory; + ThrowIfFailed(pDXGIAdapter->GetParent(IID_PPV_ARGS(&pIDXGIFactory))); + + ThrowIfFailed(pIDXGIFactory->MakeWindowAssociation(window, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER)); + + pIDXGIFactory->Release(); + pDXGIAdapter->Release(); + pDXGIDevice->Release(); +} + +void Asteroids::ResizeSwapChain(IDXGIFactory2* dxgiFactory, HWND outputWindow, unsigned int width, unsigned int height) +{ + ReleaseSwapChain(); + + // Create swap chain + { + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // Can create an SRGB render target view on the swap chain buffer + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = NUM_SWAP_CHAIN_BUFFERS; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Not used + swapChainDesc.Flags = 0; + + IDXGISwapChain1 *swapChain1 = nullptr; + ThrowIfFailed(dxgiFactory->CreateSwapChainForHwnd( + mCommandQueue, outputWindow, &swapChainDesc, nullptr, nullptr, &swapChain1)); + // MakeWindowAssociation must be called after CreateSwapChain + ThrowIfFailed(dxgiFactory->MakeWindowAssociation(outputWindow, + DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_PRINT_SCREEN)); + ThrowIfFailed(swapChain1->QueryInterface(&mSwapChain)); + swapChain1->Release(); + } + + { + // Create an SRGB view of the swap chain buffer + D3D12_RENDER_TARGET_VIEW_DESC desc = {}; + desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + desc.Texture2D.MipSlice = 0; + desc.Texture2D.PlaneSlice = 0; + + // Create render target view for each swap chain buffer + for (UINT s = 0; s < NUM_SWAP_CHAIN_BUFFERS; s++) { + auto buffer = &mSwapChainBuffer[s]; + ThrowIfFailed(mSwapChain->GetBuffer(s, IID_PPV_ARGS(&buffer->mRenderTarget))); + mDevice->CreateRenderTargetView(buffer->mRenderTarget, &desc, buffer->mRenderTargetView); + } + } + + // create depth stencil view + { + D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D( + DXGI_FORMAT_D32_FLOAT, width, height, 1, 1, 1, 0, + D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL ); + + // We use (1-z) so typically clear depth to 0 + D3D12_CLEAR_VALUE clearValue = {}; + clearValue.Format = desc.Format; + clearValue.DepthStencil.Depth = 0.0f; + clearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(mDevice->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &desc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &clearValue, + IID_PPV_ARGS(&mDepthStencil) + )); + + mDevice->CreateDepthStencilView(mDepthStencil, nullptr, mDepthStencilView); + } + + // create the viewport and scissor + ZeroMemory(&mViewPort, sizeof(D3D11_VIEWPORT)); + mViewPort.TopLeftX = 0; + mViewPort.TopLeftY = 0; + mViewPort.Width = (float)width; + mViewPort.Height = (float)height; + mViewPort.MinDepth = 0.0f; + mViewPort.MaxDepth = 1.0f; + + mScissorRect.left = 0; + mScissorRect.top = 0; + mScissorRect.right = width; + mScissorRect.bottom = height; +} + +void Asteroids::CreatePSOs() +{ + // Generic root signature (t0, s0, b0) + { + CD3DX12_DESCRIPTOR_RANGE descRanges[2]; + descRanges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0); // t0 + descRanges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0); // s0 + + CD3DX12_ROOT_PARAMETER rootParams[3]; + rootParams[RP_DRAW_CBV].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); // b0 + rootParams[RP_TEX_SRV].InitAsDescriptorTable(1, &descRanges[0], D3D12_SHADER_VISIBILITY_PIXEL); // t0 + rootParams[RP_SMP].InitAsDescriptorTable(1, &descRanges[1], D3D12_SHADER_VISIBILITY_PIXEL); // s0 + + CD3DX12_ROOT_SIGNATURE_DESC RSLayout(ARRAYSIZE(rootParams), rootParams, 0, 0, + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS); + + ID3DBlob* serializedLayout = nullptr; + D3D12SerializeRootSignature(&RSLayout, D3D_ROOT_SIGNATURE_VERSION_1, &serializedLayout, 0); + + ThrowIfFailed(mDevice->CreateRootSignature( + 1, + serializedLayout->GetBufferPointer(), + serializedLayout->GetBufferSize(), + IID_PPV_ARGS(&mGenericRootSignature))); + + serializedLayout->Release(); + } + + // Asteroids root signature (tN, s0, b0) + { + CD3DX12_DESCRIPTOR_RANGE descRanges[2]; + descRanges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, NUM_UNIQUE_TEXTURES, 0, 0); // t0...tN + descRanges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0); // s0 + + CD3DX12_ROOT_PARAMETER rootParams[3]; + rootParams[RP_DRAW_CBV].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); // b0 + rootParams[RP_TEX_SRV].InitAsDescriptorTable(1, &descRanges[0], D3D12_SHADER_VISIBILITY_PIXEL); // t0 + rootParams[RP_SMP].InitAsDescriptorTable(1, &descRanges[1], D3D12_SHADER_VISIBILITY_PIXEL); // s0 + + CD3DX12_ROOT_SIGNATURE_DESC RSLayout(ARRAYSIZE(rootParams), rootParams, 0, 0, + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS); + + ID3DBlob* serializedLayout = nullptr; + D3D12SerializeRootSignature(&RSLayout, D3D_ROOT_SIGNATURE_VERSION_1, &serializedLayout, 0); + + ThrowIfFailed(mDevice->CreateRootSignature( + 1, + serializedLayout->GetBufferPointer(), + serializedLayout->GetBufferSize(), + IID_PPV_ARGS(&mAsteroidsRootSignature))); + + serializedLayout->Release(); + } + + // Command signature + { + D3D12_INDIRECT_ARGUMENT_DESC args[2] = {}; + args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW; + args[0].ConstantBufferView.RootParameterIndex = RP_DRAW_CBV; + args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; + + D3D12_COMMAND_SIGNATURE_DESC desc; + desc.ByteStride = sizeof(ExecuteIndirectArgs); + desc.NodeMask = 1; + desc.pArgumentDescs = args; + desc.NumArgumentDescs = ARRAYSIZE(args); + + ThrowIfFailed(mDevice->CreateCommandSignature(&desc, mGenericRootSignature, IID_PPV_ARGS(&mCommandSignature))); + } + + // Common state for this app + D3D12_GRAPHICS_PIPELINE_STATE_DESC defaultDesc = {}; + defaultDesc.BlendState = CD3DX12_BLEND_DESC(CD3DX12_DEFAULT()); + defaultDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(CD3DX12_DEFAULT()); + defaultDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(CD3DX12_DEFAULT()); + defaultDesc.pRootSignature = mGenericRootSignature; + defaultDesc.SampleMask = UINT_MAX; + defaultDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + defaultDesc.NumRenderTargets = 1; + defaultDesc.RTVFormats[0] = mRTVFormat; + defaultDesc.DSVFormat = mDSVFormat; + defaultDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; + defaultDesc.SampleDesc.Count = 1; + + // asteroid pipeline state + D3D12_INPUT_ELEMENT_DESC asteroidInputDesc[] = { + { "ATTRIB", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "ATTRIB", 1, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + D3D12_GRAPHICS_PIPELINE_STATE_DESC asteroidDesc = defaultDesc; + asteroidDesc.pRootSignature = mAsteroidsRootSignature; + asteroidDesc.VS = { g_asteroid_vs, sizeof(g_asteroid_vs) }; + asteroidDesc.PS = { g_asteroid_ps, sizeof(g_asteroid_ps) }; + asteroidDesc.InputLayout = { asteroidInputDesc, ARRAYSIZE(asteroidInputDesc) }; + + // skybox pipeline state + D3D12_INPUT_ELEMENT_DESC skyboxInputDesc[] = { + { "ATTRIB", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "ATTRIB", 1, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + D3D12_GRAPHICS_PIPELINE_STATE_DESC skyboxDesc = defaultDesc; + skyboxDesc.VS = { g_skybox_vs, sizeof(g_skybox_vs) }; + skyboxDesc.PS = { g_skybox_ps, sizeof(g_skybox_ps) }; + skyboxDesc.InputLayout = { skyboxInputDesc, ARRAYSIZE(skyboxInputDesc) }; + + // sprite pipeline state + D3D12_INPUT_ELEMENT_DESC spriteInputDesc[] = { + { "ATTRIB", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "ATTRIB", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + D3D12_GRAPHICS_PIPELINE_STATE_DESC spriteDesc = defaultDesc; + spriteDesc.VS = { g_sprite_vs, sizeof(g_sprite_vs) }; + spriteDesc.PS = { g_sprite_ps, sizeof(g_sprite_ps) }; + spriteDesc.InputLayout = { spriteInputDesc, ARRAYSIZE(spriteInputDesc) }; + spriteDesc.DepthStencilState.DepthEnable = FALSE; + // Premultiplied over blend + spriteDesc.BlendState.RenderTarget[0].BlendEnable = TRUE; + spriteDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; + spriteDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; + spriteDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + + // font pipeline state + D3D12_GRAPHICS_PIPELINE_STATE_DESC fontDesc = spriteDesc; + fontDesc.PS = { g_font_ps, sizeof(g_font_ps) }; + + concurrency::parallel_invoke( + [&] { ThrowIfFailed(mDevice->CreateGraphicsPipelineState(&asteroidDesc, IID_PPV_ARGS(&mAsteroidPSO))); }, + [&] { ThrowIfFailed(mDevice->CreateGraphicsPipelineState(&skyboxDesc, IID_PPV_ARGS(&mSkyboxPSO))); }, + [&] { ThrowIfFailed(mDevice->CreateGraphicsPipelineState(&spriteDesc, IID_PPV_ARGS(&mSpritePSO))); }, + [&] { ThrowIfFailed(mDevice->CreateGraphicsPipelineState(&fontDesc, IID_PPV_ARGS(&mFontPSO))); } + ); +} + + +void Asteroids::CreateSubsets(UINT numHeapsPerFrame) +{ + ReleaseSubsets(); + + mDrawsPerSubset = (NUM_ASTEROIDS + numHeapsPerFrame - 1) / numHeapsPerFrame; + mSubsetCount = numHeapsPerFrame; + + for (UINT f = 0; f < NUM_FRAMES_TO_BUFFER; f++) { + // Per-frame data + auto frame = &mFrame[f]; + auto dynamicUploadGPUVA = frame->mDynamicUpload->Heap()->GetGPUVirtualAddress(); + + for (UINT subsetIdx = 0; subsetIdx < mSubsetCount; ++subsetIdx) { + void* memory = _aligned_malloc(sizeof(SubsetD3D12), 64); + auto subset = new(memory) SubsetD3D12(mDevice, NUM_UNIQUE_TEXTURES, mAsteroidPSO); + frame->mSubsets.push_back(subset); + } + } +} + +void Asteroids::ReleaseSubsets() +{ + WaitForAll(); + + for (UINT i = 0; i < NUM_FRAMES_TO_BUFFER; ++i) { + for (auto j : mFrame[i].mSubsets) { + j->~SubsetD3D12(); + _aligned_free(j); + } + mFrame[i].mSubsets.clear(); + } + + mSubsetCount = 0; + mDrawsPerSubset = 0; +} + + +void Asteroids::CreateMeshes() +{ + auto asteroidMeshes = mAsteroids->Meshes(); + std::vector<SkyboxVertex> skyboxVertices; + CreateSkyboxMesh(&skyboxVertices); + + // Simple linear allocate + UINT64 asteroidVBSize = asteroidMeshes->vertices.size() * sizeof(asteroidMeshes->vertices[0]); + UINT64 asteroidIBSize = asteroidMeshes->indices.size() * sizeof(asteroidMeshes->indices[0]); + UINT64 skyboxVBSize = skyboxVertices.size() * sizeof(SkyboxVertex); + + UINT64 asteroidVBOffset = 0; + UINT64 asteroidIBOffset = asteroidVBOffset + asteroidVBSize; + UINT64 skyboxVBOffset = asteroidIBOffset + asteroidIBSize; + UINT64 totalSize = skyboxVBOffset + skyboxVBSize; + + mMeshUpload = new UploadHeap(mDevice, totalSize); + auto bufferWO = (BYTE*)mMeshUpload->DataWO(); + auto gpuVA = mMeshUpload->Heap()->GetGPUVirtualAddress(); + + // Asteroid vertices + { + memcpy(bufferWO + asteroidVBOffset, asteroidMeshes->vertices.data(), asteroidVBSize); + + mAsteroidVertexBufferView.BufferLocation = gpuVA + asteroidVBOffset; + mAsteroidVertexBufferView.SizeInBytes = static_cast<UINT>(asteroidVBSize); + mAsteroidVertexBufferView.StrideInBytes = sizeof(asteroidMeshes->vertices[0]); + } + + // Asteroid indices + { + memcpy(bufferWO + asteroidIBOffset, asteroidMeshes->indices.data(), asteroidIBSize); + + mAsteroidIndexBufferView.BufferLocation = gpuVA + asteroidIBOffset; + mAsteroidIndexBufferView.SizeInBytes = static_cast<UINT>(asteroidIBSize); + mAsteroidIndexBufferView.Format = sizeof(IndexType) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; + } + + // Skybox vertices + { + memcpy(bufferWO + skyboxVBOffset, skyboxVertices.data(), skyboxVBSize); + + mSkyboxVertexBufferView.BufferLocation = gpuVA + skyboxVBOffset; + mSkyboxVertexBufferView.SizeInBytes = static_cast<UINT>(skyboxVBSize); + mSkyboxVertexBufferView.StrideInBytes = sizeof(skyboxVertices[0]); + } +} + + +void Asteroids::CreateGUIResources() +{ + auto font = mGUI->Font(); + auto textureDesc = CD3DX12_RESOURCE_DESC::Tex2D( + DXGI_FORMAT_R8_UNORM, font->BitmapWidth(), font->BitmapHeight(), 1, 1); + + ThrowIfFailed(mDevice->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_COMMON, + nullptr, + IID_PPV_ARGS(&mFontTexture) + )); + + D3D11_SUBRESOURCE_DATA initialData = {}; + initialData.pSysMem = font->Pixels(); + initialData.SysMemPitch = font->BitmapWidth(); + + InitializeTexture2D(mDevice, mCommandQueue, mFontTexture, &textureDesc, 1, &initialData); + + // Load any GUI sprite textures + for (int i = -1; i < (int)mGUI->size(); ++i) { + auto control = i>=0 ? (*mGUI)[i] : mD3D12Sprite; + if (control->TextureFile().length() > 0 && mSpriteTextures.find(control->TextureFile()) == mSpriteTextures.end()) { + ID3D12Resource* texture = nullptr; + ThrowIfFailed(CreateTexture2DFromDDS_XXXX8( + mDevice, mCommandQueue, &texture, control->TextureFile().c_str(), DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)); + mSpriteTextures[control->TextureFile()] = texture; + } + } +} + +void Asteroids::WaitForAll() +{ + ThrowIfFailed(mCommandQueue->Signal(mFence, ++mCurrentFence)); + ThrowIfFailed(mFence->SetEventOnCompletion(mCurrentFence, mFenceEventHandle)); + WaitForSingleObject(mFenceEventHandle, INFINITE); +} + +void Asteroids::WaitForReadyToRender() +{ + // Wait for both the GPU to be done with our per-frame resources + HANDLE handles[] = { mFenceEventHandle }; + + ThrowIfFailed(mFence->SetEventOnCompletion(mFrame[mCurrentFrameIndex].mFrameCompleteFence, mFenceEventHandle)); + WaitForMultipleObjects(ARRAYSIZE(handles), handles, TRUE, INFINITE); +} + +void Asteroids::RenderSubset( + D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView, + size_t frameIndex, float frameTime, + SubsetD3D12* subset, UINT subsetIdx, + XMVECTOR cameraEye, XMMATRIX viewProjection, + const Settings& settings) +{ + UINT drawStart = mDrawsPerSubset * subsetIdx; + UINT drawEnd = std::min(drawStart + mDrawsPerSubset, (UINT)NUM_ASTEROIDS); + assert(drawStart < drawEnd); + auto staticAsteroidData = mAsteroids->StaticData(); + auto dynamicAsteroidData = mAsteroids->DynamicData(); + // Frame data + auto frame = &mFrame[frameIndex]; + auto drawConstantBuffers = frame->mDynamicUpload->DataWO()->mDrawConstantBuffers; + auto indirectArgs = frame->mDynamicUpload->DataWO()->mIndirectArgs; + + auto cmdLst = subset->Begin(mAsteroidPSO); + + // Root signature and common bindings + cmdLst->SetGraphicsRootSignature(mAsteroidsRootSignature); + ID3D12DescriptorHeap* heaps[2] = {mSRVDescs->Heap(), mSMPDescs->Heap()}; + cmdLst->SetDescriptorHeaps(ARRAYSIZE(heaps), heaps); + + // Common state + cmdLst->IASetIndexBuffer(&mAsteroidIndexBufferView); + cmdLst->IASetVertexBuffers(0, 1, &mAsteroidVertexBufferView); + cmdLst->RSSetViewports(1, &mViewPort); + cmdLst->RSSetScissorRects(1, &mScissorRect); + cmdLst->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + cmdLst->OMSetRenderTargets(1, &renderTargetView, true, &mDepthStencilView); + + // Set textures (all as a single descriptor table) and samplers + cmdLst->SetGraphicsRootDescriptorTable(RP_TEX_SRV, mSRVDescs->GPU(0)); + cmdLst->SetGraphicsRootDescriptorTable(RP_SMP, mSampler); + + if (!settings.executeIndirect) + { + // Standard draw path + auto constantsPointer = frame->mDrawConstantBuffersGPUVA + sizeof(DrawConstantBuffer) * drawStart; + for (UINT drawIdx = drawStart; drawIdx < drawEnd; ++drawIdx) + { + auto staticData = &staticAsteroidData[drawIdx]; + auto dynamicData = &dynamicAsteroidData[drawIdx]; + + XMStoreFloat4x4(&drawConstantBuffers[drawIdx].mWorld, dynamicData->world); + XMStoreFloat4x4(&drawConstantBuffers[drawIdx].mViewProjection, viewProjection); + + // Set root cbuffer + //cmdLst->SetGraphicsRootDescriptorTable(RP_TEX_SRV, mSRVDescs->GPU(0)); + cmdLst->SetGraphicsRootConstantBufferView(RP_DRAW_CBV, constantsPointer); + constantsPointer += sizeof(DrawConstantBuffer); + + cmdLst->DrawIndexedInstanced(dynamicData->indexCount, 1, dynamicData->indexStart, staticData->vertexStart, 0); + } + } + else + { + // ExecuteIndirect path + for (UINT drawIdx = drawStart; drawIdx < drawEnd; ++drawIdx) + { + auto dynamicData = &dynamicAsteroidData[drawIdx]; + + XMStoreFloat4x4(&drawConstantBuffers[drawIdx].mWorld, dynamicData->world); + XMStoreFloat4x4(&drawConstantBuffers[drawIdx].mViewProjection, viewProjection); + + auto drawIndexed = &indirectArgs[drawIdx].mDrawIndexed; + drawIndexed->IndexCountPerInstance = dynamicData->indexCount; + drawIndexed->StartIndexLocation = dynamicData->indexStart; + } + + UINT64 offset = (BYTE*)(&indirectArgs[drawStart]) - (BYTE*)frame->mDynamicUpload->DataWO(); + cmdLst->ExecuteIndirect(mCommandSignature, drawEnd - drawStart, + frame->mDynamicUpload->Heap(), offset, + nullptr, 0); + } + + subset->End(); +} + +void Asteroids::Render(float frameTime, const OrbitCamera& camera, const Settings& settings) +{ + // Pick the right swap chain buffer based on where DXGI says we are... + auto backBufferIndex = mSwapChain->GetCurrentBackBufferIndex(); + assert(backBufferIndex < NUM_SWAP_CHAIN_BUFFERS); + auto swapChainBuffer = &mSwapChainBuffer[backBufferIndex]; + + // And the right frame data based on our own rotation/fences + assert(mCurrentFrameIndex < NUM_FRAMES_TO_BUFFER); + auto frame = &mFrame[mCurrentFrameIndex]; + + QueryPerformanceCounter((LARGE_INTEGER*)&mTotalUpdateTicks); + // Update asteroid simulation + if (settings.multithreadedRendering) + { + concurrency::parallel_for<UINT>(0, mSubsetCount, [&](UINT subsetIdx) { + UINT drawStart = mDrawsPerSubset * subsetIdx; + UINT drawEnd = std::min(drawStart + mDrawsPerSubset, (UINT)NUM_ASTEROIDS); + mAsteroids->Update(frameTime, camera.Eye(), settings, drawStart, drawEnd - drawStart); + }); + } + else + { + mAsteroids->Update(frameTime, camera.Eye(), settings, 0, (UINT)NUM_ASTEROIDS); + } + LONG64 currCounter; + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + mTotalUpdateTicks = currCounter - mTotalUpdateTicks; + + mTotalRenderTicks = currCounter; + // Generate command lists + if (settings.multithreadedRendering) + { + concurrency::parallel_for<UINT>(0, mSubsetCount, [&](UINT subsetIdx) { + RenderSubset(swapChainBuffer->mRenderTargetView, mCurrentFrameIndex, frameTime, + frame->mSubsets[subsetIdx], subsetIdx, camera.Eye(), camera.ViewProjection(), settings); + }); + } + else + { + LONG64 SubsetUpdateTicks = 0, SubsetRenderTicks = 0; + for (unsigned int subsetIdx = 0; subsetIdx < mSubsetCount; ++subsetIdx) { + RenderSubset(swapChainBuffer->mRenderTargetView, mCurrentFrameIndex, frameTime, + frame->mSubsets[subsetIdx], subsetIdx, camera.Eye(), camera.ViewProjection(), settings); + } + } + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + mTotalRenderTicks = currCounter - mTotalRenderTicks; + + LONG64 prevCounter = currCounter; + // Set up pre and post commands + { + auto cmdAlloc = frame->mCmdAlloc; + auto dynamicUploadWO = frame->mDynamicUpload->DataWO(); + ThrowIfFailed(cmdAlloc->Reset()); + + // Set resource states for rendering + ResourceBarrier rb; + rb.AddTransition(swapChainBuffer->mRenderTarget, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); + + // Pre + { + ThrowIfFailed(mPreCmdLst->Reset(cmdAlloc, mAsteroidPSO)); + rb.Submit(mPreCmdLst); + + // Don't need to clear color at the moment - skybox overwrites it all and no MSAA + //float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + //mPreCmdLst->ClearRenderTargetView(swapChainBuffer->mRenderTargetView, clearcol, 0, 0); + + // Clear depth + mPreCmdLst->ClearDepthStencilView(mDepthStencilView, D3D12_CLEAR_FLAG_DEPTH, 0.0f, 0, 0, nullptr); + + ThrowIfFailed(mPreCmdLst->Close()); + } + + rb.ReverseTransitions(); + + // Post + { + ThrowIfFailed(mPostCmdLst->Reset(cmdAlloc, mSkyboxPSO)); + + // Root signature and descriptor heaps + mPostCmdLst->SetGraphicsRootSignature(mGenericRootSignature); + ID3D12DescriptorHeap* heaps[2] = { frame->mSRVDescs->Heap(), mSMPDescs->Heap() }; + mPostCmdLst->SetDescriptorHeaps(2, heaps); + + mPostCmdLst->SetGraphicsRootDescriptorTable(RP_SMP, mSampler); + + // Common state + mPostCmdLst->RSSetViewports(1, &mViewPort); + mPostCmdLst->RSSetScissorRects(1, &mScissorRect); + mPostCmdLst->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + mPostCmdLst->OMSetRenderTargets(1, &swapChainBuffer->mRenderTargetView, true, &mDepthStencilView); + + // Draw skybox + { + auto constants = &frame->mDynamicUpload->DataWO()->mSkyboxConstants; + XMStoreFloat4x4(&constants->mViewProjection, camera.ViewProjection()); + + mPostCmdLst->IASetVertexBuffers(0, 1, &mSkyboxVertexBufferView); + + mPostCmdLst->SetGraphicsRootConstantBufferView(RP_DRAW_CBV, frame->mSkyboxConstants); + mPostCmdLst->SetGraphicsRootDescriptorTable(RP_TEX_SRV, frame->mSkyboxTexture); + mPostCmdLst->DrawInstanced(6 * 6, 1, 0, 0); + } + + // Draw sprites + { + auto vertexBase = dynamicUploadWO->mSpriteVertices; + auto vertexEnd = vertexBase; + + // Drop off any dynamic descriptors from the last frame + auto descHeap = frame->mSRVDescs; + descHeap->Resize(frame->mSRVDescsDynamicStart); + + mPostCmdLst->IASetVertexBuffers(0, 1, &frame->mSpriteVertexBufferView); + + for (int i = -1; i < (int)mGUI->size(); ++i) { + auto control = i >=0 ? (*mGUI)[i] : mD3D12Sprite; + if (!control->Visible()) continue; + + UINT numVertices = (UINT)(control->Draw(mViewPort.Width, mViewPort.Height, vertexEnd) - vertexEnd); + ID3D12Resource* texture = nullptr; + + // TODO: Could eliminate redundant state setting and cache descriptors... meh for now. + if (control->TextureFile().length() == 0) { // Font + mPostCmdLst->SetPipelineState(mFontPSO); + texture = mFontTexture; + } + else { // Sprite + mPostCmdLst->SetPipelineState(mSpritePSO); + texture = mSpriteTextures[control->TextureFile()]; + } + + if (texture) { + mPostCmdLst->SetGraphicsRootDescriptorTable(RP_TEX_SRV, descHeap->AppendSRV(texture)); + } + + mPostCmdLst->DrawInstanced(numVertices, 1, (UINT)(vertexEnd - vertexBase), 0); + vertexEnd += numVertices; + } + } + + // Final resource state transitions + rb.Submit(mPostCmdLst); + ThrowIfFailed(mPostCmdLst->Close()); + } + } + + // Set up command lists for submission + mCmdListsToSubmit.resize(0); + mCmdListsToSubmit.push_back(mPreCmdLst); + if (settings.submitRendering) { + for (auto &i :frame->mSubsets) + mCmdListsToSubmit.push_back(i->mCmdLst); + } + mCmdListsToSubmit.push_back(mPostCmdLst); + + mCommandQueue->ExecuteCommandLists( + (UINT)mCmdListsToSubmit.size(), + CommandListCast(mCmdListsToSubmit.data())); + + if (settings.vsync) + ThrowIfFailed(mSwapChain->Present(1, 0)); + else + ThrowIfFailed(mSwapChain->Present(0, 0)); + + ThrowIfFailed(mCommandQueue->Signal(mFence, ++mCurrentFence)); + frame->mFrameCompleteFence = mCurrentFence; + mCurrentFrameIndex = (mCurrentFrameIndex + 1) % NUM_FRAMES_TO_BUFFER; + + //LONG64 currCounter; + QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); + mTotalRenderTicks += currCounter - prevCounter; +} + +void Asteroids::GetPerfCounters(float &UpdateTime, float &RenderTime) +{ + UpdateTime = (float)mTotalUpdateTicks/(float)mPerfCounterFreq; + RenderTime = (float)mTotalRenderTicks/(float)mPerfCounterFreq; +} + +} // namespace AsteroidsD3D12 diff --git a/Projects/Asteroids/src/asteroids_d3d12.h b/Projects/Asteroids/src/asteroids_d3d12.h new file mode 100644 index 0000000..3021d28 --- /dev/null +++ b/Projects/Asteroids/src/asteroids_d3d12.h @@ -0,0 +1,182 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include <d3d11.h> +#include <d3d12.h> +#include <dxgi1_4.h> +#include <directxmath.h> +#include <deque> +#include <random> +#include <map> + +#include "camera.h" +#include "settings.h" +#include "simulation.h" +#include "subset_d3d12.h" +#include "descriptor.h" +#include "upload_heap.h" +#include "util.h" +#include "gui.h" + +namespace AsteroidsD3D12 { + +CBUFFER_ALIGN struct DrawConstantBuffer { + DirectX::XMFLOAT4X4 mWorld; + DirectX::XMFLOAT4X4 mViewProjection; + DirectX::XMFLOAT3 mSurfaceColor; + float unused0; + DirectX::XMFLOAT3 mDeepColor; + float unused1; + UINT mTextureIndex; +}; + +CBUFFER_ALIGN struct SkyboxConstantBuffer { + DirectX::XMFLOAT4X4 mViewProjection; +}; + +struct ExecuteIndirectArgs { + D3D12_GPU_VIRTUAL_ADDRESS mConstantBuffer; + D3D12_DRAW_INDEXED_ARGUMENTS mDrawIndexed; +}; + +struct DynamicUploadHeap { + DrawConstantBuffer mDrawConstantBuffers[NUM_ASTEROIDS]; + SkyboxConstantBuffer mSkyboxConstants; + ExecuteIndirectArgs mIndirectArgs[NUM_ASTEROIDS]; + SpriteVertex mSpriteVertices[MAX_SPRITE_VERTICES_PER_FRAME]; +}; + +class Asteroids { +public: + Asteroids(AsteroidsSimulation* asteroids, GUI *gui, UINT minCmdLsts, IDXGIAdapter* adapter); + ~Asteroids(); + + void WaitForReadyToRender(); + void Render(float frameTime, const OrbitCamera& camera, const Settings& settings); + + void ReleaseSwapChain(); + void ResizeSwapChain(IDXGIFactory2* dxgiFactory, HWND outputWindow, unsigned int width, unsigned int height); + + void GetPerfCounters(float &UpdateTime, float &RenderTime); + +private: + void WaitForAll(); + + void RenderSubset( + D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView, + size_t frameIndex, float frameTime, + SubsetD3D12* subset, UINT subsetIdx, + DirectX::XMVECTOR cameraEye, DirectX::XMMATRIX viewProjection, + const Settings& settings); + + void CreatePSOs(); + + void CreateSubsets(UINT numHeapsPerFrame); + void ReleaseSubsets(); + + void CreateMeshes(); + void CreateGUIResources(); + + struct Frame { + std::vector<SubsetD3D12*> mSubsets; + ID3D12CommandAllocator* mCmdAlloc = nullptr; + + UploadHeapT<DynamicUploadHeap>* mDynamicUpload = nullptr; + D3D12_VERTEX_BUFFER_VIEW mSpriteVertexBufferView; + D3D12_GPU_VIRTUAL_ADDRESS mDrawConstantBuffersGPUVA; + + // Descriptor heap and associated GPU handles + SRVDescriptorList* mSRVDescs = nullptr; + D3D12_GPU_VIRTUAL_ADDRESS mSkyboxConstants; + D3D12_GPU_DESCRIPTOR_HANDLE mSkyboxTexture; + UINT mSRVDescsDynamicStart = 0; + + UINT64 mFrameCompleteFence = 0; + } mFrame[NUM_FRAMES_TO_BUFFER]; + + // Swap chain resources + struct SwapChainBuffer { + ID3D12Resource* mRenderTarget = nullptr; + D3D12_CPU_DESCRIPTOR_HANDLE mRenderTargetView; + } mSwapChainBuffer[NUM_SWAP_CHAIN_BUFFERS]; + + // Swap chain stuff + IDXGISwapChain3* mSwapChain = nullptr; + DXGI_FORMAT mRTVFormat; + D3D12_VIEWPORT mViewPort; + D3D11_RECT mScissorRect; + + // Fences and synchronization + size_t mCurrentFrameIndex = 0; + ID3D12Fence* mFence = nullptr; + HANDLE mFenceEventHandle = NULL; + UINT64 mCurrentFence = 0; + + // Device + ID3D12Device* mDevice = nullptr; + ID3D12CommandQueue* mCommandQueue = nullptr; + + // Root signature, descriptors and binding + ID3D12RootSignature* mGenericRootSignature = nullptr; + ID3D12RootSignature* mAsteroidsRootSignature = nullptr; + ID3D12CommandSignature* mCommandSignature = nullptr; + RTVDescriptorList* mRTVDescs = nullptr; + DSVDescriptorList* mDSVDescs = nullptr; + SRVDescriptorList* mSRVDescs = nullptr; + SMPDescriptorList* mSMPDescs = nullptr; + D3D12_CPU_DESCRIPTOR_HANDLE mDepthStencilView; + D3D12_GPU_DESCRIPTOR_HANDLE mSampler; + D3D12_VERTEX_BUFFER_VIEW mSkyboxVertexBufferView; + D3D12_INDEX_BUFFER_VIEW mAsteroidIndexBufferView; + D3D12_VERTEX_BUFFER_VIEW mAsteroidVertexBufferView; + + // Command lists + ID3D12GraphicsCommandList* mPreCmdLst = nullptr; + ID3D12GraphicsCommandList* mPostCmdLst = nullptr; + + DXGI_FORMAT mDSVFormat; + ID3D12Resource* mDepthStencil = nullptr; + + AsteroidsSimulation* mAsteroids = nullptr; + ID3D12Resource* mAsteroidTextures[NUM_UNIQUE_TEXTURES]; + + // Mesh + UploadHeap* mMeshUpload = nullptr; + UINT mIndexOffsets[MESH_MAX_SUBDIV_LEVELS + 2]; // inclusive + UINT mNumVerticesPerMesh = 0; + + ID3D12PipelineState* mAsteroidPSO = nullptr; + + ID3D12PipelineState* mSkyboxPSO = nullptr; + ID3D12Resource* mSkybox = nullptr; + + ID3D12PipelineState* mFontPSO = nullptr; + ID3D12Resource* mFontTexture = nullptr; + + ID3D12PipelineState* mSpritePSO = nullptr; + std::map<std::string, ID3D12Resource*> mSpriteTextures; + + GUI* mGUI = nullptr; + + // Transient, just here to avoid allocations each frame + std::vector<ID3D12GraphicsCommandList*> mCmdListsToSubmit; + + UINT mSubsetCount = 0; + UINT mDrawsPerSubset = 0; + + GUISprite* mD3D12Sprite = nullptr; + + UINT64 mPerfCounterFreq = 0; + volatile LONG64 mTotalUpdateTicks = 0, mTotalRenderTicks = 0; +}; + +} // namespace AsteroidsD3D12 diff --git a/Projects/Asteroids/src/asteroids_d3d12.ico b/Projects/Asteroids/src/asteroids_d3d12.ico Binary files differnew file mode 100644 index 0000000..449296f --- /dev/null +++ b/Projects/Asteroids/src/asteroids_d3d12.ico diff --git a/Projects/Asteroids/src/camera.cpp b/Projects/Asteroids/src/camera.cpp new file mode 100644 index 0000000..ac5ceec --- /dev/null +++ b/Projects/Asteroids/src/camera.cpp @@ -0,0 +1,170 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#include "camera.h" +#include "util.h" +#include <algorithm> + +using namespace DirectX; + + +OrbitCamera::OrbitCamera() +{ + // Defaults + mCenter = XMVectorSet(0, 0, 0, 0); + mUp = XMVectorSet(0, 1, 0, 0); + mRadius = 1.0f; + mMinRadius = 1.0f; + mMaxRadius = 1.0f; + mLongAngle = 0.0f; + mLatAngle = 0.0f; + + // Set up interaction context (i.e. touch input processing, etc) + ThrowIfFailed(CreateInteractionContext(&mInteractionContext)); + ThrowIfFailed(SetPropertyInteractionContext(mInteractionContext, INTERACTION_CONTEXT_PROPERTY_FILTER_POINTERS, TRUE)); + + { + INTERACTION_CONTEXT_CONFIGURATION config[] = + { + {INTERACTION_ID_MANIPULATION, + INTERACTION_CONFIGURATION_FLAG_MANIPULATION | + INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_X | + INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_Y | + INTERACTION_CONFIGURATION_FLAG_MANIPULATION_SCALING | + INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_INERTIA | + INTERACTION_CONFIGURATION_FLAG_MANIPULATION_SCALING_INERTIA | + INTERACTION_CONFIGURATION_FLAG_MANIPULATION_MULTIPLE_FINGER_PANNING + }, + }; + + ThrowIfFailed(SetInteractionConfigurationInteractionContext(mInteractionContext, ARRAYSIZE(config), config)); + } + + ThrowIfFailed(RegisterOutputCallbackInteractionContext(mInteractionContext, OrbitCamera::StaticInteractionOutputCallback, this)); +} + + +OrbitCamera::~OrbitCamera() +{ + DestroyInteractionContext(mInteractionContext); +} + + +void OrbitCamera::View( + DirectX::XMVECTOR center, float radius, float minRadius, float maxRadius, + float longAngle, float latAngle) +{ + mCenter = center; + mRadius = radius; + mMinRadius = minRadius; + mMaxRadius = maxRadius; + mLongAngle = longAngle; + mLatAngle = latAngle; + UpdateData(); +} + + +void OrbitCamera::Projection(float fov, float aspect) +{ + float fovY = (aspect <= 1.0 ? fov : fov / aspect); + mProjection = XMMatrixPerspectiveFovRH(fovY, aspect, 10000.0f, 0.1f); + UpdateData(); +} + + +void OrbitCamera::UpdateData() +{ + mEye = XMVectorSet( + mRadius * std::sin(mLatAngle) * std::cos(mLongAngle), + mRadius * std::cos(mLatAngle), + mRadius * std::sin(mLatAngle) * std::sin(mLongAngle), + 0.0f); + + mView = XMMatrixLookAtRH(mEye, mCenter, mUp); + mViewProjection = XMMatrixMultiply(mView, mProjection); +} + + +void OrbitCamera::OrbitX(float angle) +{ + mLongAngle += angle; + UpdateData(); +} + + +void OrbitCamera::OrbitY(float angle) +{ + float limit = XM_PI * 0.01f; + mLatAngle = std::max(limit, std::min(XM_PI-limit, mLatAngle + angle)); + UpdateData(); +} + + +void OrbitCamera::ZoomRadius(float delta) +{ + mRadius = std::max(mMinRadius, std::min(mMaxRadius, mRadius + delta)); + UpdateData(); +} + +void OrbitCamera::ZoomRadiusScale(float delta) +{ + mRadius = std::max(mMinRadius, std::min(mMaxRadius, mRadius * delta)); + UpdateData(); +} + + +void OrbitCamera::AddPointer(UINT pointerId) +{ + AddPointerInteractionContext(mInteractionContext, pointerId); +} + + +void OrbitCamera::ProcessPointerFrames(UINT pointerId, const POINTER_INFO* pointerInfo) +{ + ProcessPointerFramesInteractionContext(mInteractionContext, 1, 1, pointerInfo); +} + + +void OrbitCamera::RemovePointer(UINT pointerId) +{ + RemovePointerInteractionContext(mInteractionContext, pointerId); +} + + +void OrbitCamera::ProcessInertia() +{ + ProcessInertiaInteractionContext(mInteractionContext); +} + + +VOID CALLBACK OrbitCamera::StaticInteractionOutputCallback(VOID *clientData, const INTERACTION_CONTEXT_OUTPUT *output) +{ + auto camera = reinterpret_cast<OrbitCamera*>(clientData); + camera->InteractionOutputCallback(output); +} + + +void OrbitCamera::InteractionOutputCallback(const INTERACTION_CONTEXT_OUTPUT *output) +{ + switch(output->interactionId) + { + case INTERACTION_ID_MANIPULATION: { + auto delta = &output->arguments.manipulation.delta; + OrbitX(delta->translationX * 0.0007f); + OrbitY(-delta->translationY * 0.0007f); + ZoomRadiusScale(1.0f / delta->scale); + + break; + } + + default: + break; + } +} diff --git a/Projects/Asteroids/src/camera.h b/Projects/Asteroids/src/camera.h new file mode 100644 index 0000000..69ffc3f --- /dev/null +++ b/Projects/Asteroids/src/camera.h @@ -0,0 +1,62 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include <DirectXMath.h> +#include <interactioncontext.h> + +class OrbitCamera +{ +public: + OrbitCamera(); + ~OrbitCamera(); + + void View(DirectX::XMVECTOR center, + float radius, float minRadius, float maxRadius, + float longAngle, float latAngle); + + // Uses the provided fov for the larger dimension + void Projection(float fov, float aspect); + + DirectX::XMVECTOR const& Eye() const { return mEye; } + DirectX::XMMATRIX const& ViewProjection() const { return mViewProjection; } + + void AddPointer(UINT pointerId); + void ProcessPointerFrames(UINT pointerId, const POINTER_INFO* pointerInfo); + void ProcessInertia(); + void RemovePointer(UINT pointerId); + + void OrbitX(float angle); + void OrbitY(float angle); + void ZoomRadius(float delta); + void ZoomRadiusScale(float delta); + +private: + void UpdateData(); + static VOID CALLBACK StaticInteractionOutputCallback(VOID *clientData, const INTERACTION_CONTEXT_OUTPUT *output); + void InteractionOutputCallback(const INTERACTION_CONTEXT_OUTPUT *output); + + DirectX::XMVECTOR mCenter; + DirectX::XMVECTOR mUp; + float mMinRadius; + float mMaxRadius; + + float mLatAngle; + float mLongAngle; + float mRadius; + + DirectX::XMVECTOR mEye; + DirectX::XMMATRIX mView; + DirectX::XMMATRIX mProjection; + DirectX::XMMATRIX mViewProjection; + + HINTERACTIONCONTEXT mInteractionContext; +}; diff --git a/Projects/Asteroids/src/common.hlsl b/Projects/Asteroids/src/common.hlsl new file mode 100644 index 0000000..3609db6 --- /dev/null +++ b/Projects/Asteroids/src/common.hlsl @@ -0,0 +1,45 @@ +#ifndef COMMON_HLSL +#define COMMON_HLSL + +struct VSIn +{ + float3 position : POSITION; + float3 normal : NORMAL; +}; + +struct VSOut +{ + float4 position : SV_Position; + float3 positionModel : POSITIONMODEL; + float3 normalWorld : NORMAL; + float3 albedo : ALBEDO; // Alternatively, can pass just "ao" to PS and read cbuffer in PS +}; + + +struct Skybox_VSIn +{ + float3 position : POSITION; + float3 uvFace : UVFACE; +}; + +struct Skybox_VSOut +{ + float4 position : SV_Position; + float3 coords : UVFACE; +}; + + +struct Font_VSIn +{ + float2 position : POSITION; + float2 uv : UV; +}; + +struct Font_VSOut +{ + float4 position : SV_Position; + float2 uv : UV; +}; + + +#endif diff --git a/Projects/Asteroids/src/common_defines.h b/Projects/Asteroids/src/common_defines.h new file mode 100644 index 0000000..4af7169 --- /dev/null +++ b/Projects/Asteroids/src/common_defines.h @@ -0,0 +1,6 @@ +#ifndef COMMON_H +#define COMMON_H + +#define NUM_UNIQUE_TEXTURES 10 + +#endif diff --git a/Projects/Asteroids/src/dds.h b/Projects/Asteroids/src/dds.h new file mode 100644 index 0000000..65fe730 --- /dev/null +++ b/Projects/Asteroids/src/dds.h @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// dds.h +// +// This header defines constants and structures that are useful when parsing +// DDS files. DDS files were originally designed to use several structures +// and constants that are native to DirectDraw and are defined in ddraw.h, +// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar +// (compatible) constants and structures so that one can use DDS files +// without needing to include ddraw.h. +//-------------------------------------------------------------------------------------- + +#ifndef _DDS_H_ +#define _DDS_H_ + +#include <dxgiformat.h> +#include <d3d11.h> + +#pragma pack(push,1) + +#define DDS_MAGIC 0x20534444 // "DDS " + +struct DDS_PIXELFORMAT +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwFourCC; + DWORD dwRGBBitCount; + DWORD dwRBitMask; + DWORD dwGBitMask; + DWORD dwBBitMask; + DWORD dwABitMask; +}; + +#define DDS_FOURCC 0x00000004 // DDPF_FOURCC +#define DDS_RGB 0x00000040 // DDPF_RGB +#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#define DDS_ALPHA 0x00000002 // DDPF_ALPHA + +const DDS_PIXELFORMAT DDSPF_DXT1 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; + +const DDS_PIXELFORMAT DDSPF_DXT2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 }; + +const DDS_PIXELFORMAT DDSPF_DXT3 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 }; + +const DDS_PIXELFORMAT DDSPF_DXT4 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 }; + +const DDS_PIXELFORMAT DDSPF_DXT5 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 }; + +const DDS_PIXELFORMAT DDSPF_A8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; + +const DDS_PIXELFORMAT DDSPF_A1R5G5B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 }; + +const DDS_PIXELFORMAT DDSPF_A4R4G4B4 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 }; + +const DDS_PIXELFORMAT DDSPF_R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +const DDS_PIXELFORMAT DDSPF_R5G6B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 }; + +// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) +const DDS_PIXELFORMAT DDSPF_DX10 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 }; + +#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT +#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT +#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH +#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH +#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + +#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT +#define DDS_WIDTH 0x00000004 // DDSD_WIDTH + +#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE +#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP +#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX + +#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX +#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX +#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY +#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY +#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ +#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + +#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) + +#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + +#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME + +// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION +typedef enum DDS_RESOURCE_DIMENSION +{ + DDS_DIMENSION_TEXTURE1D = 2, + DDS_DIMENSION_TEXTURE2D = 3, + DDS_DIMENSION_TEXTURE3D = 4, +} DDS_RESOURCE_DIMENSION; + +// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG +typedef enum DDS_RESOURCE_MISC_FLAG +{ + DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L, +} DDS_RESOURCE_MISC_FLAG; + +typedef struct +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwHeight; + DWORD dwWidth; + DWORD dwPitchOrLinearSize; + DWORD dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags + DWORD dwMipMapCount; + DWORD dwReserved1[11]; + DDS_PIXELFORMAT ddspf; + DWORD dwCaps; + DWORD dwCaps2; + DWORD dwCaps3; + DWORD dwCaps4; + DWORD dwReserved2; +} DDS_HEADER; + +typedef struct +{ + DXGI_FORMAT dxgiFormat; + UINT resourceDimension; + DWORD miscFlag; // see DDS_RESOURCE_MISC_FLAG + UINT arraySize; + UINT reserved; +} DDS_HEADER_DXT10; + +#pragma pack(pop) + +#endif // _DDS_H diff --git a/Projects/Asteroids/src/descriptor.h b/Projects/Asteroids/src/descriptor.h new file mode 100644 index 0000000..4c87286 --- /dev/null +++ b/Projects/Asteroids/src/descriptor.h @@ -0,0 +1,165 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include "util.h" + +#include <assert.h> +#include <d3d12.h> +#include <d3dx12.h> + +// Used for CPU-only desriptors; simple linear allocator. +class DescriptorArray +{ +public: + // device must live for the lifetime of this object (no explicit refcount increment) + DescriptorArray(ID3D12Device* device, UINT maxDescriptors, D3D12_DESCRIPTOR_HEAP_TYPE type, + bool shaderVisible = false) + : mDevice(device) + , mMaxSize(maxDescriptors) + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.Type = type; + desc.Flags = shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + desc.NumDescriptors = mMaxSize; + + ThrowIfFailed(mDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&mHeap))); + + mCPUBegin = mHeap->GetCPUDescriptorHandleForHeapStart(); + mHandleIncrementSize = mDevice->GetDescriptorHandleIncrementSize(desc.Type); + + if (shaderVisible) { + mGPUBegin = mHeap->GetGPUDescriptorHandleForHeapStart(); + } + } + + ~DescriptorArray() + { + SafeRelease(&mHeap); + } + + // Direct access to handles + CD3DX12_CPU_DESCRIPTOR_HANDLE CPU(UINT index = 0) const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(mCPUBegin, index, mHandleIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE GPU(UINT index = 0) const + { + return CD3DX12_GPU_DESCRIPTOR_HANDLE(mGPUBegin, index, mHandleIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE GPUEnd() const { return GPU(mCurrentSize); } + INT HandleIncrementSize() const { return mHandleIncrementSize; } + + // NOTE: Caller can fill in data at new handle and/or derived classes provide + // specialized methods to do it in one step. + CD3DX12_CPU_DESCRIPTOR_HANDLE Append() + { + assert(mCurrentSize < mMaxSize); + return CPU(mCurrentSize++); + } + + // Invalidates contents of any previous handles + void Clear() { mCurrentSize = 0; } + void Resize(UINT newSize) { mCurrentSize = newSize; } + UINT Size() const { return mCurrentSize; } + +protected: + ID3D12Device* mDevice = nullptr; + ID3D12DescriptorHeap* mHeap = nullptr; + CD3DX12_CPU_DESCRIPTOR_HANDLE mCPUBegin; + CD3DX12_GPU_DESCRIPTOR_HANDLE mGPUBegin; + UINT mHandleIncrementSize = 0; + UINT mCurrentSize = 0; + UINT mMaxSize = 0; +}; + + +// Render target views +class RTVDescriptorList : public DescriptorArray +{ +public: + RTVDescriptorList(ID3D12Device* device, UINT maxDescriptors) + : DescriptorArray( device, maxDescriptors, D3D12_DESCRIPTOR_HEAP_TYPE_RTV ) + {} + + using DescriptorArray::Append; + + D3D12_CPU_DESCRIPTOR_HANDLE Append(ID3D12Resource* resource, D3D12_RENDER_TARGET_VIEW_DESC* desc = nullptr) + { + auto handle = Append(); + mDevice->CreateRenderTargetView(resource, desc, handle); + return handle; + } +}; + +// Depth stencil views +class DSVDescriptorList : public DescriptorArray +{ +public: + DSVDescriptorList(ID3D12Device* device, UINT descriptorCount) + : DescriptorArray( device, descriptorCount, D3D12_DESCRIPTOR_HEAP_TYPE_DSV ) + {} + + using DescriptorArray::Append; + + D3D12_CPU_DESCRIPTOR_HANDLE Append(ID3D12Resource* resource, D3D12_DEPTH_STENCIL_VIEW_DESC* desc = nullptr) + { + auto handle = Append(); + mDevice->CreateDepthStencilView(resource, desc, handle); + return handle; + } +}; + +// SRVs, CBVs, UAVs, etc. +class SRVDescriptorList : public DescriptorArray +{ +public: + SRVDescriptorList(ID3D12Device* device, UINT descriptorCount) + : DescriptorArray( device, descriptorCount, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, true ) + {} + + ID3D12DescriptorHeap* Heap() { return mHeap; } + + // In this class it's more useful to have the GPU handle returned + // In the long run it's useful to have both (for copying, etc) but this suits our purposes for now + + D3D12_GPU_DESCRIPTOR_HANDLE AppendSRV(ID3D12Resource* resource, D3D12_SHADER_RESOURCE_VIEW_DESC* desc = nullptr) + { + auto handle = GPU(mCurrentSize); + mDevice->CreateShaderResourceView(resource, desc, DescriptorArray::Append()); + return handle; + } + + D3D12_GPU_DESCRIPTOR_HANDLE AppendCBV(D3D12_CONSTANT_BUFFER_VIEW_DESC* desc = nullptr) + { + auto handle = GPU(mCurrentSize); + mDevice->CreateConstantBufferView(desc, DescriptorArray::Append()); + return handle; + } +}; + +// Samplers +class SMPDescriptorList : public DescriptorArray +{ +public: + SMPDescriptorList(ID3D12Device* device, UINT descriptorCount) + : DescriptorArray( device, descriptorCount, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, true ) + {} + + ID3D12DescriptorHeap* Heap() { return mHeap; } + + D3D12_GPU_DESCRIPTOR_HANDLE Append(D3D12_SAMPLER_DESC* desc) + { + auto handle = GPU(mCurrentSize); + mDevice->CreateSampler(desc, DescriptorArray::Append()); + return handle; + } +}; diff --git a/Projects/Asteroids/src/font.h b/Projects/Asteroids/src/font.h new file mode 100644 index 0000000..cd32626 --- /dev/null +++ b/Projects/Asteroids/src/font.h @@ -0,0 +1,98 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include "sprite.h" +#include "intel_clear_bd_50_usascii.inl" +#include "stb_font_consolas_bold_50_usascii.inl" + +#include <vector> +#include <assert.h> + +class BitmapFont +{ +public: + SpriteVertex* DrawString(const char* str, float x, float y, float viewportWidth, float viewportHeight, SpriteVertex* outVertex) const + { + for (; *str; ++str) { + auto codePoint = *str - STB_SOMEFONT_FIRST_CHAR; + assert(codePoint >= 0 && codePoint < mFontData.size()); + const stb_fontchar* cd = &mFontData[codePoint]; + + outVertex[0] = {x + cd->x0, y + cd->y0, cd->s0, cd->t0}; + outVertex[1] = {x + cd->x1, y + cd->y0, cd->s1, cd->t0}; + outVertex[2] = {x + cd->x1, y + cd->y1, cd->s1, cd->t1}; + outVertex[3] = outVertex[0]; + outVertex[4] = outVertex[2]; + outVertex[5] = {x + cd->x0, y + cd->y1, cd->s0, cd->t1}; + + for (int i = 0; i < 6; ++i) { + outVertex[i].x = (outVertex[i].x / viewportWidth * 2.0f - 1.0f); + outVertex[i].y = -(outVertex[i].y / viewportHeight * 2.0f - 1.0f); + } + + outVertex += 6; + x += cd->advance_int; + } + + return outVertex; + } + + void GetDimensions(const char* str, int* width, int* height) const + { + UINT w = 0; + for (; *str; ++str) { + auto codePoint = *str - STB_SOMEFONT_FIRST_CHAR; + assert(codePoint >= 0 && codePoint < mFontData.size()); + const stb_fontchar* cd = &mFontData[codePoint]; + w += cd->advance_int; + } + + *width = w; + *height = FontHeight(); + } + + int BitmapWidth() const { return mBitmapWidth; } + int BitmapHeight() const { return mBitmapHeight; } + int FontHeight() const { return mFontHeight; } + + virtual const unsigned char* Pixels() const = 0; + +protected: + // Setup by derived class + std::vector<stb_fontchar> mFontData; + int mBitmapWidth; + int mBitmapHeight; + int mFontHeight; + + BitmapFont() {} + BitmapFont(const BitmapFont&) {} +}; + + +class IntelClearBold : public BitmapFont +{ +public: + IntelClearBold() + { + mFontData.resize(STB_FONT_intelclearbd_NUM_CHARS); + stb_font_intelclearbd(mFontData.data(), mFontPixels, STB_FONT_intelclearbd_BITMAP_HEIGHT); + + mBitmapWidth = STB_FONT_intelclearbd_BITMAP_WIDTH; + mBitmapHeight = STB_FONT_intelclearbd_BITMAP_HEIGHT; + mFontHeight = 50; // This doesn't seem to get put into the file anywhere... + } + + virtual const unsigned char* Pixels() const override { return mFontPixels[0]; } + +private: + unsigned char mFontPixels[STB_FONT_intelclearbd_BITMAP_HEIGHT][STB_FONT_intelclearbd_BITMAP_WIDTH]; +}; diff --git a/Projects/Asteroids/src/font_ps.hlsl b/Projects/Asteroids/src/font_ps.hlsl new file mode 100644 index 0000000..3100db9 --- /dev/null +++ b/Projects/Asteroids/src/font_ps.hlsl @@ -0,0 +1,12 @@ +#include "sprite_vs.hlsl" + +Texture2D Tex;// : register(t0); +SamplerState Tex_sampler;// : register(s0); + +void font_ps(in float4 position : SV_Position, + in Font_VSOut vs_out, + out float4 color : SV_Target ) +{ + float alpha = Tex.Sample(Tex_sampler, vs_out.uv).r; + color = float4(1, 1, 1, 1) * alpha; +} diff --git a/Projects/Asteroids/src/gui.h b/Projects/Asteroids/src/gui.h new file mode 100644 index 0000000..d56aab6 --- /dev/null +++ b/Projects/Asteroids/src/gui.h @@ -0,0 +1,149 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include "font.h" + +#include <vector> +#include <string> + + +class GUIControl +{ +protected: + int mX; + int mY; + int mWidth; + int mHeight; + std::string mTextureFile = ""; + bool mVisible = true;; + +public: + GUIControl() {} + virtual ~GUIControl() {} + + // For now, empty string means use the font texture/shader... let's not overengineer this yet :) + std::string TextureFile() const { return mTextureFile; } + + void Visible(bool visible) { mVisible = visible; } + bool Visible() const { return mVisible; } + + virtual SpriteVertex* Draw(float viewportWidth, float viewportHeight, SpriteVertex* outVertex) const = 0; + + bool HitTest(int x, int y) const + { + return mVisible && (x >= mX && x < (mX + mWidth) && y > mY && y < (mY + mHeight)); + } +}; + + +class GUIText : public GUIControl +{ +private: + std::string mText; + const BitmapFont* mFont; + + void ComputeDimensions() + { + mFont->GetDimensions(mText.c_str(), &mWidth, &mHeight); + } + +public: + // Font lifetime managed by caller + GUIText(int x, int y, const BitmapFont* font, const std::string& text) + : mFont(font), mText(text) + { + mX = x; + mY = y; + ComputeDimensions(); + } + + void Text(const std::string& text) + { + mText = text; + ComputeDimensions(); + } + + virtual SpriteVertex* Draw(float viewportWidth, float viewportHeight, SpriteVertex* outVertex) const override + { + return mFont->DrawString(mText.c_str(), float(mX), float(mY), viewportWidth, viewportHeight, outVertex); + } +}; + + +class GUISprite : public GUIControl +{ +private: + std::string mSpriteFile; + +public: + GUISprite(int x, int y, int width, int height, const std::string& spriteFile) + : mSpriteFile(spriteFile) + { + mX = x; + mY = y; + mWidth = width; + mHeight = height; + mTextureFile = spriteFile; + } + + virtual SpriteVertex* Draw(float viewportWidth, float viewportHeight, SpriteVertex* outVertex) const override + { + return DrawSprite(float(mX), float(mY), float(mWidth), float(mHeight), viewportWidth, viewportHeight, outVertex); + } +}; + + +class GUI +{ +private: + std::vector<GUIControl*> mControls; + IntelClearBold mFont; // Single font for the entire GUI works for now + +public: + GUI() + { + } + ~GUI() + { + for (auto i : mControls) { + delete i; + } + } + + const BitmapFont* Font() const { return &mFont; } + + GUIText* AddText(int x, int y, const std::string& text = "") + { + auto control = new GUIText(x, y, &mFont, text); + mControls.push_back(control); + return control; + } + + GUISprite* AddSprite(int x, int y, int width, int height, const std::string& spriteFile) + { + auto control = new GUISprite(x, y, width, height, spriteFile); + mControls.push_back(control); + return control; + } + + // NOTE: Caller needs to preadjust x/y for any stretching/scaling going on + GUIControl* HitTest(int x, int y) const + { + for (auto i : mControls) { + if (i->HitTest(x, y)) return i; + } + return nullptr; + } + + GUIControl* operator[](size_t i) { return mControls[i]; } + size_t size() const { return mControls.size(); } +}; diff --git a/Projects/Asteroids/src/intel_clear_bd_50_usascii.inl b/Projects/Asteroids/src/intel_clear_bd_50_usascii.inl new file mode 100644 index 0000000..7a294a5 --- /dev/null +++ b/Projects/Asteroids/src/intel_clear_bd_50_usascii.inl @@ -0,0 +1,920 @@ +// Font generated by stb_font_inl_generator.c (4/1 bpp) +// +// Following instructions show how to use the only included font, whatever it is, in +// a generic way so you can replace it with any other font by changing the include. +// To use multiple fonts, replace STB_SOMEFONT_* below with STB_FONT_intelclearbd_*, +// and separately install each font. Note that the CREATE function call has a +// totally different name; it's just 'stb_font_intelclearbd'. +// +/* // Example usage: + +static stb_fontchar fontdata[STB_SOMEFONT_NUM_CHARS]; + +static void init(void) +{ + // optionally replace both STB_SOMEFONT_BITMAP_HEIGHT with STB_SOMEFONT_BITMAP_HEIGHT_POW2 + static unsigned char fontpixels[STB_SOMEFONT_BITMAP_HEIGHT][STB_SOMEFONT_BITMAP_WIDTH]; + STB_SOMEFONT_CREATE(fontdata, fontpixels, STB_SOMEFONT_BITMAP_HEIGHT); + ... create texture ... + // for best results rendering 1:1 pixels texels, use nearest-neighbor sampling + // if allowed to scale up, use bilerp +} + +// This function positions characters on integer coordinates, and assumes 1:1 texels to pixels +// Appropriate if nearest-neighbor sampling is used +static void draw_string_integer(int x, int y, char *str) // draw with top-left point x,y +{ + ... use texture ... + ... turn on alpha blending and gamma-correct alpha blending ... + glBegin(GL_QUADS); + while (*str) { + int char_codepoint = *str++; + stb_fontchar *cd = &fontdata[char_codepoint - STB_SOMEFONT_FIRST_CHAR]; + glTexCoord2f(cd->s0, cd->t0); glVertex2i(x + cd->x0, y + cd->y0); + glTexCoord2f(cd->s1, cd->t0); glVertex2i(x + cd->x1, y + cd->y0); + glTexCoord2f(cd->s1, cd->t1); glVertex2i(x + cd->x1, y + cd->y1); + glTexCoord2f(cd->s0, cd->t1); glVertex2i(x + cd->x0, y + cd->y1); + // if bilerping, in D3D9 you'll need a half-pixel offset here for 1:1 to behave correct + x += cd->advance_int; + } + glEnd(); +} + +// This function positions characters on float coordinates, and doesn't require 1:1 texels to pixels +// Appropriate if bilinear filtering is used +static void draw_string_float(float x, float y, char *str) // draw with top-left point x,y +{ + ... use texture ... + ... turn on alpha blending and gamma-correct alpha blending ... + glBegin(GL_QUADS); + while (*str) { + int char_codepoint = *str++; + stb_fontchar *cd = &fontdata[char_codepoint - STB_SOMEFONT_FIRST_CHAR]; + glTexCoord2f(cd->s0f, cd->t0f); glVertex2f(x + cd->x0f, y + cd->y0f); + glTexCoord2f(cd->s1f, cd->t0f); glVertex2f(x + cd->x1f, y + cd->y0f); + glTexCoord2f(cd->s1f, cd->t1f); glVertex2f(x + cd->x1f, y + cd->y1f); + glTexCoord2f(cd->s0f, cd->t1f); glVertex2f(x + cd->x0f, y + cd->y1f); + // if bilerping, in D3D9 you'll need a half-pixel offset here for 1:1 to behave correct + x += cd->advance; + } + glEnd(); +} +*/ + +#ifndef STB_FONTCHAR__TYPEDEF +#define STB_FONTCHAR__TYPEDEF +typedef struct +{ + // coordinates if using integer positioning + float s0,t0,s1,t1; + signed short x0,y0,x1,y1; + int advance_int; + // coordinates if using floating positioning + float s0f,t0f,s1f,t1f; + float x0f,y0f,x1f,y1f; + float advance; +} stb_fontchar; +#endif + +#define STB_FONT_intelclearbd_BITMAP_WIDTH 256 +#define STB_FONT_intelclearbd_BITMAP_HEIGHT 222 +#define STB_FONT_intelclearbd_BITMAP_HEIGHT_POW2 256 + +#define STB_FONT_intelclearbd_FIRST_CHAR 32 +#define STB_FONT_intelclearbd_NUM_CHARS 95 + +#define STB_FONT_intelclearbd_LINE_SPACING 27 + +static unsigned int stb__intelclearbd_pixels[]={ + 0x20266666,0x10ccccc9,0x00001333,0x00019990,0x009a9880,0x310ccccc, + 0x00001333,0x00066666,0x9aaa9880,0x26620000,0x09999999,0x00133331, + 0x33333310,0x40001333,0x00000019,0xcccc9800,0xfffff10c,0xfffff507, + 0x3fffff63,0xff00001d,0x9100001f,0x40dfffff,0x265ffffc,0x001fffff, + 0x3ffffdc0,0xfecba800,0xffffffff,0x7fec003d,0x5fffffff,0x00dffff9, + 0xffffffd0,0x26009fff,0xeffffedb,0x220001bd,0xacdffedb,0x50999999, + 0x223fffff,0xa83fffff,0xfb1fffff,0x09ffffff,0x01fff000,0xffffb800, + 0xff106fff,0xffe85fff,0x6c0005ff,0x4005ffff,0xffffffeb,0xffffffff, + 0xffb002ef,0xbfffffff,0x03ffffea,0xfffffd00,0x8809ffff,0xfffffffd, + 0x004fffff,0x7ffffe44,0xffffffff,0xffff52ff,0x3fffe23f,0xffffa83f, + 0xfffffb1f,0x80005fff,0x20000fff,0xfffffff9,0xffff706f,0xfffff50d, + 0x3fe20003,0xf3002fff,0xffffffff,0xffffffff,0xd803bfff,0xffffffff, + 0xfffff15f,0xfffe8007,0x04ffffff,0x3fffffea,0xffffffff,0xffd001ef, + 0xffffffff,0x25ffffff,0x11fffffa,0x507fffff,0x363fffff,0xffffffff, + 0xfb98000f,0x0009bdff,0x7ffffff4,0xffff06ff,0x3fffe07f,0xff50006f, + 0xf7001fff,0xdfffffff,0xffdb759b,0x09ffffff,0x7fffffec,0x3ff65fff, + 0x7f4005ff,0xffffffff,0xfffff904,0xffffffff,0x807fffff,0xcefffffd, + 0xfffffffc,0xffff52ff,0x3fffe23f,0xaaaa883f,0x7ffdcc0a,0xb1002fff, + 0xffffffff,0xf3005dff,0x037fffff,0x07ffffdc,0x1fffffc8,0xffffd800, + 0xffffd806,0x71001cff,0x09ffffff,0x2ffffec0,0x01fffff7,0x27ffff40, + 0xfffff980,0xecaaceff,0x0fffffff,0x7fffff10,0x0dffff70,0x21555551, + 0x03fffff8,0xffff9800,0xfffc803f,0xffffffff,0x2a01efff,0x802fffff, + 0x204ffffe,0x04fffff8,0x3fffff80,0x7ffffe40,0xf910001e,0x2003ffff, + 0x225ffffd,0x002fffff,0x013ffffa,0x77fffff4,0x3fffe601,0xfff505ff, + 0x3ffe20ff,0x7c4001ff,0x0003ffff,0x09fffff0,0xffffffc8,0xffffffff, + 0x3fee05ff,0xffa807ff,0x7ec01fff,0x54007fff,0x200fffff,0x03fffffa, + 0xffff3000,0xfffb001d,0xffffe8bf,0x3fffa004,0xfffb804f,0xe8800dff, + 0xc82fffff,0x3604ffff,0x4003ffff,0x83fffff8,0x00ccccc8,0x817ffff6, + 0xdffffffa,0xffecbfff,0x3ff200ff,0xffe806ff,0xffa806ff,0x32002fff, + 0x2206ffff,0x003fffff,0x7fffd400,0xffffd804,0x3ffffdc5,0x9ffffd00, + 0xfffff880,0x3fe6001f,0xffb86fff,0x3ffa06ff,0x666443ff,0xffff10cc, + 0xffff307f,0x7ffec03f,0x3fff605f,0x41fff0df,0x7e403fc8,0x7c406fff, + 0x8804ffff,0x004fffff,0x813ffffe,0x105ffffb,0x4437bd95,0x7ffec2aa, + 0x7ffec01f,0x7fffcc5f,0xfffd001f,0xfffa809f,0xfe8005ff,0x7cc1ffff, + 0xf980ffff,0x7cc1ffff,0xff11ffff,0xff307fff,0x7ec03fff,0x3fe05fff, + 0x3ffe1fff,0xffc80080,0x7fd406ff,0xff003fff,0x2600dfff,0x101fffff, + 0x301fffff,0x7ffffffd,0xf883fffe,0x7ec03fff,0xffe85fff,0xffd004ff, + 0xffb809ff,0xa8001fff,0xe82fffff,0x98beffff,0x0fffffeb,0x8fffffcc, + 0x83fffff8,0x01fffff9,0x417ffff6,0x7c6ffff8,0xf90000ff,0xfb80dfff, + 0xd002ffff,0x200fffff,0x207ffffb,0xa83ffffa,0xffffffff,0x40ffffcf, + 0x6c05fffc,0xfc85ffff,0xfd006fff,0xfc809fff,0x8000ffff,0x83fffff8, + 0xfffffff9,0x2fffffff,0x1fffff98,0x07fffff1,0x03fffff3,0x82ffffec, + 0x20fffff8,0x90000fff,0xd80dffff,0x001fffff,0x03fffffb,0x09ffffd0, + 0x207fffe4,0xfffffff8,0xffffffff,0x037ffd40,0x217ffff6,0x01fffff9, + 0x04ffffe8,0x03fffff4,0xfffff880,0xfffff505,0x7fffffff,0x3ffffe60, + 0x7fffff11,0x3fffff30,0x2ffffec0,0x47fffff0,0x90000fff,0xe80dffff, + 0x000fffff,0x05fffff9,0x2fffff88,0x21ffffe0,0x21effffc,0x0fffffe9, + 0x007fffcc,0x20bffffb,0x803fffff,0x404ffffe,0x006fffff,0x1bffffe0, + 0x3fffffee,0x00cfffff,0x47ffffe6,0x83fffff8,0x01fffff9,0x81fffff2, + 0xaefffffd,0xd0000fff,0xf80bffff,0x2007ffff,0x03fffffb,0x03ffffdc, + 0x88bffff1,0x880fffff,0x440fffff,0x3601ffff,0xf905ffff,0xfd00dfff, + 0x7c409fff,0x0005ffff,0x71fffffa,0x5537ffff,0x3e600355,0xff11ffff, + 0xff307fff,0x7d403fff,0x880affff,0xffffffff,0xf98001ff,0x7c03ffff, + 0x2006ffff,0x04fffffa,0x02ffffec,0x989ffff3,0x3204ffff,0xff80ffff, + 0x3ff602ff,0xfff505ff,0xffe801ff,0x7ffc04ff,0x3e0006ff,0x7f47ffff, + 0x980006ff,0xf11fffff,0xf307ffff,0x4403ffff,0xeffffffe,0x7ffffd40, + 0x0bdfffff,0x7fffff40,0x3fe200ff,0x26005fff,0x204fffff,0x02fffff8, + 0x50ffffea,0x5405ffff,0xfe80ffff,0x3ff602ff,0xfff105ff,0xffe807ff, + 0x7ff404ff,0x3e0007ff,0x7fc6ffff,0x40000fff,0x11fffff9,0x307fffff, + 0x803fffff,0xffffffe8,0xffffe980,0xcfffffff,0xffffff00,0xfff8801d, + 0x3e2004ff,0x2a05ffff,0x200fffff,0x5c1ffffa,0x2601ffff,0xff80ffff, + 0x3ff601ff,0x3ff605ff,0x7ff405ff,0x7fec04ff,0xf10007ff,0xfc8bffff, + 0xcccdffff,0x2601abcc,0xf11fffff,0xf307ffff,0x8803ffff,0x0ffffffd, + 0x3ffff660,0x2fffffff,0xeffffff8,0x7fffc400,0x7ffc004f,0x3ff605ff, + 0x7fd406ff,0x7ffdc1ff,0x3ffea01f,0x0ffff80f,0x17ffff60,0x0fffffb8, + 0x13ffffa0,0x1fffff70,0xffff3000,0xfffd889f,0xffffffff,0xff982eff, + 0xfff11fff,0xfff307ff,0x7f4403ff,0x00ffffff,0xfffffa88,0x7c1fffff, + 0x0effffff,0x3ffffe20,0x3ffe2005,0x3ffe04ff,0x7fd403ff,0x7ffd43ff, + 0x3ffee02f,0x3fffcc0f,0x17ffff60,0x2fffff88,0x13ffffa0,0x9fffff50, + 0xffff9000,0xfffd105f,0xffffffff,0xff989fff,0xfff11fff,0xfff307ff, + 0x7fd403ff,0x8000bfff,0xffffcfff,0xffa886ff,0x7fc03fff,0x2a006fff, + 0x504fffff,0x801fffff,0x4c4ffff9,0x3a04ffff,0x7e40ffff,0x7fec06ff, + 0x7ff405ff,0x3ffa04ff,0x7fcc04ff,0x2000ffff,0x87fffff8,0xfffffffa, + 0xffffffff,0x3ffe62ff,0xffff11ff,0xffff307f,0x7ffdc03f,0x3fe0007f, + 0xffffc88f,0xffffd01f,0xfffff809,0x3ffee007,0xfff903ff,0xfff100df, + 0xfffff0bf,0xfffff705,0x17fffc45,0x17ffff60,0x0fffff70,0x027ffff4, + 0x27ffffe4,0xfffffb00,0xfffff98b,0xfffb980a,0x3ffe64ff,0xffff11ff, + 0xffff307f,0x7ffec03f,0x3fe0005f,0x3ffffa0f,0xdffff903,0x7fffff80, + 0x3ffff200,0xfffff02f,0x3fffe009,0xfffffb86,0xffffdaae,0xffeaaeff, + 0xfffd806f,0x7ffcc05f,0xfffd01ff,0xfff1009f,0xd880bfff,0x40ffffff, + 0x804ffffc,0x266ffffd,0xf11fffff,0xf307ffff,0x6c03ffff,0x0005ffff, + 0xffb83ffe,0xfff904ff,0xfffd80df,0xffb000ff,0xff303fff,0x36003fff, + 0xff887fff,0xffffffff,0xffffff9f,0xd802ffff,0xe805ffff,0xfd04ffff, + 0x2e009fff,0xbeffffff,0xffeca88a,0xfe82ffff,0xfb802fff,0x3fe65fff, + 0xfff11fff,0xfff307ff,0x7fec03ff,0xf00c05ff,0x7ffe41ff,0xffff902f, + 0xffffc80d,0xfffd001f,0x3ffee0ff,0x3fea007f,0xfff983ff,0x71ffffff, + 0xffffffff,0x3fff6007,0xfffc805f,0xffffd06f,0x7fff4009,0xffffffff, + 0x4fffffff,0x0dffffd0,0x45ffffd0,0x11fffff9,0x307fffff,0x403fffff, + 0x205ffffd,0xfff80dfa,0x1fffff10,0x1bffff20,0x5fffff50,0x3ffffe00, + 0x9ffffd06,0x7fffc400,0xfffe880f,0x7fec2eff,0x2001efff,0x805ffffd, + 0x81fffff9,0x004ffffe,0x7fffffe4,0xffffffff,0x3ff203ff,0x260acfff, + 0x0fffffdb,0x47ffffe6,0x83fffff8,0x01fffff9,0x417ffff6,0x0acfffe8, + 0xffd73fff,0x7fe40dff,0x7fc406ff,0xf8803fff,0xf884ffff,0x4002ffff, + 0x205ffffc,0x2600ab98,0xd8000aba,0xf005ffff,0xfd07ffff,0x30009fff, + 0xfffffffd,0x1bffffff,0x7ffffc40,0xffffffff,0x7cc1ffff,0xff11ffff, + 0xff307fff,0x7ec03fff,0xff905fff,0xffffffff,0xffffffff,0x7fffe401, + 0xffffe806,0xffffa806,0xffffb82f,0xfff88007,0x000002ff,0xffffb000, + 0x3fff200b,0xffffe86f,0x3fb20004,0xffffffff,0x301dffff,0xffffffff, + 0x5fffffff,0x3fffff30,0x0fffffe2,0x07ffffe6,0x05ffffe8,0xffffffd3, + 0xffffffff,0xffc805ff,0xffb807ff,0x7ec01fff,0xffb06fff,0x2e000bff, + 0x004fffff,0xfd800000,0xf5005fff,0xfe81ffff,0x00004fff,0xfffb9751, + 0x7dffffff,0xfffeb881,0x2effffff,0x3ffe2000,0xfff983ff,0xfff301ff, + 0xfea807ff,0xffffffff,0xa800dfff,0x802fffff,0x204fffff,0x83fffff8, + 0x02fffff8,0x3ffff200,0x4a8002ef,0xfffd8000,0xfff1005f,0xfffe87ff, + 0x4000004f,0xffffffea,0x2ea601ff,0x0009abcc,0xfffff880,0xfffffb83, + 0xffffea80,0xfb95002f,0x39dfffff,0x7fffcc00,0x7fdc02ef,0xff700fff, + 0x3fea0fff,0x40000fff,0xdffffffd,0xeb9981ab,0x6c0001ff,0x2005ffff, + 0x745ffffd,0x0004ffff,0xfffb3000,0x00000dff,0xffff1000,0xfffe987f, + 0x3ffff67f,0x000fffff,0x003fff10,0x7fffffc0,0xff886fff,0xfff03fff, + 0x3ff607ff,0x500006ff,0xffffffff,0xfffffdff,0x6400bfff,0xffffeeee, + 0x3fee005f,0x3ffa0fff,0x3eeeefff,0x2e200000,0x00002fff,0xfff88000, + 0xffff73ff,0x7fecdfff,0x03ffffff,0x007ffc00,0xfffff500,0x3f20dfff, + 0xffa86fff,0xfff00fff,0x400007ff,0xffffffc8,0xffffffff,0xb000ffff, + 0xffffffff,0x7fc400bf,0x3ffa2fff,0x4fffffff,0xb5000000,0x00000000, + 0x4fffffe2,0xfffffffb,0x3fffff62,0xf80005ff,0x640000ff,0x6fffffff, + 0x3fffff10,0x04ffffd8,0x01fffff3,0xffd30000,0xffffffff,0x0017dfff, + 0x7fffffec,0x74005fff,0x3fa4ffff,0xffffffff,0x00000004,0x80000000, + 0x73fffff8,0x8bffffff,0x1efffffd,0x1fff0000,0xffb30000,0x7e40dfff, + 0x3fe24fff,0xff900fff,0x00000dff,0xffecba88,0x001cceff,0xffffffb0, + 0xb800bfff,0x3fa7ffff,0xffffffff,0x00000004,0x80000000,0x73fffff8, + 0x107fffff,0x00013555,0x000aaa80,0x05554c00,0x45555510,0x202aaaa8, + 0x001aaaaa,0x00100000,0xaaaa9800,0x002aaaaa,0x85555544,0xaaaaaaaa, + 0x000001aa,0x00000000,0xfffff880,0x00135513,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x4ccccc00, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x09999970, + 0x39999930,0x000cc000,0x1ddddd30,0x01331000,0x3bbbba60,0x40000000, + 0x00000998,0x00001998,0x3bbbba20,0x00262001,0x99999100,0xffdb9807, + 0x332a21bd,0x1599911c,0x6f7f6544,0x3fffee03,0x7ffe401f,0xb73000ff, + 0x7bdffffd,0x3ffea003,0xfd7000ff,0x7bdfffff,0xfffff301,0x44000003, + 0xfffffecb,0x54000bef,0xfffffedc,0x200003ee,0x02fffff8,0x7ffffecc, + 0xff88001d,0x3ee06fff,0x3fffffff,0x265ffff9,0xff54ffff,0x1dffffff, + 0x9fffff10,0x5ffffe80,0xffffd880,0xffffffff,0xffffa804,0x7ffdc00f, + 0xffffffff,0x7ffcc3ff,0x000001ff,0xfffffff7,0x17ffffff,0xffffe980, + 0xffffffff,0x440000bf,0x102fffff,0xfffffffb,0xf8800bff,0xfb06ffff, + 0xffffffff,0x5ffffb7f,0x27bfffe6,0xffffffff,0xffd81fff,0x3fe206ff, + 0x7d402fff,0xffffffff,0x1effffff,0x3ffffea0,0x3ffff600,0xffffffff, + 0xff31ffff,0x00003fff,0xfffffd88,0xffffffff,0xff9101ff,0xffffffff, + 0x03ffffff,0xffff8800,0xffffb02f,0x7fffffff,0x7fffc400,0xffffb86f, + 0xffffffff,0xf32fffff,0xfffddfff,0xffffffff,0xfffff50d,0x3fffee01, + 0x7fffe407,0xffffffff,0x03ffffff,0x01fffff5,0x3fffffee,0xffffffff, + 0xfff30fff,0x400003ff,0xfffffffa,0xffffffff,0xffff304f,0xffffffff, + 0x00bfffff,0xfffff100,0xfffff705,0xffffff9d,0x3ffe2001,0x7ffc46ff, + 0xca9befff,0x2fffffff,0xfffffff3,0xfffb537b,0xfff05fff,0x3ff607ff, + 0x3fe604ff,0xacefffff,0xfffffeca,0xfffa80ff,0xfff980ff,0xaabdffff, + 0x22fffecb,0x01fffff9,0xffff1000,0x559bffff,0x201fff97,0xfffffffe, + 0xfdcaabce,0x880000ff,0xd82fffff,0x7e43ffff,0xf1002fff,0xfc8dffff, + 0xf705ffff,0x265fffff,0x04ffffff,0x0dfffff7,0x20bffff9,0x201fffff, + 0x1efffffe,0x3ffffe60,0xffffa85f,0xffffb80f,0x46d9805f,0x01fffff9, + 0xffff9000,0x077009ff,0x3fffffee,0x025c400d,0xffff8800,0x7ffff82f, + 0x04ffff98,0x0aaaaaa0,0x01fffffd,0x97ffffec,0x07fffff9,0x43fffff4, + 0x987ffff8,0x2e06ffff,0x00dfffff,0xfffffe88,0x7ffffd42,0xfffffc80, + 0x3fe60000,0x80001fff,0x2ffffff9,0x7ffcc000,0x00002fff,0xffff1000, + 0xbffff05f,0x09ffff10,0xffff8000,0x7ffd404f,0xffff32ff,0xfffb807f, + 0xfffe80ff,0x7fffe42f,0xfffff103,0x7fcc003f,0x7fd46fff,0xffe80fff, + 0x4c0007ff,0x511fffff,0x807bdfd9,0x04fffffe,0xffffd800,0x3000004f, + 0x239bffb7,0x82fffff8,0xfa87fffd,0x00002fff,0x0fffffe2,0x5fffff10, + 0x07ffffe6,0x3fffff50,0x89ffff50,0x500ffffe,0x00bfffff,0x3fffffd0, + 0x07ffffd4,0x17fffff4,0xffff3000,0xffffd13f,0xf101dfff,0x001fffff, + 0xfffff880,0xb800000f,0xffffffff,0x2fffff8b,0x42ffffb8,0x0007fffc, + 0x7ffffcc0,0x7fffc402,0xfffff32f,0xffff9801,0xdffff02f,0x02ffffc4, + 0x03fffff7,0xfffff500,0x7ffffd45,0xfffffc80,0x3fe60005,0xffffbfff, + 0x1fffffff,0x1fffffcc,0x7ffcc000,0x800003ff,0xfffffffd,0xffffcfff, + 0xffff982f,0xbffff91f,0xffa80000,0xff801fff,0xfff32fff,0xff9801ff, + 0xff902fff,0x3ffee3ff,0x3fff202f,0xf88000ff,0x3ea3ffff,0xfb80ffff, + 0x0bffffff,0x7fffcc00,0xffffffff,0x5c6fffff,0x002fffff,0xfffffb80, + 0x7dc00002,0xffffffff,0xffffffff,0xdffff702,0x03fffffb,0xfff98000, + 0x7fc402ff,0xfff32fff,0xffa801ff,0xff301fff,0x3fff67ff,0x7ffff407, + 0xfff10007,0x7ffd4bff,0xfffd00ff,0x17bfffff,0xfffff300,0xfb537bff, + 0x645fffff,0x000fffff,0xfffffc80,0x3e200000,0x9befffff,0xffffffca, + 0x3fff602f,0x01ffffff,0xfff88000,0x7fcc03ff,0xfff32fff,0xffb803ff, + 0x3fa00fff,0x9ffff5ff,0x6fffff80,0x3fffe000,0x3fffea6f,0xffff300f, + 0xdfffffff,0x3ffe6017,0xff704fff,0x7fecdfff,0xb00007ff,0x4c0fffff, + 0xaaaaaaaa,0x3ffff22a,0xffff705f,0x7fc405ff,0x00dfffff,0x3ffe0000, + 0x7fe406ff,0xfff32fff,0xffe809ff,0x7fdc07ff,0x1ffffaff,0x3ffffe20, + 0x3ffa0005,0x3ffea7ff,0x3fa200ff,0xffffffff,0xff984fff,0x7f407fff, + 0x3ffe7fff,0xf00007ff,0x640fffff,0xffffffff,0x3ffffa5f,0x3fffa00f, + 0xfff502ff,0x5c0dffff,0x77440bde,0x7fec4eee,0xff101fff,0x3e65ffff, + 0x300fffff,0x809fffff,0xfffffff8,0xffff806f,0x3fe0006f,0x3fea7fff, + 0xea800fff,0xffffffff,0x3e60efff,0x5c03ffff,0xfd0fffff,0x0000ffff, + 0x81fffffa,0xfffffffc,0x3fffe5ff,0x7ffd404f,0x7fec42ff,0x4fffffff, + 0x889fffd0,0x4c6fffff,0x42ffffff,0xfffffff9,0xffffff32,0xffffa83d, + 0xffd801ff,0x803fffff,0x007ffffe,0x97ffffe0,0x00fffffa,0x3fff6e20, + 0x25ffffff,0x01fffff9,0x8fffffd4,0x00fffffd,0xffffd800,0xffff900f, + 0x22bfffff,0x403fffff,0x22fffff8,0xcfffffe8,0x444fffff,0x7c41ffff, + 0xfd86ffff,0xfeffffff,0xffffffff,0xffffff32,0xffffdfff,0x2a00bfff, + 0x0fffffff,0x7ffffd80,0xffff1000,0x7fffd49f,0x3660000f,0x2fffffff, + 0x01fffff3,0x2fffff98,0x03fffff7,0xffff7000,0x3fff203f,0x35ffffff, + 0x805fffff,0x22fffff8,0x52fffffc,0x547fffff,0xff887fff,0xff986fff, + 0xffffffff,0x2fffffef,0xfffffff3,0xffffffff,0x7fc003ff,0x7005ffff, + 0x001fffff,0x7fffff30,0x07ffffd4,0x7ff44000,0xfff35fff,0xff9801ff, + 0xfff52fff,0x500005ff,0x007fffff,0xaaffffdc,0x801fffff,0xf32fffff, + 0xfa85ffff,0xffd2ffff,0xffff109f,0x3ffa60bf,0x8dffffff,0xf32fffff, + 0xffb3ffff,0x3dffffff,0xffffc800,0xfff5002f,0xf90009ff,0x7d43ffff, + 0x0000ffff,0xdfffff50,0x03ffffe6,0x3fffff50,0x1bffffe6,0x3ffe6000, + 0x3ee006ff,0xfff35fff,0xff8805ff,0xfff72fff,0x3ffee0df,0x1ffffbff, + 0x4fffff88,0x3ffff620,0xffff14ff,0x3fffe65f,0xfffff91f,0xf30001bf, + 0x4c00ffff,0x00ffffff,0x3ffffe20,0x3fffea0f,0x3e00000f,0xff36ffff, + 0xfb803fff,0xff10ffff,0x0005ffff,0xffffff88,0xffff7003,0x1fffffcb, + 0x3ffffe60,0x09ffff92,0x7fffffdc,0x7fc406ff,0x1553003f,0x2fffff88, + 0x83fffff3,0x40001aa9,0x004ffffa,0x27ffffe4,0xfffffb00,0xfffffa87, + 0x44001501,0xf35fffff,0xe809ffff,0x7dc7ffff,0x000effff,0x7ffffdc0, + 0xfffb800f,0x3ffffe5f,0x7fffe406,0x9ffffb2f,0xfffffc80,0x7fcc01ff, + 0xf880003f,0xff32ffff,0x00003fff,0x3ffffa20,0x7ffc4001,0x6c405fff, + 0x986fffff,0x882fffff,0xfc800cff,0xff33ffff,0x2601ffff,0xe85fffff, + 0x02ffffff,0xfffd0498,0xfb807fff,0x3ff65fff,0xff101fff,0x3ee5ffff, + 0x6c00efff,0x806fffff,0x0002fffb,0x2fffff88,0x03fffff3,0xffb30000, + 0x2e0009ff,0xbeffffff,0xffeca88a,0xf882ffff,0x21aeffff,0x9bcffffd, + 0xfffeba88,0xfff31fff,0xfa83dfff,0x981fffff,0xdfffffff,0xfdaa99ab, + 0xffff982f,0x89abdfff,0x5ffffd99,0x3fffffe6,0x7ffffcc2,0xffff32ff, + 0x3f6a03bf,0x400effff,0x0000fffd,0x2fffff88,0x03fffff3,0x3ffee000, + 0x001fffff,0x3fffffa0,0xffffffff,0x205fffff,0x7fffffff,0xfffffff5, + 0xffffffff,0x7fcc7fff,0xefffffff,0x5fffffff,0x3fffff60,0xffffffff, + 0xff906fff,0xffffffff,0xffffffff,0xfffffd8b,0xfffffeff,0x3fa2ffff, + 0xeeffffff,0xfffffffe,0xff100eff,0x220000bf,0xf32fffff,0x0003ffff, + 0x3ffffee0,0x440004ff,0xfffffffc,0xffffffff,0x7ffe404f,0xffd37fff, + 0xffffffff,0x8bffffff,0xfceffff9,0xffffffff,0x7fdc01ff,0xffffffff, + 0x03ffffff,0xfffffff7,0xffffffff,0xfff98bff,0xffffffff,0x22ffffed, + 0xfffffff9,0xffffffff,0x706fffff,0x00005fff,0x4bffffe2,0x01fffff9, + 0xffff7000,0x40000dff,0xfffffffa,0x1effffff,0xfffff880,0x7fffd47f, + 0xffffffff,0xfff984ff,0xfffff95f,0x2003dfff,0xffffffe8,0xdfffffff, + 0x3fff6201,0xffffffff,0xe983ffff,0xffffffff,0x85ffffb5,0xfffffff9, + 0x9cffffff,0x505ffffe,0x440000fd,0xf32fffff,0x0003ffff,0x3ffffee0, + 0x4400000c,0xffffffec,0x44003eff,0x707ffffc,0xfffffffd,0x3e6019ff, + 0x3ff21eff,0x000dffff,0xfffffdb8,0x001dffff,0x3fffff66,0x0befffff, + 0x3ffff620,0x3ffa64ef,0xfffd702f,0x41bfffff,0x05ffffe8,0xf8800002, + 0xff32ffff,0x00003fff,0x0026aaa2,0x5d440000,0x200000ab,0x97310009, + 0x40000135,0x00001aa8,0x026b2a62,0x5dd4c000,0x5300009a,0x22000015, + 0x0009aaa9,0x20000000,0x26099999,0x00001999,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0xa8800000,0x0000abdb,0x4eeedc98,0x01ddddd3,0x33331000,0x33333333, + 0x98800133,0x001abcdb,0x5e6e5d44,0x2200000a,0x002eeeee,0x26200033, + 0x20009bcb,0x20019998,0x00eeeee9,0x654c4000,0xed802acd,0xddd34eee, + 0x7fd407dd,0x2fffffff,0xfffd9800,0xfff36fff,0xb00003ff,0xffffffff, + 0x05ffffff,0x3ffffae0,0x802effff,0xfffffffb,0x100003ff,0x107fffff, + 0xfffffd97,0xfff5003b,0x2003ffff,0x2007fffd,0x01fffff9,0xfffd3000, + 0x07ffffff,0x9afffff4,0x903fffff,0xffffffff,0x44009fff,0xffffffff, + 0x3fffff36,0xfffd0000,0xffffffff,0xd8805fff,0xffffffff,0xf105ffff, + 0xffffffff,0x0001ffff,0x3fffff88,0x7fffffdc,0x00efffff,0xfffffff7, + 0xff9807ff,0x3e6003ff,0x0001ffff,0x7ffffecc,0xffffffff,0x5ffffe80, + 0x87fffff3,0xffffffe8,0xefffffff,0xffffd800,0xff36ffff,0x00003fff, + 0xffffffff,0x5fffffff,0x7ffffd40,0xffffffff,0xfffe881f,0xffffffff, + 0x20000eff,0x33fffff8,0xfffffffd,0x1dffffff,0xdfffff98,0x201fffff, + 0x000ffffd,0x07ffffe6,0xffffb000,0xffffffff,0xfffd0dff,0x3fffe6bf, + 0x7fffe43f,0xffffefff,0x7cc04fff,0xceffffff,0x3fffff33,0xffff0000, + 0xffffffff,0x3e605fff,0xefffffff,0x906ffffe,0x9dffffff,0x9ffffffd, + 0x7ffc4000,0xffff73ff,0xffffffff,0xffd8bfff,0xfffd30df,0x3fffe60b, + 0x7ffcc004,0x440001ff,0xfeffffff,0x4fffffff,0x9afffff4,0x223fffff, + 0x0bffffff,0xffffff71,0x7fffd401,0xffff304f,0xf880003f,0x9999dfff, + 0x00999999,0x3dfffffb,0x7fc07aa0,0x7cc1efff,0x0007ffff,0x8fffffe2, + 0x9abdfffd,0x7fffffdb,0x307fffe2,0xfb01ffff,0x98001fff,0x001fffff, + 0x40aefb80,0x6fffffd9,0x9afffff4,0x323fffff,0x703fffff,0x409fffff, + 0x207ffffb,0x01fffff9,0x7fffcc00,0x7fcc0003,0x20004fff,0x04fffff8, + 0x01fffff9,0x3fffe200,0x8077e23f,0x31fffffe,0x3fe0ffff,0x7ffcc1ff, + 0xff98004f,0x00001fff,0xfffff005,0x5ffffe8f,0x27fffff3,0x06fffff8, + 0x07ffffec,0x06ffffc8,0x07ffffe6,0xffff5000,0xffe80007,0x4c0005ff, + 0x301fffff,0x005fffff,0x3ffffe20,0x7fd40043,0xfff52fff,0x0bfffe0d, + 0x001ffffb,0x3fffff30,0x64000000,0x3a1fffff,0xff35ffff,0x3fea7fff, + 0x7dc03fff,0x32a2ffff,0xcfffffec,0xfff32ccc,0x3f6e23ff,0x3ea02def, + 0x20002fff,0x01fffff9,0x7fffc400,0xffff301f,0x3e20001f,0x8003ffff, + 0x71fffffa,0x3fa0dfff,0x3ffe23ff,0xff30004f,0x32203fff,0x0003cccc, + 0xd1ffffee,0x3e6bffff,0xff73ffff,0xf8801fff,0x3ee3ffff,0xffffffff, + 0xfff34fff,0xffff33ff,0x2e09ffff,0x0001ffff,0x417fffee,0x3ff60009, + 0xfff904ff,0x7c4000bf,0x8003ffff,0x2a7ffffd,0xfff07fff,0x7fffe45f, + 0xfff30000,0x3ffa03ff,0x20001fff,0x745ffffe,0xff15ffff,0x3ff25fff, + 0xfff007ff,0x7ffdc9ff,0xffffffff,0xfffff34f,0xfffffff9,0xff907fff, + 0xdfdb53ff,0x7fe4017b,0xffd913ff,0xfb805bff,0x7d42ffff,0x0003ffff, + 0x0fffffe2,0xfffff700,0x83fffcc7,0xff11ffff,0x4c0009ff,0xc81fffff, + 0x003fffff,0x3ffffe60,0xafffff43,0xb2fffff8,0x200fffff,0x2e5ffffe, + 0xffffffff,0xff34ffff,0xffffffff,0x1fffffff,0xfeffffc8,0x3fffffff, + 0x55ffffb0,0xffffffff,0x3f6201bf,0xffdfffff,0x000effff,0x3ffffe20, + 0x3ffee003,0x7ffc45ff,0x7fffd41f,0x81ffff90,0x301bcdba,0xa83fffff, + 0x005fffff,0xff955553,0xfe81dfff,0xfff15fff,0x3fffa5ff,0xfffd006f, + 0x7f6654df,0xccccffff,0xffffff32,0xfff9359f,0xffd87fff,0xffffffff, + 0xfe86ffff,0xffffcfff,0x6fffffff,0x7ffffe40,0x04ffffff,0xffff8800, + 0xfff7003f,0xff901dff,0x3ffaa5df,0xbffff14f,0x7fffff4c,0x7ffcc0df, + 0x3ffe21ff,0x3f2006ff,0xffffffff,0xffffe80d,0x5fffff15,0x017ffffe, + 0x83ffffec,0x206ffffc,0x3ffffff9,0x4fffff98,0x7ffffff4,0xffffffff, + 0x7ffffc3f,0xffffffff,0x404fffff,0xfffffffe,0x100006ff,0x007fffff, + 0x1dfffff9,0x3ffffe20,0x90ffffff,0x3ea3ffff,0xffffffff,0x3fffe60e, + 0x3ffff61f,0x3ff2000f,0x1fffffff,0x2bffffd0,0xf2fffff8,0x200bffff, + 0x907ffffd,0x4c0dffff,0x206fffff,0x545fffff,0xdcdffffe,0xffffffff, + 0xffffff10,0xf93135df,0x301fffff,0xfffffffd,0x003dffff,0xfffff880, + 0x7fffd403,0x7fd400ef,0x2fffffff,0x74bffff1,0xffedffff,0x3ffe64ff, + 0xffff91ff,0xffc8005f,0xffffffff,0x7ffff40d,0x5fffff15,0x01bffffa, + 0x837ffff4,0x206ffffc,0x03fffff9,0x41bffff6,0xffd503da,0x7ffc7fff, + 0x3ee06fff,0x7e42ffff,0xfeffffff,0x04ffffff,0x3fffe200,0x7fffc03f, + 0xfd1000ef,0x641dffff,0xff71ffff,0x7ffdc3df,0xfffff30f,0x9fffffdb, + 0xffff9000,0xdfffffff,0xafffff41,0xb2fffff8,0x200fffff,0x905ffffe, + 0x4c0dffff,0x202fffff,0x006ffffc,0x3ffffe60,0x3fffffe4,0x7ffffc01, + 0x3ffffee3,0x7ffe542c,0xf10003ff,0x4c07ffff,0x002fffff,0x4409a988, + 0x3f65ffff,0xfffe83ff,0xffffff33,0x00dfffff,0x7fedcc00,0x3ffa4fff, + 0xffff15ff,0x3ffff25f,0xfffff007,0x3ffff209,0x3fffe606,0x3fff201f, + 0x7fc0006f,0x3ff65fff,0xffd807ff,0x3fffe5ff,0x7ffe404f,0xff10007f, + 0x7d407fff,0x0000ffff,0x1ffffc80,0x320bfffe,0xfff34fff,0xffffffff, + 0xf1000009,0x3a1fffff,0xff15ffff,0x3fee3fff,0x7cc01fff,0xf903ffff, + 0x7cc0dfff,0x3201ffff,0x0006ffff,0x937ffff4,0xb00fffff,0x3e69ffff, + 0x4c01ffff,0x001fffff,0x2fffff98,0x3ffffea0,0x7c400000,0x7ffc5fff, + 0x5fffc81f,0xfffffff3,0x005fffff,0xffff9000,0x3ffffa3f,0xa8666665, + 0x404fffff,0x02fffffb,0x40dffff9,0x01fffff9,0x01bffff2,0x9fffff00, + 0x03ffffdc,0xa9ffffec,0x400fffff,0x02fffff8,0xfffffa80,0x0ccccc01, + 0x7fe40000,0x3ffe21ff,0x6fffb81f,0x33fffff3,0x01fffffd,0xfffa8000, + 0xffffd2ff,0x7fffc00b,0x7fff406f,0xfff900ff,0x7ffcc0df,0x3ff201ff, + 0x260006ff,0x263fffff,0x401fffff,0xf32fffff,0x9803ffff,0x001fffff, + 0x0fffffc8,0x40000000,0xf86ffff8,0xffc81fff,0xfffff35f,0x3ffffe63, + 0x7dc00005,0xffd1ffff,0x7dc00bff,0xf904ffff,0x6407ffff,0x2606ffff, + 0x201fffff,0x4c6ffffc,0xfffe802f,0x7ffec1ff,0x3ffee05f,0x3fffe0ff, + 0x7ffe405f,0x100d40ff,0x00ffffff,0xf7000000,0xffd05fff,0x7fffb05f, + 0x87ffffe6,0x02fffffb,0x3e200664,0x3fa7ffff,0xddd35fff,0xffff87dd, + 0xfda8adff,0x6407ffff,0x2606ffff,0x201fffff,0x226ffffc,0x109beffe, + 0xdfffffd5,0x9fffff30,0xfffffb81,0x7fffff45,0x3ff2a0ac,0x7fc46fff, + 0xfea989ad,0x5404ffff,0x002eeeee,0x1bfffe00,0x7c2fffec,0xfff32fff, + 0xfffe83ff,0xfff500ff,0x7fdcc359,0x3fa5ffff,0xfff55fff,0xfffb89ff, + 0xffffffff,0x6403ffff,0x2606ffff,0x201fffff,0x326ffffc,0xffffffff, + 0xffffffff,0xfffffb01,0xfffffddf,0xfffa81ff,0xffefffff,0x42ffffff, + 0xfffffffc,0x0fffffff,0x7ffffdc0,0xff700003,0x3fe605ff,0xffea8dff, + 0x3fffe66f,0x7fffd41f,0xffff885f,0xffffffff,0x3a1fffff,0xff55ffff, + 0xff909fff,0xffffffff,0xf9009fff,0x7cc0dfff,0x3201ffff,0x3f66ffff, + 0xffffffff,0x03ffffff,0x3fffff62,0xffffffff,0xfffff703,0xffffffff, + 0xfff987ff,0xffffffff,0xfb803fff,0x0003ffff,0x80dffff0,0xfffffffc, + 0x3fe62fff,0xffd81fff,0x7fd43fff,0xffffffff,0x42ffffff,0xf55ffffe, + 0x2a09ffff,0xffffffff,0xf9002fff,0x7cc0dfff,0x3201ffff,0x7546ffff, + 0xffffffff,0x7002ffff,0xffffffff,0xfb805fff,0xffffffff,0xd883ffff, + 0xffffffff,0x7003ffff,0x007fffff,0x5ffff700,0xffffd880,0x7cc3ffff, + 0xf881ffff,0x441fffff,0xfffffffd,0x83ffffff,0xf55ffffe,0x4409ffff, + 0xfffffffd,0x3ff2000d,0x3fe606ff,0x3f201fff,0xfd706fff,0x9fffffff, + 0xfffb3000,0x0019ffff,0x3ffffee2,0x400bffff,0xffffffd9,0x2e000dff, + 0x003fffff,0x06ffff80,0x3ffffae0,0xffff981d,0xffff701f,0x3fb660df, + 0x3fffffff,0x57ffffa0,0x04fffffa,0x00155510,0x1bffff20,0x1fffff98, + 0x1bffff20,0x026aaa20,0x55544000,0x54c40000,0x300009aa,0x00035775, + 0x0fffffee,0x40000000,0x7fcc0198,0x3fa01fff,0x9804ffff,0x00009aaa, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x32e62000,0x3ba001bc,0x2e003eee,0x3aa6eeee, + 0x0004eeee,0x77774400,0x3bbbb25e,0xeec8003e,0xddd52eee,0xdddddddd, + 0xdddddddd,0x77647ddd,0xb1004eee,0x6c1bdddd,0xeeeeeeee,0x8009acde, + 0xeeeeeee8,0xeeeeeeee,0xdb2eeeee,0xdddddddd,0x6c01359b,0x0004eeee, + 0xffffc880,0x400dffff,0x004fffff,0x99fffff2,0x007fffff,0x7ffd4000, + 0x3ffea5ff,0xff8006ff,0xff70ffff,0xffffffff,0xffffffff,0x7cc9ffff, + 0x801fffff,0x43fffffc,0xfffffffe,0x3fffffff,0x7ffffc40,0xffffffff, + 0x3fffffff,0xfffffffd,0x5fffffff,0x17ffffa0,0xfff50000,0xffffffff, + 0x7fffc03d,0x3ff2004f,0x7fffc7ff,0x7fcc00ff,0xfc806fff,0x7fc3ffff, + 0x2000ffff,0x25fffffa,0xfffffffb,0xffffffff,0x4fffffff,0x37ffffdc, + 0x3ffffe60,0xfffffe85,0xffffffff,0xff101fff,0xffffffff,0xffffffff, + 0x3fffa7ff,0xffffffff,0x741effff,0x0005ffff,0x3ffffe60,0xffffffff, + 0xfffff02f,0x7ffe4009,0x7fffec7f,0x7ffdc02f,0x7ec00fff,0x7e41ffff, + 0x2003ffff,0x22fffffc,0xfffffffb,0xffffffff,0x4fffffff,0x2fffffe8, + 0x3fffffa0,0xfffffe80,0xffffffff,0xf880efff,0xffffffff,0xffffffff, + 0xfffd3fff,0xffffffff,0xe8dfffff,0x0005ffff,0x3fffffa0,0xffffdcce, + 0xffff80ff,0x3ff2004f,0x7ffdc7ff,0x7fec04ff,0x7c02ffff,0xf987ffff, + 0x2005ffff,0x20ffffff,0xccccccca,0xcfffffec,0x2ccccccc,0x6fffff98, + 0x7fffff70,0x3bffffa0,0xffeecccc,0x9905ffff,0x99999999,0xffff9999, + 0x3fffa5ff,0xdcaaaadf,0x24ffffff,0x005ffffe,0xfffff700,0xfffff309, + 0x9fffff07,0x7fffe400,0x7ffffc47,0x7ffffc05,0x3fe204ff,0xfff05fff, + 0xf3001fff,0x000bffff,0x00dffffb,0x7ffffe40,0x7ffffc43,0x3ffffa05, + 0x3fffea04,0x900000ff,0x749fffff,0x2a04ffff,0xd0ffffff,0x000bffff, + 0x17ffffa0,0x86ffffa8,0x004fffff,0x21fffff2,0x207ffffe,0xfffffff9, + 0x3fffea06,0xffff902f,0xfff7005f,0xfb0005ff,0x8000dfff,0x20fffffe, + 0x00fffffd,0x013ffffa,0x03fffff7,0xffff5000,0xffffe8bf,0x7fffdc04, + 0xbffffd2f,0x3ffe0000,0x7ff401ff,0x7fffc2ff,0x3ff2004f,0xfffc87ff, + 0xfff900ff,0x203fffff,0x00fffffc,0x0bfffff3,0x0fffffd0,0x3ffff600, + 0x7fcc0006,0xfff55fff,0xffe805ff,0x7fc404ff,0x40003fff,0x86fffff9, + 0x404ffffe,0xd3fffff8,0x000bffff,0x1fffff10,0x5ffffd80,0x027ffffc, + 0x0fffff90,0x05fffff5,0x3ffffffa,0xfffb03ff,0xfffe80df,0x7ffc407f, + 0xfb0004ff,0x0000dfff,0xd5fffff9,0xd00bffff,0xf009ffff,0x0007ffff, + 0x7fffffc4,0x4ffffe80,0x4fffff80,0x00bffffd,0xfffff500,0xdffffb00, + 0x04fffff8,0x1fffff20,0x13ffffe2,0x3fbfffe2,0xfff05fff,0xffb809ff, + 0x3ea01fff,0x0001ffff,0x00dffffb,0xffffd100,0x01ffffff,0x09ffffd0, + 0x2fffff88,0xfffd1000,0x3ffa03ff,0xfff804ff,0xffffd4ff,0xff30000b, + 0xfe801fff,0x7ffc7fff,0x3f2004ff,0xffd07fff,0xfff50bff,0x0fffff5f, + 0x05fffff1,0x4fffff88,0x1bffff60,0xffffd800,0xff500006,0x5fffffff, + 0x3ffffa00,0x7fffdc04,0xffb0001f,0x7f405fff,0x7c404fff,0xffd3ffff, + 0x10000bff,0x805fffff,0x7c7fffff,0x2004ffff,0x707ffffc,0xf90fffff, + 0xfffb1fff,0xffffa83f,0xfffd800f,0x3fffe06f,0x3f60003f,0x00006fff, + 0x3ffffff6,0x3ffa005f,0x3fea04ff,0x90005fff,0x809fffff,0x404ffffe, + 0xd2fffffa,0x000bffff,0x1bffffe0,0xffffffb8,0x13ffffe0,0x7ffffc80, + 0x3fffff30,0xf76fffe8,0xffb87fff,0xff5006ff,0xff303fff,0x40001fff, + 0x006ffffd,0x3fffe200,0x3a000fff,0xaaadffff,0xfffffecb,0xffa8001f, + 0xfe805fff,0x3e604fff,0xfd0fffff,0x0000bfff,0x3bfffff6,0xffff910b, + 0x7ffc3fff,0x3f2004ff,0x3fe07fff,0x3fe22fff,0xffff14ff,0x3ffffd8d, + 0xfffff100,0xbffff907,0xfffd8000,0x7400006f,0x00ffffff,0x3fffffa0, + 0xffffffff,0x98002fff,0x00efffff,0xadffffe8,0xfffdbaaa,0x3ffa4fff, + 0x300005ff,0xffffffff,0xfffffffd,0x7fffc1ff,0x3ff2004f,0x3ff607ff, + 0x3ffea4ff,0x3ffffa1f,0x07ffffe0,0x6ffffd80,0x02ffffe8,0x7fffec00, + 0x3f200006,0x05ffffff,0x3fffffa0,0xffffffff,0xf88002ef,0x000fffff, + 0xfffffffd,0xffffffff,0xffffe8df,0x3f200005,0xffffffff,0x7ffffeff, + 0x027ffffc,0x0fffff90,0xb2ffffdc,0xffc8ffff,0xffff12ff,0xfffa800f, + 0x3ffe60ff,0x6c0000ff,0x0006ffff,0xffffff30,0x3a005fff,0xffffffff, + 0x001fffff,0x3fffffa0,0x3fffa001,0xffffffff,0x741effff,0x0005ffff, + 0x7ffffe40,0xffacffff,0x7fffc6ff,0x3ff2004f,0x3fe207ff,0x3fffe7ff, + 0xa7fffcc5,0x005ffffa,0x22fffff8,0x005ffffb,0x6ffffd80,0xfffd0000, + 0x1fffffff,0xdffffd00,0xfffffd99,0x3ff60007,0x74003fff,0xffffffff, + 0x03ffffff,0x00bffffd,0xfffd5000,0x3fee7dff,0x7fff45ff,0x3ff6005f, + 0x7ff406ff,0xffff99ff,0x76ffff83,0x0007ffff,0x6cbffff9,0x0002ffff, + 0x06ffffd8,0xffffb800,0x5fffffbf,0x4ffffe80,0x07fffff4,0x3ffff200, + 0xffe8004f,0xdeeeefff,0x3fa00abc,0x00005fff,0x7ec0d4c0,0x7fec4fff, + 0x3fa006ff,0x7e405fff,0xfffbafff,0xffffd81f,0x01ffffd8,0x7ffff980, + 0x00fffff1,0x3ffff600,0x7fcc0006,0xfffb3fff,0xffe805ff,0x7ffcc4ff, + 0x3ea006ff,0x0005ffff,0x009ffffd,0x5ffffe80,0x10000000,0xc85fffff, + 0x2007ffff,0x404fffff,0xfdcffffa,0xfff706ff,0x0dfffd5f,0x7ffff400, + 0x04ffffaa,0xffffb000,0xffe8000d,0x3ffe26ff,0x3fa00fff,0xffc84fff, + 0xf9803fff,0x000effff,0x09ffffd0,0xffffe800,0x00000005,0x70dffff9, + 0x007fffff,0x07fffff7,0xfeffff88,0xff104fff,0x9ffffdff,0x7ffdc000, + 0x1ffffdcf,0xfffb0000,0x7dc000df,0x7dc2ffff,0x3a05ffff,0xf884ffff, + 0x200fffff,0x0ffffff8,0x3fffa000,0x7f40004f,0x00005fff,0x3fee0062, + 0xff882fff,0x2601ffff,0x00ffffff,0xffffffe8,0x3ffa02ff,0x02ffffff, + 0x3fffe200,0x006fffff,0x3ffff600,0xfff10006,0x3ffa0bff,0xffd02fff, + 0x3fea09ff,0x3fa05fff,0x0001ffff,0x027ffff4,0x3ffffa00,0x3f600005, + 0xfb5309bd,0x5c0dffff,0xacffffff,0xffffca88,0xff7004ff,0x01ffffff, + 0x7fffffe4,0x740000ff,0xffffffff,0x3f600003,0xd0006fff,0x201fffff, + 0x0ffffff9,0x04ffffe8,0x0ffffff6,0x37fffff6,0xaaaaaaaa,0xd1aaaaaa, + 0x0009ffff,0xaeffffe8,0xaaaaaaaa,0xfff302aa,0xffffffff,0xf803ffff, + 0xffffffff,0xffffffff,0x3ffe6007,0x5406ffff,0x6fffffff,0xfffb8000, + 0x000fffff,0x3ffff600,0xfffb8006,0x7fe403ff,0xffe85fff,0x3fe604ff, + 0x7f40ffff,0xffffffff,0xffffffff,0xfffd3fff,0xfe80009f,0xffffffff, + 0x5fffffff,0xffffffd0,0xdfffffff,0xffff5003,0xffffffff,0x8005ffff, + 0x3fffffff,0xffffff80,0xf880004f,0x06ffffff,0x7ffec000,0x7fc4006f, + 0xf8806fff,0x742fffff,0x6404ffff,0x745fffff,0xffffffff,0xffffffff, + 0xffd3ffff,0xe80009ff,0xffffffff,0xffffffff,0xfffff705,0xbfffffff, + 0x7ff4c001,0xffffffff,0xd8000eff,0x01ffffff,0xffffffd8,0xffb00001, + 0x0007ffff,0x6ffffd80,0x7fffec00,0xfff5002f,0x7ff41fff,0x7fc404ff, + 0x3fa2ffff,0xffffffff,0xffffffff,0xfffd3fff,0xfe80009f,0xffffffff, + 0x5fffffff,0x3fffee20,0x003dffff,0x3ffffae0,0x003effff,0x3ffffee0, + 0xffff7007,0x540000ff,0x00ffffff,0x7ffec000,0x3fea006f,0x6c005fff, + 0x3a5fffff,0xa804ffff,0xd0ffffff,0xffffffff,0xffffffff,0x3fa7ffff, + 0x40004fff,0xfffffffe,0xffffffff,0x2aa6005f,0x9800000a,0x0001abba, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x77775400,0x3b62004e,0x3bb65eee,0xd3002eee, + 0x776cdddd,0x30002eee,0x36bddddd,0xb004eeee,0x6c7ddddd,0xeeeeeeee, + 0xeeeeeeee,0x09ddddb2,0x277776c0,0x440cccc0,0xeed80999,0xeeeeeeee, + 0x1eeeeeee,0x3372ea20,0x2666202a,0x99999999,0x09999999,0xdddddddb, + 0x003579bd,0xffffff10,0x3ffee003,0x3fffa2ff,0xf9800fff,0x3ffa7fff, + 0xb0006fff,0x3adfffff,0xc805ffff,0x746fffff,0xffffffff,0xffffffff, + 0x0bffffd3,0x37ffff40,0x21fffe60,0xfe84fffc,0xffffffff,0xffffffff, + 0xfffffb82,0xc82effff,0xffffffff,0xffffffff,0xffffd5ff,0xffffffff, + 0xfb8005bf,0xf004ffff,0xfe8dffff,0x803fffff,0x3a7ffff9,0x03ffffff, + 0x7ffffcc0,0xbffffd6f,0xfffff980,0x7ffff40f,0xffffffff,0xffd3ffff, + 0x7f400bff,0x7d406fff,0xfffd86ff,0xfffffe83,0xffffffff,0x3aa2ffff, + 0xffffffff,0x7e45ffff,0xffffffff,0xffffffff,0xfffffd5f,0xffffffff, + 0xfe800bff,0x5c00ffff,0x742fffff,0x0fffffff,0x3ffffcc0,0xdffffffd, + 0xffffd800,0xffffd6ff,0x7fffc40b,0xfffe82ff,0xffffffff,0xfd3fffff, + 0x7400bfff,0x5c06ffff,0xffe85fff,0xffffe81f,0xffffffff,0xf52fffff, + 0xffffffff,0x47ffffff,0xfffffffc,0xffffffff,0xfffd5fff,0xffffffff, + 0x007fffff,0x27ffffd4,0x17ffffa0,0x3ffffffa,0x7ffcc04f,0x3ffffa7f, + 0xf3003fff,0x2dffffff,0x205ffffe,0x04fffffd,0x99dffffd,0x99999999, + 0x3ffffa59,0x3fffa005,0x7ffe406f,0x80ffff83,0xcceffffe,0xcccccccc, + 0x3fffa1cc,0xffffeeff,0xff91ffff,0xffffffff,0xffffffff,0x3bffffab, + 0xfffeeccc,0x2001ffff,0x00fffffe,0x03fffff5,0xfffffffd,0x7ffcc01f, + 0x3ffffa7f,0xfb006fff,0x2dffffff,0x705ffffe,0x40dfffff,0x005ffffe, + 0x0bffffd0,0x37ffff40,0x10bfff60,0x3fa0ffff,0x40005fff,0x2209dff8, + 0x2fffffea,0x33333331,0xfd333333,0x3ffa7fff,0xffd304ff,0x4c005fff, + 0xd03fffff,0x3a09ffff,0xffffffff,0x3fffe605,0x3fffffa7,0x7cc02fff, + 0x6fffffff,0x10bffffd,0x01ffffff,0x02fffff4,0x5ffffe80,0x3ffffa00, + 0x0ffff406,0x741bffe6,0x0005ffff,0x7fdc01a8,0x20004fff,0xd0fffff9, + 0x4409ffff,0x004fffff,0x437fffec,0x00fffffa,0xfffffffd,0x3fe603ff, + 0x3fffa7ff,0x406fffff,0xfffffffd,0xbffffd6f,0x5fffffd0,0x5ffffe80, + 0xffffd000,0x7fff400b,0x3fffea6f,0xffffffff,0xffffffff,0x0bffffd2, + 0x3e200000,0x0005ffff,0xe93ffff6,0x7c04ffff,0x4005ffff,0x42fffff8, + 0x204ffffe,0xffdffffe,0xfff305ff,0x7ffff4ff,0x302fffff,0xffffffff, + 0x3ffffadf,0x7ffffe45,0xffffe804,0xfffd0005,0x7ff400bf,0x3ffea6ff, + 0xffffffff,0xffffffff,0xbffffd2f,0x7c000000,0x0003ffff,0x41fffff1, + 0x404ffffe,0x003ffffe,0x26ffffc8,0x00fffff9,0x3afffffa,0xf981ffff, + 0x3ffa7fff,0x6ffffcff,0xf9ffffb0,0x3ffadfff,0x3ffea5ff,0xffd005ff, + 0x3a000bff,0x2005ffff,0x2a6ffffe,0xffffffff,0xffffffff,0xffd2ffff, + 0x00000bff,0x3ffffe60,0xfff90001,0xffffe8bf,0x3fffe204,0xff88001f, + 0xfffb2fff,0xfffe807f,0x6ffff9bf,0x27ffff98,0xfcbffffe,0x7fcc2fff, + 0xffffbcff,0x2bffffd6,0x0ffffffa,0xbffffd00,0x3fffa000,0x3ffa005f, + 0x333266ff,0xcccefffe,0xccdffffc,0xbffffd1c,0x32000000,0x0007ffff, + 0xd07ffffe,0x2209ffff,0x007ffffd,0x37fffee0,0x806ffff9,0xfb3ffffe, + 0xff985fff,0x3fffa7ff,0x6ffff8bf,0x5c7fffec,0xffd6ffff,0xffffffff, + 0x7f4003ff,0x9999efff,0x74099999,0xeeefffff,0xfeeeeeee,0x3206ffff, + 0xfff84fff,0xffffd01f,0xdddddddf,0x20005ddd,0x05fffffb,0xdffff700, + 0x9dffffd0,0xffffdb99,0xf80001df,0xfffeffff,0xfffe802f,0xdffff13f, + 0x27ffff98,0xf93ffffe,0x3fe65fff,0xffff74ff,0x3fffffad,0x03ffffff, + 0x7fffff40,0xffffffff,0x7ffff45f,0xffffffff,0xffffffff,0x0ffff606, + 0x201ffff1,0xfffffffe,0xffffffff,0xfffa8002,0xd0001fff,0xfd07ffff, + 0xffffffff,0x009fffff,0x3fffee00,0xd005ffff,0x7e47ffff,0x3fe63fff, + 0x3fffa7ff,0xdffff13f,0x5c3ffff6,0xffd6ffff,0xffffffff,0xffe8007f, + 0xffffffff,0x7f45ffff,0xffffffff,0xffffffff,0x3fa06fff,0x7ffcc2ff, + 0x3ffffa07,0xffffffff,0x64002fff,0x03ffffff,0xfffff500,0x3fffffa0, + 0xffffffff,0xd00002df,0x3fffffff,0x3ffffa00,0x9ffffe23,0x3a7ffff9, + 0x3f23ffff,0xffffcfff,0x5bfffee4,0xfffffffe,0x001fffff,0x3ffffffa, + 0xffffffff,0x7fffff45,0xffffffff,0x6fffffff,0x507fffe0,0x7f40dfff, + 0xffffffff,0x02ffffff,0xfffffb10,0x7ec0007f,0xffd04fff,0xffffffff, + 0x1bffffff,0xfffa8000,0x3a005fff,0x7dc3ffff,0xfff33fff,0x7ffff4ff, + 0x3ffffe23,0x3ee0ffff,0xfffd6fff,0xffffd5df,0x3fa001df,0xffffffff, + 0x745fffff,0xccceffff,0xfccccccc,0xf106ffff,0xfff70fff,0x7ffff409, + 0xccccccce,0xf9801ccc,0x02ffffff,0x3fffe600,0xffffd00f,0xd975555b, + 0x00dfffff,0xfffffd00,0x7fff4001,0xfffff83f,0x27ffff98,0x643ffffe, + 0x4fffffff,0xeb7fffdc,0x3f65ffff,0xd005ffff,0x555dffff,0x85555555, + 0x005ffffe,0x41bffffa,0xfc87fff9,0x3ffa03ff,0x200005ff,0xfffffffa, + 0x7fe40001,0x3ffa05ff,0x7fdc04ff,0x40003fff,0x007ffffd,0x41fffff4, + 0xf9cffffb,0x3ffa7fff,0x7ffc43ff,0x7dc0ffff,0xfffd6fff,0x7fffc4bf, + 0xffe803ff,0xfd0005ff,0x7400bfff,0xff56ffff,0xffffffff,0xffffffff, + 0x7fff45ff,0xf300005f,0x01bfffff,0xffff8800,0x3fffa01f,0xfffd804f, + 0x7ec0006f,0x74007fff,0xfd03ffff,0xffff5fff,0x1fffff4f,0x27ffffe4, + 0xeb7fffdc,0x7d45ffff,0x401fffff,0x005ffffe,0x0bffffd0,0xb7ffff40, + 0xfffffffa,0xffffffff,0x3a2fffff,0x0005ffff,0xffffff98,0xff700004, + 0xffe80dff,0xffb804ff,0x6c0007ff,0x4007ffff,0x503ffffe,0xfffdffff, + 0x7ffff4ff,0xfffff883,0x6ffffb80,0x90bffffd,0x01ffffff,0x02fffff4, + 0x5ffffe80,0x3ffffa00,0xffffff56,0xffffffff,0x45ffffff,0x005ffffe, + 0x7ffffc40,0x3e00002f,0x7402ffff,0xb804ffff,0x000fffff,0x1fffff60, + 0x7ffffd00,0x7ffffec0,0x3ffa7fff,0x333103ff,0x3fffee01,0x0bffffd6, + 0x17fffffa,0x05ffffe8,0xbffffd00,0x7ffff400,0xffd55516,0xff75559f, + 0x415555ff,0x005ffffe,0x7ffffec0,0x3ea00002,0xfe807fff,0xfd804fff, + 0x40007fff,0x007ffffd,0x01fffff4,0xfffffff3,0x7ffff4ff,0x7fdc0003, + 0xffffd6ff,0x3fffe60b,0xfffd03ff,0x3fa000bf,0x3a005fff,0xff06ffff, + 0xfff983ff,0x7ffff406,0x7ffc0005,0x400003ff,0x803ffffe,0x404ffffe, + 0x05fffffb,0x7fffec00,0x7fff4007,0x7ffec03f,0x3fa7ffff,0x40003fff, + 0xfd6ffffb,0x7dc0bfff,0xe81fffff,0x0005ffff,0x00bffffd,0x437ffff4, + 0x5c0ffff8,0x7f405fff,0xaaaaefff,0xaaaaaaaa,0x7fffff31,0x55555555, + 0xff980355,0xfe800fff,0xaaaadfff,0xfffffecb,0x7ec0003f,0x74007fff, + 0x4403ffff,0x7fffffff,0x00fffffa,0xdffff700,0x017ffffa,0x1ffffffb, + 0x05ffffe8,0xbffffd00,0x7ffff400,0x87fff986,0x7404fffc,0xffffffff, + 0xffffffff,0xfffff74f,0xffffffff,0xfd80bfff,0xfd004fff,0xffffffff, + 0xffffffff,0xffb0000d,0xfe800fff,0xfc803fff,0x3a7fffff,0x0003ffff, + 0xeb7fffdc,0x4405ffff,0x46ffffff,0x005ffffe,0x0bffffd0,0x37ffff40, + 0x6c37ffd4,0x7f402fff,0xffffffff,0xffffffff,0xffffffb4,0xffffffff, + 0x7fc40bff,0xfd001fff,0xffffffff,0xffffffff,0xffb00001,0xfe800fff, + 0xf8803fff,0x3a7fffff,0x0003ffff,0xeb7fffdc,0xa805ffff,0x24ffffff, + 0x005ffffe,0x0bffffd0,0x37ffff40,0x742fffdc,0x7f401fff,0xffffffff, + 0xffffffff,0xffffffb4,0xffffffff,0x7fe40bff,0x3fa005ff,0xffffffff, + 0x0cffffff,0xfffb0000,0xffe800ff,0xff7003ff,0x7ff4ffff,0x5c0003ff, + 0xffd6ffff,0x3f600bff,0xfd2fffff,0x2000bfff,0x005ffffe,0x21bffffa, + 0xff83fffc,0x7ff400ff,0xffffffff,0x4fffffff,0xfffffffb,0xffffffff, + 0x3ffe20bf,0x3fa002ff,0xffffffff,0x000bcdef,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0xddddd100,0x3300000b,0x44000333,0xed809999,0xdeeeeeee,0x220001ac, + 0x00019999,0x00000000,0x00000000,0x00000000,0x00000000,0xf5000000, + 0x003fffff,0x3fffaa00,0xe88000ff,0xfe84ffff,0xffffffff,0x003effff, + 0x03ffffe4,0xdfffdb30,0xb9500179,0x007bdffd,0x3ffb2e60,0x93000bde, + 0x017bdfdb,0xffedb980,0x664402cd,0x3b2a20ac,0xcc882def,0x3f6e60ac, + 0xdb980acf,0xb0003eff,0x09ffffff,0xfffea800,0x8000ffff,0x84fffffd, + 0xfffffffe,0xffffffff,0xfff9001e,0xffb100ff,0xffffffff,0xfffd5019, + 0x5dffffff,0x7fffe400,0x04ffffff,0x3fffff62,0x8803ffff,0xfffffffd, + 0xff302eff,0x3ffe69ff,0x4c4fffff,0xff54ffff,0xc8dfffff,0xefffffff, + 0x3ffe2000,0x0007ffff,0xffffffd5,0xa8001fff,0x84ffffff,0xfffffffe, + 0xffffffff,0xffc804ff,0x7f4407ff,0xffffffff,0x3fa25fff,0xffffffff, + 0x4c01ffff,0xfffffffe,0xf505ffff,0xffffffff,0x7d40bfff,0xffffffff, + 0xf985ffff,0xfff9efff,0x3fffffff,0x27bfffe6,0xffffffff,0xfffff95f, + 0x400dffff,0xfffffffb,0x3fae002f,0xffffffff,0x3e2000ff,0x84ffffff, + 0xeefffffe,0xffffffee,0x7e403fff,0x7e407fff,0xffffffff,0x7ec1ffff, + 0xffffffff,0x2206ffff,0xffffffff,0x881fffff,0xffffffff,0x82ffffff, + 0xfffffff8,0xffffffff,0x7ffffcc4,0xffffffff,0xff30ffff,0xffffffff, + 0xfbffffff,0xffffffff,0x3fa005ff,0x5fffffff,0xfffff500,0xffffffff, + 0x7fff4001,0xfe84ffff,0xd5105fff,0x81ffffff,0xffffecc9,0x3a0ccccf, + 0x99bfffff,0xf885fdb9,0xeca9abef,0xb02fffff,0x9bffffff,0x360df975, + 0x52dfffff,0x81fffffb,0xaefffffd,0xfffffca9,0x3fffe61f,0xfc9acfff, + 0xf33fffff,0x59ffffff,0xfffffff7,0xfff759ff,0xf300dfff,0xffff5fff, + 0x3ffa001f,0xfffdefff,0xff9000ff,0x09ffffff,0x00bffffd,0x8bfffff9, + 0xfffffffb,0xf11fffff,0x4c07ffff,0xff805701,0xffa84fff,0x0202ffff, + 0x07ffffea,0x517fffec,0x209fffff,0x26fffff9,0x3ffffff9,0x4fffff98, + 0x5ffffff3,0xffffffd0,0xffffff03,0x1ffff900,0x005ffffb,0x5cffffea, + 0x800fffff,0xfffffffa,0xfffe84ff,0xfffd005f,0x7ffdc5ff,0xffffffff, + 0xfffff11f,0x64000007,0xfd85ffff,0x8001ffff,0x206ffffd,0x364ffffa, + 0x6407ffff,0xf30fffff,0x7c0dffff,0xff35ffff,0x3f20bfff,0xf905ffff, + 0xff00ffff,0x3ffeabff,0x0ffa005f,0x01fffff7,0xdfffff88,0xfe84ffff, + 0xf5005fff,0x7dcbffff,0xffffffff,0x3ffe1fff,0x0000cfff,0x6ffffa80, + 0x05ffffe8,0x5ffffd00,0x2ffffc40,0x809fffff,0x32fffff9,0x407fffff, + 0xf36ffffd,0x2a05ffff,0x502fffff,0x401fffff,0xf13ffffa,0x2001ffff, + 0xfffff700,0xffffd801,0x84ffffbb,0x005ffffe,0x99fffffa,0xfffffecc, + 0x3ee0cccc,0xceffffff,0x332a2001,0xffffeeee,0x7ffffc46,0xfff88003, + 0xeeeeeeff,0x16ffffee,0x007fffff,0x267fffff,0x202fffff,0xf36ffffc, + 0x2603ffff,0x501fffff,0x401fffff,0x360ffffd,0x0003ffff,0x07ffffdc, + 0x2dffff70,0xe84ffffb,0x2005ffff,0x80fffffc,0x807ffffc,0xfffffffd, + 0x32202eff,0xffffffff,0x7cc6ffff,0x8002ffff,0xfffffff9,0xffffffff, + 0xffff36ff,0xffff005f,0x3fffe69f,0x3fff201f,0xfffff36f,0x3fffe603, + 0xffff500f,0x3ffe201f,0x7fffdc6f,0x7fdc0006,0xff300fff,0x3fee1fff, + 0xfffe84ff,0x3ff2005f,0xffc81fff,0xfb3007ff,0xffffffff,0xfffff109, + 0xffffffff,0xffffa8df,0xff98001f,0xffffffff,0x6fffffff,0x03fffff5, + 0x2bffffd0,0x01fffff9,0x4dbffff2,0x301fffff,0x201fffff,0x00fffffa, + 0x887ffff7,0x001fffff,0x3ffffee0,0xffffe880,0x13fffee2,0x017ffffa, + 0x2fffffb8,0x07ffffc8,0x7fffecc0,0x3a23ffff,0xabdfffff,0x46ffffca, + 0x02fffff8,0xfffff880,0xaaaaaaab,0xff11aaaa,0xff005fff,0x3fe69fff, + 0x3f201fff,0xfff36fff,0x3fe603ff,0xff500fff,0x3fa01fff,0xffe81fff, + 0x2e0004ff,0xd80fffff,0x7dc5ffff,0xffe84fff,0x3ea005ff,0xfc83ffff, + 0x20007fff,0x7fffffd9,0x07ffffea,0x21bfffea,0x004fffff,0x03fffff0, + 0x7ffffc00,0x7fffc403,0xfffff32f,0x7fffe403,0x3fffff36,0x3ffffe60, + 0xfffff500,0xfffff101,0x1ffffee0,0xffffb800,0x7fffd40f,0x7fffdc0e, + 0x5ffffe84,0x3fffea00,0xffffc83f,0xffc80007,0xfff70fff,0x3fff20bf, + 0xffffe86f,0xfffd0007,0x7f40009f,0x7d406fff,0xff31ffff,0x7e403fff, + 0xfff36fff,0x3fe603ff,0xff500fff,0xff701fff,0x3fe609ff,0x70002fff, + 0x441fffff,0xb81fffff,0xfe84ffff,0x2e005fff,0xc81fffff,0x2807ffff, + 0x7ffffd40,0x09ffffb0,0x21bffffe,0x04fffffc,0xfffffc80,0xfff90001, + 0x7ff403ff,0x3ffe67ff,0x3ff201ff,0xffff36ff,0x3ffe603f,0xfff500ff, + 0xfffd01ff,0xdddddddf,0x00bfffff,0x3ffffee0,0x13ffffa0,0x427fffdc, + 0x005ffffe,0x03fffff2,0x01fffff2,0xe8815df7,0x3f27ffff,0x2e20ffff, + 0x887fffff,0x9effffff,0x3e21ae60,0x303fffff,0xffff10bb,0xffe885ff, + 0x3fe63fff,0x3f201fff,0xfff36fff,0x3fe603ff,0xff500fff,0xff981fff, + 0xffffffff,0xffffffff,0xfffb8000,0xffff70ff,0xb999999f,0x999dffff, + 0x017ffffa,0x07ffffd8,0x40fffff9,0xdefffff8,0x5ffffffe,0x3fffffea, + 0xffffffcd,0x7fd43eff,0xffffffff,0xffb82fff,0xeeefffff,0xfb82ffff, + 0xfeffffff,0x46ffffff,0x01fffff9,0x4dbffff2,0x301fffff,0x201fffff, + 0x40fffffa,0xfffffffc,0xffffffff,0xb8003fff,0xf90fffff,0xffffffff, + 0xffffffff,0x3fffafff,0xfff1005f,0x3fee0dff,0xff900fff,0xffffffff, + 0xfe81ffff,0xffffffff,0x5fffffdf,0xffffffd8,0x05ffffff,0xfffffffb, + 0x0dffffff,0x3ffffff6,0xffffffff,0x7ffffcc1,0x3ffff201,0x3fffff36, + 0x3ffffe60,0xfffff500,0xffffff81,0xffffffff,0x006fffff,0x0fffffb8, + 0xfffffff9,0xffffffff,0x3fafffff,0xf9005fff,0x2a07ffff,0x103fffff, + 0xfffffffb,0x305fffff,0xffffffff,0x3ffff69f,0xfffff705,0x1fffffff, + 0x3ffffee0,0x4fffffff,0x3ffffee0,0x0dffffff,0x1fffff98,0x5bffff20, + 0x01fffff9,0x01fffff3,0x83ffffea,0xaafffffa,0xdaaaaaaa,0x000fffff, + 0x87ffffdc,0xfffffffc,0xffffffff,0xffd7ffff,0xff500bff,0x7cc0dfff, + 0x1bcfffff,0xfffffd98,0x2200cfff,0x3efffffd,0x817fff62,0xffffffd8, + 0x6c400cff,0xffffffff,0xffd8800d,0x02efffff,0x07ffffe6,0x36ffffc8, + 0x203fffff,0x00fffff9,0x41fffff5,0x005ffffd,0x07fffff3,0xfffffb80, + 0x99999950,0xffb99999,0x3a999dff,0x2205ffff,0x2ffffffd,0x3ffffe20, + 0x2201ffff,0x0009aaa9,0x30026a62,0x554c4001,0x53100009,0x44000135, + 0x00001aa9,0x00000000,0xffff1000,0x7ffc007f,0x7dc006ff,0x0000ffff, + 0xd09ffff7,0x999dffff,0xfffffdb9,0xff900bff,0x03ffffff,0x00000000, + 0x00000000,0x00000000,0x00000000,0xff700000,0x64001fff,0x001fffff, + 0x03ffffee,0x7fffdc00,0xfffffe84,0xffffffff,0x000effff,0xfffffffd, + 0x00000003,0x00000000,0x00000000,0x00000000,0xd0000000,0x800dffff, + 0x04fffffa,0x3ffffee0,0xfff70000,0xffffd09f,0xffffffff,0x0007ffff, + 0x3fffffd5,0x00000000,0x00000000,0x00000000,0x00000000,0xf9800000, + 0x8003ffff,0x007fffff,0x03ffffee,0x7fffdc00,0xfffffe84,0xffffffff, + 0x880000df,0x00000019,0x00000000,0x00000000,0x00000000,0x00000000, + 0x03fffff9,0xfffffb00,0x3ffee005,0xf70000ff,0xffd09fff,0xdfffffff, + 0x00003579,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x30000000,0x44099999,0x910ccccc,0x00079999,0x00288540, + 0x33332e00,0xcccc9804,0x9999971c,0x66640000,0x999933cc,0x6664c059, + 0x999950cc,0x99999999,0x50019999,0x91005555,0xdb881599,0x33332005, + 0xdddd1004,0x3bba209d,0x3bbba604,0x7fffdc04,0x3fffe207,0xfffff11f, + 0xeb88000d,0x017df31f,0xffffb800,0x7ffe401f,0xffff70ff,0x2666203f, + 0xffff1009,0x7fffec7f,0xffffd00f,0x7ffffe4b,0xffffffff,0xfe801fff, + 0xff9806ff,0xfffd34ff,0x3ffea00f,0xff8802ff,0xff106fff,0x7ffd40bf, + 0x7ffdc06f,0x3ffe207f,0xffff11ff,0x322000df,0xff31ffff,0x200019ff, + 0x04fffff8,0x32fffff4,0x207fffff,0x506ffffb,0x443fffff,0xb85fffff, + 0x320effff,0xffffffff,0xffffffff,0x6fffe801,0x6ffff980,0x00fffffd, + 0x1bfffffa,0x3ffffe20,0x09fff026,0x02ffffcc,0x81ffffee,0x11fffff8, + 0x00dfffff,0xfffffda8,0xfffff31f,0xfb0005bf,0x7c40dfff,0x7f42ffff, + 0xffd04fff,0xff701fff,0xfff50dff,0x7ffc45ff,0x7ffe41ff,0xffffffff, + 0x801fffff,0x9806fffe,0xffbeffff,0xfa807fff,0x02ffffff,0x37ffffc4, + 0x4bffe1bd,0x3ffe63ea,0x7ffdc05f,0x3ffe207f,0xffff11ff,0xfd7100df, + 0x3fffffff,0x3fffffe6,0x5000beff,0x201fffff,0xc87ffffb,0xf886ffff, + 0xd83fffff,0xfb04ffff,0x7fe4dfff,0xccca84ff,0xfdcccccc,0x800effff, + 0x9806fffe,0xffffffff,0xfe806fff,0x06ffffff,0xafffffc4,0xffecfff9, + 0x3e66ffec,0x7dc05fff,0x3e207fff,0xff11ffff,0x6440dfff,0xffffffff, + 0x3ff623ef,0xffffffff,0xffff800c,0xffffb03f,0xfffff309,0xfffffa81, + 0xfffff85f,0xfffff101,0x0dffff37,0x7fffc400,0xffd000ef,0xfff300df, + 0x013dffff,0x3bfffea0,0x2202ffff,0xf94fffff,0xffffffff,0x3fe63fff, + 0x7fdc04ff,0x3fe207ff,0x2aaa1fff,0xffda82aa,0xcfffffff,0x3ffae201, + 0xdfffffff,0x3ffff201,0x1fffff05,0x07ffffe0,0xfffffff9,0x07ffff88, + 0x77ffffd4,0x0000ffff,0x1fffffd1,0x37fff400,0x7ffffcc0,0xffe8004f, + 0x6ffff8ff,0x73fff880,0xfffffffb,0x3e23bfff,0x7dc04fff,0x3e207fff, + 0x2001ffff,0xffffffeb,0x4000beff,0xffffffc9,0xf983efff,0xffa87fff, + 0x3ff606ff,0x7fffc3ff,0x3ea1ffff,0xfc804fff,0x3fffffff,0xfffd1000, + 0xfe8003ff,0xff9806ff,0x4000ffff,0xf94ffffa,0xf9805fff,0x7fd443ff, + 0xf881dfff,0x7dc04fff,0x3e207fff,0x3001ffff,0xffffffff,0x51000039, + 0xfffffffd,0xffffd03f,0x2ffffc85,0x97fffea0,0xffddfff9,0x3fffee3f, + 0xfffe8802,0x20005fff,0x01fffffd,0xfffffff9,0xffffffff,0x3ffe6bff, + 0xfe8004ff,0xfff30fff,0xfffb80df,0xfffffc82,0xffff881f,0x7fffdc03, + 0x3fffe207,0xfff3001f,0x00005bff,0x7fffe4c0,0xfffb81ff,0x7ffffc4f, + 0x3fffe200,0x2efffee7,0x3ff65fff,0x3fe6007f,0x0000ffff,0x05fffffb, + 0x7fffffe4,0xffffffff,0xfff35fff,0xfa8007ff,0x7ff45fff,0x3ff602ff, + 0x6fffdc0f,0xff80ffff,0x7fdc03ff,0x3fe207ff,0xf3001fff,0x017dffff, + 0x7ecc0000,0xf881ffff,0x3fe66fff,0xffd804ff,0x1fffb0ff,0x7fcffff1, + 0x3e6005ff,0x001fffff,0x2fffffc8,0x7ffffe40,0xffffffff,0xff35ffff, + 0xe8005fff,0x7dc2ffff,0xff106fff,0xffffb8bf,0x40efffb8,0x5c009999, + 0x2607ffff,0x001fffff,0xfffffff3,0x200005bf,0xfffffeb8,0xfffb01ff, + 0x3fffee3f,0xffffb801,0x7f4dfff2,0xffff89ff,0x3fffa003,0x2000efff, + 0x03fffffb,0xffffffc8,0xffffffff,0xfff35fff,0x7d4003ff,0xfff06fff, + 0xfff705ff,0x22fffd85,0x0002fffe,0x07ffffdc,0x1fffffb8,0x3fffee00, + 0x0cffffff,0xfffda800,0x0cffffff,0x27ffff50,0x1006fffe,0xff59ffff, + 0x67ffe49f,0x000ffffa,0xfffffff9,0x3fee009f,0x31004fff,0xffd33333, + 0x333333ff,0x3ffffe61,0x3fffa001,0xffff903f,0x5c1faa0d,0x0077cc6f, + 0x7fffd400,0xffffb01f,0xfd50003f,0xffffffff,0xffb8805b,0xefffffff, + 0xffff800b,0x03ffff8d,0x33bfffa0,0x3fea2fff,0x06fffcef,0xfdffff50, + 0xa805ffff,0x004fffff,0x0dfffd00,0x3fffff30,0x3fffea00,0xffff300f, + 0x3300405f,0x4c000050,0x883fffff,0x11ffffff,0x409ddddd,0xffffffd9, + 0x2a0cffff,0xfffffffd,0x64001dff,0xfffbffff,0x3ff2000f,0x447ffeff, + 0xfffeffff,0xffff8803,0xfffffb9f,0xfffff300,0x7f40000b,0xff9806ff, + 0xfd001fff,0xfd80bfff,0x00006fff,0x3e200000,0x221effff,0x1ffffffd, + 0x0dfffff1,0xfffff910,0x3e63ffff,0xffffffff,0xff10000c,0x0bffffff, + 0xfffff980,0xfffd85ff,0xd801ffff,0x3fa4ffff,0xff985fff,0x9999efff, + 0x00999999,0x806fffe8,0x01fffff9,0x1fffffa8,0x7ffffd40,0x00000001, + 0x3ffffa00,0xffffefff,0xff11ffff,0xa800dfff,0x1ffffffe,0xdffffff3, + 0x3f600007,0x02ffffff,0xffffff80,0xffffb83f,0xffb806ff,0x3fe60eff, + 0x7ff43fff,0xffffffff,0x02ffffff,0x806fffe8,0x01fffff9,0x01999988, + 0x01333330,0x00000000,0x7fffffd4,0xffedffff,0xffff11ff,0x366000df, + 0xff31ffff,0x00003bff,0xffffffa8,0xfff90007,0xff301fff,0x9809ffff, + 0xc82fffff,0x3a0fffff,0xffffffff,0xffffffff,0x6fffe802,0xfffff980, + 0x00000001,0x00000000,0xfffffd80,0xfffb5fff,0x3fffe23f,0x6440006f, + 0x19ff31ff,0x7fc00000,0x0004ffff,0x0dfffff5,0x0ffffffc,0x17ffffa0, + 0x37ffffc4,0xfffffffd,0xffffffff,0xfffd005f,0xffff300d,0x0000003f, + 0x00000000,0x3ffee000,0xfd30dfff,0x3ffe23ff,0x200006ff,0x0000710a, + 0x3ffff200,0xff10001f,0x7e409fff,0x7e407fff,0x2a00ffff,0xfd4fffff, + 0xffffffff,0x5fffffff,0x05555500,0x3fffff30,0x00000000,0x00000000, + 0x00554c40,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0xaaaaaa88,0xaaaaaaaa,0xddd30aaa, + 0x7777649d,0x0aaaaaa1,0x0b37b2a0,0x22bdddd0,0x515eeeee,0x55555555, + 0x3bba1555,0xeeeeeeee,0xeeeeeeee,0x00000001,0x00000000,0x00000000, + 0x00000000,0x3fe20000,0xffffffff,0x0fffffff,0x74dffff5,0x3ee2ffff, + 0xd102ffff,0x3dffffff,0x2dffff10,0x76fffff8,0xffffffff,0x3fe3ffff, + 0xffffffff,0xffffffff,0x0000002f,0x00000000,0x00000000,0x00000000, + 0x3e200000,0xffffffff,0xffffffff,0x4bffff30,0x6c1ffffd,0xfd06ffff, + 0xffffffff,0x5ffff989,0x2dfffff1,0xfffffffb,0xff1fffff,0xffffffff, + 0xffffffff,0x0000005f,0x00000000,0x00000000,0x00000000,0x7c400000, + 0xffffffff,0xffffffff,0x4bffff30,0x441ffffd,0x543fffff,0xffffffff, + 0xfebbefff,0xfff14fff,0x3ffeedff,0xffffffff,0xffffff1f,0xffffffff, + 0x005fffff,0x00000000,0x00000000,0x00000000,0x00000000,0x77777440, + 0xeeeeeeee,0xff30eeee,0x7ffecbff,0xffffa81f,0x7ffffe47,0xffffffcb, + 0x12ffffff,0x2edfffff,0xffffffff,0x1111ffff,0x11111111,0x11111111, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x24ffff98, + 0x900ffffc,0x7ec7ffff,0x3f621fff,0xffffffff,0x3ffffe26,0x22222226, + 0x00088888,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0xfff88000,0x3ffff24f,0x3ffffa00,0x01ffffd0,0xffffffd5,0x0000003d, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0xf8800000, + 0x3ff24fff,0x266200ff,0xddddb099,0x3deeca80,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0xfff10000,0x3fffe47f, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x88000000,0xeeeeeeee,0xeeeeeeee,0x8ffffe0e,0x0007fffb,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0xfff10000, + 0xffffffff,0x41ffffff,0x26209999,0x00000199,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0xfffff100,0xffffffff, + 0x0001ffff,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x80000000,0xfffffff8,0xffffffff,0x000000ff,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x54400000, + 0xaaaaaaaa,0xaaaaaaaa,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +}; + +static signed short stb__intelclearbd_x[95]={ 0,2,1,0,1,1,1,1,1,0,1,2,1,1, +1,0,0,2,2,1,1,1,1,1,1,1,1,1,2,2,2,0,1,0,3,2,3,3,3,2,3,3,0,3, +3,3,3,1,3,1,3,1,0,2,0,0,0,0,1,3,0,0,1,0,4,1,2,1,1,1,0,1,2,2, +-1,2,2,2,2,1,2,1,2,1,0,2,0,0,0,0,1,0,3,0,1, }; +static signed short stb__intelclearbd_y[95]={ 38,11,11,11,7,11,10,11,9,9,11,15,32,25, +32,9,11,11,11,11,11,11,11,11,11,11,18,18,15,18,15,10,11,11,11,10,11,11,11,10,11,11,11,11, +11,11,11,10,11,10,11,10,11,11,11,11,11,11,11,9,9,9,11,42,8,17,10,17,10,17,10,17,10,10, +10,10,10,17,17,17,17,17,18,17,13,18,18,18,18,18,18,9,9,9,21, }; +static unsigned short stb__intelclearbd_w[95]={ 0,7,14,23,21,35,26,6,12,11,14,19,7,14, +7,17,23,15,18,20,21,20,21,20,21,21,7,7,19,19,19,18,36,26,21,22,23,19,18,23,22,6,18,23, +18,27,23,28,20,28,22,21,24,24,26,38,26,25,22,11,17,11,21,20,11,19,21,18,21,19,14,21,19,7, +10,20,9,31,19,21,21,21,14,17,14,19,21,30,20,21,18,15,7,15,21, }; +static unsigned short stb__intelclearbd_h[95]={ 0,27,11,27,36,28,29,11,36,36,14,20,14,6, +6,36,28,27,27,28,27,28,28,27,28,28,20,28,20,14,20,28,36,27,27,29,27,27,27,29,27,27,28,27, +27,27,27,29,27,33,27,29,27,28,27,27,27,27,27,36,36,36,17,5,8,22,29,22,29,22,28,30,28,28, +37,28,29,21,21,22,30,30,20,22,26,21,20,20,20,29,20,36,38,36,8, }; +static unsigned short stb__intelclearbd_s[95]={ 255,248,41,145,36,163,219,242,74,87,227, +162,219,98,90,99,1,28,189,220,44,60,81,208,103,1,21,246,29,21,49, +144,117,1,229,150,66,169,103,173,122,241,125,79,233,51,27,67,212,196,166, +106,114,23,87,48,139,1,189,184,166,154,197,113,56,123,128,143,197,162,25, +225,40,247,9,199,96,224,204,182,23,1,182,105,90,1,69,91,122,45,143, +58,1,20,68, }; +static unsigned short stb__intelclearbd_t[95]={ 1,71,206,129,1,71,40,185,1,1,185, +185,185,206,206,1,71,157,129,71,157,71,71,129,71,100,185,40,185,206,185, +71,1,157,129,40,157,129,129,40,129,71,71,129,100,129,129,40,100,1,100, +40,100,100,100,100,100,129,100,1,1,1,185,206,206,157,40,157,40,157,71, +1,71,1,1,71,40,157,157,157,40,40,185,157,157,185,185,185,185,40,185, +1,1,1,206, }; +static unsigned short stb__intelclearbd_a[95]={ 151,180,256,368,368,597,422,136, +200,200,249,368,155,253,155,262,368,368,368,368,368,368,368,368, +368,368,155,155,368,368,368,300,609,413,393,393,439,367,346,433, +447,190,327,411,340,528,451,479,390,479,395,379,386,448,412,600, +406,391,378,222,262,222,368,310,310,330,385,305,385,344,219,352, +376,175,175,351,196,557,376,375,385,385,242,300,226,368,329,480, +319,329,311,242,213,242,368, }; + +// Call this function with +// font: NULL or array length +// data: NULL or specified size +// height: STB_FONT_intelclearbd_BITMAP_HEIGHT or STB_FONT_intelclearbd_BITMAP_HEIGHT_POW2 +// return value: spacing between lines +static void stb_font_intelclearbd(stb_fontchar font[STB_FONT_intelclearbd_NUM_CHARS], + unsigned char data[STB_FONT_intelclearbd_BITMAP_HEIGHT][STB_FONT_intelclearbd_BITMAP_WIDTH], + int height) +{ + int i,j; + if (data != 0) { + unsigned int *bits = stb__intelclearbd_pixels; + unsigned int bitpack = *bits++, numbits = 32; + for (i=0; i < STB_FONT_intelclearbd_BITMAP_WIDTH*height; ++i) + data[0][i] = 0; // zero entire bitmap + for (j=1; j < STB_FONT_intelclearbd_BITMAP_HEIGHT-1; ++j) { + for (i=1; i < STB_FONT_intelclearbd_BITMAP_WIDTH-1; ++i) { + unsigned int value; + if (numbits==0) bitpack = *bits++, numbits=32; + value = bitpack & 1; + bitpack >>= 1, --numbits; + if (value) { + if (numbits < 3) bitpack = *bits++, numbits = 32; + data[j][i] = (bitpack & 7) * 0x20 + 0x1f; + bitpack >>= 3, numbits -= 3; + } else { + data[j][i] = 0; + } + } + } + } + + // build font description + if (font != 0) { + float recip_width = 1.0f / STB_FONT_intelclearbd_BITMAP_WIDTH; + float recip_height = 1.0f / height; + for (i=0; i < STB_FONT_intelclearbd_NUM_CHARS; ++i) { + // pad characters so they bilerp from empty space around each character + font[i].s0 = (stb__intelclearbd_s[i]) * recip_width; + font[i].t0 = (stb__intelclearbd_t[i]) * recip_height; + font[i].s1 = (stb__intelclearbd_s[i] + stb__intelclearbd_w[i]) * recip_width; + font[i].t1 = (stb__intelclearbd_t[i] + stb__intelclearbd_h[i]) * recip_height; + font[i].x0 = stb__intelclearbd_x[i]; + font[i].y0 = stb__intelclearbd_y[i]; + font[i].x1 = stb__intelclearbd_x[i] + stb__intelclearbd_w[i]; + font[i].y1 = stb__intelclearbd_y[i] + stb__intelclearbd_h[i]; + font[i].advance_int = (stb__intelclearbd_a[i]+8)>>4; + font[i].s0f = (stb__intelclearbd_s[i] - 0.5f) * recip_width; + font[i].t0f = (stb__intelclearbd_t[i] - 0.5f) * recip_height; + font[i].s1f = (stb__intelclearbd_s[i] + stb__intelclearbd_w[i] + 0.5f) * recip_width; + font[i].t1f = (stb__intelclearbd_t[i] + stb__intelclearbd_h[i] + 0.5f) * recip_height; + font[i].x0f = stb__intelclearbd_x[i] - 0.5f; + font[i].y0f = stb__intelclearbd_y[i] - 0.5f; + font[i].x1f = stb__intelclearbd_x[i] + stb__intelclearbd_w[i] + 0.5f; + font[i].y1f = stb__intelclearbd_y[i] + stb__intelclearbd_h[i] + 0.5f; + font[i].advance = stb__intelclearbd_a[i]/16.0f; + } + } +} + +#ifndef STB_SOMEFONT_CREATE +#define STB_SOMEFONT_CREATE stb_font_intelclearbd +#define STB_SOMEFONT_BITMAP_WIDTH STB_FONT_intelclearbd_BITMAP_WIDTH +#define STB_SOMEFONT_BITMAP_HEIGHT STB_FONT_intelclearbd_BITMAP_HEIGHT +#define STB_SOMEFONT_BITMAP_HEIGHT_POW2 STB_FONT_intelclearbd_BITMAP_HEIGHT_POW2 +#define STB_SOMEFONT_FIRST_CHAR STB_FONT_intelclearbd_FIRST_CHAR +#define STB_SOMEFONT_NUM_CHARS STB_FONT_intelclearbd_NUM_CHARS +#define STB_SOMEFONT_LINE_SPACING STB_FONT_intelclearbd_LINE_SPACING +#endif + diff --git a/Projects/Asteroids/src/mesh.cpp b/Projects/Asteroids/src/mesh.cpp new file mode 100644 index 0000000..bef24b6 --- /dev/null +++ b/Projects/Asteroids/src/mesh.cpp @@ -0,0 +1,352 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#include "mesh.h" +#include "noise.h" +#include <map> +#include <random> + +using namespace DirectX; + +void CreateIcosahedron(Mesh *outMesh) +{ + static const float a = std::sqrt(2.0f / (5.0f - std::sqrt(5.0f))); + static const float b = std::sqrt(2.0f / (5.0f + std::sqrt(5.0f))); + + static const size_t num_vertices = 12; + static const Vertex vertices[num_vertices] = // x, y, z + { + {-b, a, 0}, + { b, a, 0}, + {-b, -a, 0}, + { b, -a, 0}, + { 0, -b, a}, + { 0, b, a}, + { 0, -b, -a}, + { 0, b, -a}, + { a, 0, -b}, + { a, 0, b}, + {-a, 0, -b}, + {-a, 0, b}, + }; + + static const size_t num_triangles = 20; + static const IndexType indices[num_triangles*3] = + { + 0, 5, 11, + 0, 1, 5, + 0, 7, 1, + 0, 10, 7, + 0, 11, 10, + 1, 9, 5, + 5, 4, 11, + 11, 2, 10, + 10, 6, 7, + 7, 8, 1, + 3, 4, 9, + 3, 2, 4, + 3, 6, 2, + 3, 8, 6, + 3, 9, 8, + 4, 5, 9, + 2, 11, 4, + 6, 10, 2, + 8, 7, 6, + 9, 1, 8, + }; + + outMesh->clear(); + outMesh->vertices.insert(outMesh->vertices.end(), vertices, vertices + num_vertices); + outMesh->indices.insert(outMesh->indices.end(), indices, indices + num_triangles*3); +} + + +// Maps edge (lower index first!) to +struct Edge +{ + Edge(IndexType i0, IndexType i1) + : v0(i0), v1(i1) + { + if (v0 > v1) + std::swap(v0, v1); + } + IndexType v0; + IndexType v1; + + bool operator<(const Edge &c) const + { + return v0 < c.v0 || (v0 == c.v0 && v1 < c.v1); + } +}; + +typedef std::map<Edge, IndexType> MidpointMap; + +inline IndexType EdgeMidpoint(Mesh *mesh, MidpointMap *midpoints, Edge e) +{ + auto index = midpoints->find(e); + if (index == midpoints->end()) + { + auto a = mesh->vertices[e.v0]; + auto b = mesh->vertices[e.v1]; + + Vertex m; + m.x = (a.x + b.x) * 0.5f; + m.y = (a.y + b.y) * 0.5f; + m.z = (a.z + b.z) * 0.5f; + + index = midpoints->insert(std::make_pair(e, static_cast<IndexType>(mesh->vertices.size()))).first; + mesh->vertices.push_back(m); + } + return index->second; +} + + +void SubdivideInPlace(Mesh *outMesh) +{ + MidpointMap midpoints; + + std::vector<IndexType> newIndices; + newIndices.reserve(outMesh->indices.size() * 4); + outMesh->vertices.reserve(outMesh->vertices.size() * 2); + + assert(outMesh->indices.size() % 3 == 0); // trilist + size_t triangles = outMesh->indices.size() / 3; + for (size_t t = 0; t < triangles; ++t) + { + auto t0 = outMesh->indices[t*3+0]; + auto t1 = outMesh->indices[t*3+1]; + auto t2 = outMesh->indices[t*3+2]; + + auto m0 = EdgeMidpoint(outMesh, &midpoints, Edge(t0, t1)); + auto m1 = EdgeMidpoint(outMesh, &midpoints, Edge(t1, t2)); + auto m2 = EdgeMidpoint(outMesh, &midpoints, Edge(t2, t0)); + + IndexType indices[] = { + t0, m0, m2, + m0, t1, m1, + m0, m1, m2, + m2, m1, t2, + }; + newIndices.insert(newIndices.end(), indices, indices + 4*3); + } + + std::swap(outMesh->indices, newIndices); // Constant time +} + + +void SpherifyInPlace(Mesh *outMesh, float radius) +{ + for (auto &v : outMesh->vertices) { + float n = radius / std::sqrt(v.x*v.x + v.y*v.y + v.z*v.z); + v.x *= n; + v.y *= n; + v.z *= n; + } +} + + +void ComputeAvgNormalsInPlace(Mesh *outMesh) +{ + for (auto &v : outMesh->vertices) { + v.nx = 0.0f; + v.ny = 0.0f; + v.nz = 0.0f; + } + + assert(outMesh->indices.size() % 3 == 0); // trilist + size_t triangles = outMesh->indices.size() / 3; + for (size_t t = 0; t < triangles; ++t) + { + auto v1 = &outMesh->vertices[outMesh->indices[t*3+0]]; + auto v2 = &outMesh->vertices[outMesh->indices[t*3+1]]; + auto v3 = &outMesh->vertices[outMesh->indices[t*3+2]]; + + // Two edge vectors u,v + auto ux = v2->x - v1->x; + auto uy = v2->y - v1->y; + auto uz = v2->z - v1->z; + auto vx = v3->x - v1->x; + auto vy = v3->y - v1->y; + auto vz = v3->z - v1->z; + + // cross(u,v) + float nx = uy*vz - uz*vy; + float ny = uz*vx - ux*vz; + float nz = ux*vy - uy*vx; + + // Do not normalize... weight average by contributing face area + v1->nx += nx; v1->ny += ny; v1->nz += nz; + v2->nx += nx; v2->ny += ny; v2->nz += nz; + v3->nx += nx; v3->ny += ny; v3->nz += nz; + } + + // Normalize + for (auto &v : outMesh->vertices) { + float n = 1.0f / std::sqrt(v.nx*v.nx + v.ny*v.ny + v.nz*v.nz); + v.nx *= n; + v.ny *= n; + v.nz *= n; + } +} + + +void CreateGeospheres(Mesh *outMesh, unsigned int subdivLevelCount, unsigned int* outSubdivIndexOffsets) +{ + CreateIcosahedron(outMesh); + outSubdivIndexOffsets[0] = 0; + + std::vector<Vertex> vertices(outMesh->vertices); + std::vector<IndexType> indices(outMesh->indices); + + for (unsigned int i = 0; i < subdivLevelCount; ++i) { + outSubdivIndexOffsets[i+1] = (unsigned int)indices.size(); + SubdivideInPlace(outMesh); + + // Ensure we add the proper offset to the indices from this subdiv level for the combined mesh + // This avoids also needing to track a base vertex index for each subdiv level + IndexType vertexOffset = (IndexType)vertices.size(); + vertices.insert(vertices.end(), outMesh->vertices.begin(), outMesh->vertices.end()); + + for (auto newIndex : outMesh->indices) { + indices.push_back(newIndex + vertexOffset); + } + } + outSubdivIndexOffsets[subdivLevelCount+1] = (unsigned int)indices.size(); + + SpherifyInPlace(outMesh); + + // Put the union of vertices/indices back into the mesh object + std::swap(outMesh->indices, indices); + std::swap(outMesh->vertices, vertices); +} + + +void CreateAsteroidsFromGeospheres(Mesh *outMesh, + unsigned int subdivLevelCount, unsigned int meshInstanceCount, + unsigned int rngSeed, + unsigned int* outSubdivIndexOffsets, unsigned int* vertexCountPerMesh) +{ + assert(subdivLevelCount <= meshInstanceCount); + + std::mt19937 rng(rngSeed); + + Mesh baseMesh; + CreateGeospheres(&baseMesh, subdivLevelCount, outSubdivIndexOffsets); + + // Per unique mesh + *vertexCountPerMesh = (unsigned int)baseMesh.vertices.size(); + std::vector<Vertex> vertices; + vertices.reserve(meshInstanceCount * baseMesh.vertices.size()); + // Reuse indices for the different unique meshes + + auto randomNoise = std::uniform_real_distribution<float>(0.0f, 10000.0f); + auto randomPersistence = std::normal_distribution<float>(0.95f, 0.04f); + float noiseScale = 0.5f; + float radiusScale = 0.9f; + float radiusBias = 0.3f; + + // Create and randomize unique vertices for each mesh instance + for (unsigned int m = 0; m < meshInstanceCount; ++m) { + Mesh newMesh(baseMesh); + NoiseOctaves<4> textureNoise(randomPersistence(rng)); + float noise = randomNoise(rng); + + for (auto &v : newMesh.vertices) { + float radius = textureNoise(v.x*noiseScale, v.y*noiseScale, v.z*noiseScale, noise); + radius = radius * radiusScale + radiusBias; + v.x *= radius; + v.y *= radius; + v.z *= radius; + } + ComputeAvgNormalsInPlace(&newMesh); + + vertices.insert(vertices.end(), newMesh.vertices.begin(), newMesh.vertices.end()); + } + + // Copy to output + std::swap(outMesh->indices, baseMesh.indices); + std::swap(outMesh->vertices, vertices); +} + + +void CreateSkyboxMesh(std::vector<SkyboxVertex>* outVertices) +{ + // See http://msdn.microsoft.com/en-us/library/windows/desktop/bb204881(v=vs.85).aspx + + // Cube mesh centered at zero + static const float c = 0.5f; + static const DirectX::XMFLOAT3 vertexPos[] = { // x, y, z + {-c, c, -c}, // 0 + { c, c, -c}, // 1 + { c, c, c}, // 2 + {-c, c, c}, // 3 + {-c, -c, c}, // 4 + { c, -c, c}, // 5 + { c, -c, -c}, // 6 + {-c, -c, -c}, // 7 + }; + + static const size_t numIndices = 6*6; + static const unsigned int indices[numIndices] = { + 2, 6, 1, 2, 5, 6, // right (+c, ., .), face 0 + 0, 4, 3, 0, 7, 4, // left (-c, ., .), face 1 + 0, 2, 1, 0, 3, 2, // top ( ., +c, .), face 2 + 4, 6, 5, 4, 7, 6, // bottom ( ., -c, .), face 3 + 3, 5, 2, 3, 4, 5, // back ( ., ., +c), face 4 + 1, 6, 7, 1, 7, 0, // front ( ., ., -c), face 5 + }; + + // Flatten out the indexed mesh and add the per-face parameters + std::vector<SkyboxVertex> vertices(numIndices); + for (size_t i = 0; i < numIndices; ++i) { + auto &v = vertices[i]; + + v.x = vertexPos[indices[i]].x; + v.y = vertexPos[indices[i]].y; + v.z = vertexPos[indices[i]].z; + + auto face = i / 6; + v.face = (float)face; + + // Face uv's are fairly manual + switch (face) + { + case 0: + v.u = -v.z; + v.v = -v.y; + break; + case 1: + v.u = v.z; + v.v = -v.y; + break; + case 2: + v.u = v.x; + v.v = v.z; + break; + case 3: + v.u = v.x; + v.v = -v.z; + break; + case 4: + v.u = v.x; + v.v = -v.y; + break; + case 5: + v.u = -v.x; + v.v = -v.y; + break; + }; + // Move to 0..1 + v.u += 0.5f; + v.v += 0.5f; + } + + std::swap(*outVertices, vertices); +} diff --git a/Projects/Asteroids/src/mesh.h b/Projects/Asteroids/src/mesh.h new file mode 100644 index 0000000..4031a7e --- /dev/null +++ b/Projects/Asteroids/src/mesh.h @@ -0,0 +1,74 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include <vector> +#include <directxmath.h> + +typedef unsigned short IndexType; + +// NOTE: This data could be compressed, but it's not really the bottleneck at the moment +struct Vertex +{ + float x; + float y; + float z; + float nx; + float ny; + float nz; +}; + +struct Mesh +{ + void clear() + { + vertices.clear(); + indices.clear(); + } + + std::vector<Vertex> vertices; + std::vector<IndexType> indices; +}; + +void CreateIcosahedron(Mesh *outMesh); + +// 1 face -> 4 faces +void SubdivideInPlace(Mesh *outMesh); + +void SpherifyInPlace(Mesh *outMesh, float radius = 1.0f); + +void ComputeAvgNormalsInPlace(Mesh *outMesh); + +// subdivIndexOffset array should be [subdivLevels+2] in size +void CreateGeospheres(Mesh *outMesh, unsigned int subdivLevelCount, unsigned int* outSubdivIndexOffsets); + +// Returns a combined "mesh" that includes: +// - A set of indices for each subdiv level (outSubdivIndexOffsets for offsets/counts) +// - A set of vertices for each mesh instance (base vertices per mesh computed from vertexCountPerMesh) +// - Indices already have the vertex offsets for the correct subdiv level "baked-in", so only need the mesh offset +void CreateAsteroidsFromGeospheres(Mesh *outMesh, + unsigned int subdivLevelCount, unsigned int meshInstanceCount, + unsigned int rngSeed, + unsigned int* outSubdivIndexOffsets, unsigned int* vertexCountPerMesh); + + +struct SkyboxVertex +{ + float x; + float y; + float z; + float u; + float v; + float face; +}; + +// Skybox mesh... vertices-only currently +void CreateSkyboxMesh(std::vector<SkyboxVertex>* outVertices);
\ No newline at end of file diff --git a/Projects/Asteroids/src/noise.h b/Projects/Asteroids/src/noise.h new file mode 100644 index 0000000..250ae5c --- /dev/null +++ b/Projects/Asteroids/src/noise.h @@ -0,0 +1,57 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include "simplexnoise1234.h" + +// Very simple multi-octave simplex noise helper +// Returns noise in the range [0, 1] vs. the usual [-1, 1] +template <size_t N = 4> +class NoiseOctaves +{ +private: + float mWeights[N]; + float mWeightNorm; + +public: + NoiseOctaves(float persistence = 0.5f) + { + float weightSum = 0.0f; + for (size_t i = 0; i < N; ++i) { + mWeights[i] = persistence; + weightSum += persistence; + persistence *= persistence; + } + mWeightNorm = 0.5f / weightSum; // Will normalize to [-0.5, 0.5] + } + + // Returns [0, 1] + float operator()(float x, float y, float z) const + { + float r = 0.0f; + for (size_t i = 0; i < N; ++i) { + r += mWeights[i] * snoise3(x, y, z); + x *= 2.0f; y *= 2.0f; z *= 2.0f; + } + return r * mWeightNorm + 0.5f; + } + + // Returns [0, 1] + float operator()(float x, float y, float z, float w) const + { + float r = 0.0f; + for (size_t i = 0; i < N; ++i) { + r += mWeights[i] * snoise4(x, y, z, w); + x *= 2.0f; y *= 2.0f; z *= 2.0f; w *= 2.0f; + } + return r * mWeightNorm + 0.5f; + } +};
\ No newline at end of file diff --git a/Projects/Asteroids/src/settings.h b/Projects/Asteroids/src/settings.h new file mode 100644 index 0000000..d130eca --- /dev/null +++ b/Projects/Asteroids/src/settings.h @@ -0,0 +1,92 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include "camera.h" +#include "common_defines.h" + +// Profiling +#define ENABLE_VTUNE_TASK_PROFILING 1 + +// Content settings +#ifdef _DEBUG +enum { NUM_ASTEROIDS = 2000 }; +#else +enum { NUM_ASTEROIDS = 50000 }; +#endif +enum { TEXTURE_DIM = 256 }; // Req'd to be pow2 at the moment +enum { TEXTURE_ANISO = 2 }; +enum { NUM_UNIQUE_MESHES = 1000 }; +enum { MESH_MAX_SUBDIV_LEVELS = 3 }; // 4x polys for each step. +// See common_defines.h for NUM_UNIQUE_TEXTURES (also needed by shader now) + +#define SIM_ORBIT_RADIUS 450.f +#define SIM_DISC_RADIUS 120.f +#define SIM_MIN_SCALE 0.2f + +// In FLIP swap chains the compositor owns one of your buffers at any given point +// Thus to run unconstrained (>vsync) frame rates, you need 3 buffers +enum { NUM_SWAP_CHAIN_BUFFERS = 5 }; + +// In D3D12, this is the pipeline depth in frames - larger = more latency, shorter = potential bubbles. +// Usually 2-4 are good values. +enum { NUM_FRAMES_TO_BUFFER = 3 }; + +// In D3D12 this is the number of command buffers we generate for the main scene rendering +// Also effectively max thread parallelism +enum { NUM_SUBSETS = 4 }; + +// Buffer size for dynamic sprite data +enum { MAX_SPRITE_VERTICES_PER_FRAME = 6 * 1024 }; + + +// This structure is often copied/passed by value so don't put anything really expensive in it. +struct Settings +{ + double closeAfterSeconds = 0.0; + + // Will be scaled based on DPI at app start for convenience + double renderScale = 1.0; // 1.0 = window dimensions, <1 = upscaling, >1 = supersampling + int windowWidth = 1080; + int windowHeight = 720; + int renderWidth; + int renderHeight; + + int numThreads = 0; // 0 means #cpu-1 + unsigned int lockedFrameRate = 15; + + bool logFrameTimes = false; + bool vsync = 0; + + bool windowed = true; + enum RenderMode + { + NativeD3D11, + NativeD3D12, + DiligentD3D11, + DiligentD3D12, + DiligentGL + }mode = DiligentD3D11; + + bool lockFrameRate = false; + bool animate = true; + + // Multithreading actually makes debugging annoying so disable by default +#if defined(_DEBUG) + bool multithreadedRendering = true; +#else + bool multithreadedRendering = true; +#endif + + bool submitRendering = true; + bool executeIndirect = false; + bool warp = false; +}; diff --git a/Projects/Asteroids/src/simplexnoise1234.c b/Projects/Asteroids/src/simplexnoise1234.c new file mode 100644 index 0000000..a0f0814 --- /dev/null +++ b/Projects/Asteroids/src/simplexnoise1234.c @@ -0,0 +1,499 @@ +/* SimplexNoise1234, Simplex noise with true analytic + * derivative in 1D to 4D. + * + * Author: Stefan Gustavson, 2003-2005 + * Contact: stegu@itn.liu.se + */ + + /* +This code was GPL licensed until February 2011. +As the original author of this code, I hereby +release it irrevocably into the public domain. +Please feel free to use it for whatever you want. +Credit is appreciated where appropriate, and I also +appreciate being told where this code finds any use, +but you may do as you like. Alternatively, if you want +to have a familiar OSI-approved license, you may use +This code under the terms of the MIT license: + +Copyright (C) 2003-2005 by Stefan Gustavson. All rights reserved. +This code is licensed to you under the terms of the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/** \file + \brief C implementation of Perlin Simplex Noise over 1,2,3, and 4 dimensions. + \author Stefan Gustavson (stegu@itn.liu.se) +*/ + +/* + * This implementation is "Simplex Noise" as presented by + * Ken Perlin at a relatively obscure and not often cited course + * session "Real-Time Shading" at Siggraph 2001 (before real + * time shading actually took on), under the title "hardware noise". + * The 3D function is numerically equivalent to his Java reference + * code available in the PDF course notes, although I re-implemented + * it from scratch to get more readable code. The 1D, 2D and 4D cases + * were implemented from scratch by me from Ken Perlin's text. + * + * This file has no dependencies on any other file, not even its own + * header file. The header file is made for use by external code only. + */ + + +// We don't need to include this. It does no harm, but no use either. +#include "simplexnoise1234.h" + +#pragma warning(disable: 4244) // conversion double -> float + +#define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : (((int)x)-1) ) + +//--------------------------------------------------------------------- +// Static data + +/* + * Permutation table. This is just a random jumble of all numbers 0-255, + * repeated twice to avoid wrapping the index at 255 for each lookup. + * This needs to be exactly the same for all instances on all platforms, + * so it's easiest to just keep it as static explicit data. + * This also removes the need for any initialisation of this class. + * + * Note that making this an int[] instead of a char[] might make the + * code run faster on platforms with a high penalty for unaligned single + * byte addressing. Intel x86 is generally single-byte-friendly, but + * some other CPUs are faster with 4-aligned reads. + * However, a char[] is smaller, which avoids cache trashing, and that + * is probably the most important aspect on most architectures. + * This array is accessed a *lot* by the noise functions. + * A vector-valued noise over 3D accesses it 96 times, and a + * float-valued 4D noise 64 times. We want this to fit in the cache! + */ +unsigned char perm[512] = {151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, + 151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 +}; + +//--------------------------------------------------------------------- + +/* + * Helper functions to compute gradients-dot-residualvectors (1D to 4D) + * Note that these generate gradients of more than unit length. To make + * a close match with the value range of classic Perlin noise, the final + * noise values need to be rescaled to fit nicely within [-1,1]. + * (The simplex noise functions as such also have different scaling.) + * Note also that these noise functions are the most practical and useful + * signed version of Perlin noise. To return values according to the + * RenderMan specification from the SL noise() and pnoise() functions, + * the noise values need to be scaled and offset to [0,1], like this: + * float SLnoise = (noise(x,y,z) + 1.0) * 0.5; + */ + +float grad1( int hash, float x ) { + int h = hash & 15; + float grad = 1.0f + (h & 7); // Gradient value 1.0, 2.0, ..., 8.0 + if (h&8) grad = -grad; // Set a random sign for the gradient + return ( grad * x ); // Multiply the gradient with the distance +} + +float grad2( int hash, float x, float y ) { + int h = hash & 7; // Convert low 3 bits of hash code + float u = h<4 ? x : y; // into 8 simple gradient directions, + float v = h<4 ? y : x; // and compute the dot product with (x,y). + return ((h&1)? -u : u) + ((h&2)? -2.0f*v : 2.0f*v); +} + +float grad3( int hash, float x, float y , float z ) { + int h = hash & 15; // Convert low 4 bits of hash code into 12 simple + float u = h<8 ? x : y; // gradient directions, and compute dot product. + float v = h<4 ? y : h==12||h==14 ? x : z; // Fix repeats at h = 12 to 15 + return ((h&1)? -u : u) + ((h&2)? -v : v); +} + +float grad4( int hash, float x, float y, float z, float t ) { + int h = hash & 31; // Convert low 5 bits of hash code into 32 simple + float u = h<24 ? x : y; // gradient directions, and compute dot product. + float v = h<16 ? y : z; + float w = h<8 ? z : t; + return ((h&1)? -u : u) + ((h&2)? -v : v) + ((h&4)? -w : w); +} + + // A lookup table to traverse the simplex around a given point in 4D. + // Details can be found where this table is used, in the 4D noise method. + /* TODO: This should not be required, backport it from Bill's GLSL code! */ + static unsigned char simplex[64][4] = { + {0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0}, + {0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0}, + {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, + {1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0}, + {1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0}, + {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, + {2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0}, + {2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}; + +// 1D simplex noise +float snoise1(float x) { + + int i0 = FASTFLOOR(x); + int i1 = i0 + 1; + float x0 = x - i0; + float x1 = x0 - 1.0f; + + float n0, n1; + + float t0 = 1.0f - x0*x0; +// if(t0 < 0.0f) t0 = 0.0f; // this never happens for the 1D case + t0 *= t0; + n0 = t0 * t0 * grad1(perm[i0 & 0xff], x0); + + float t1 = 1.0f - x1*x1; +// if(t1 < 0.0f) t1 = 0.0f; // this never happens for the 1D case + t1 *= t1; + n1 = t1 * t1 * grad1(perm[i1 & 0xff], x1); + // The maximum value of this noise is 8*(3/4)^4 = 2.53125 + // A factor of 0.395 would scale to fit exactly within [-1,1], but + // we want to match PRMan's 1D noise, so we scale it down some more. + return 0.25f * (n0 + n1); + +} + +// 2D simplex noise +float snoise2(float x, float y) { + +#define F2 0.366025403 // F2 = 0.5*(sqrt(3.0)-1.0) +#define G2 0.211324865 // G2 = (3.0-Math.sqrt(3.0))/6.0 + + float n0, n1, n2; // Noise contributions from the three corners + + // Skew the input space to determine which simplex cell we're in + float s = (x+y)*F2; // Hairy factor for 2D + float xs = x + s; + float ys = y + s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + + float t = (float)(i+j)*G2; + float X0 = i-t; // Unskew the cell origin back to (x,y) space + float Y0 = j-t; + float x0 = x-X0; // The x,y distances from the cell origin + float y0 = y-Y0; + + // For the 2D case, the simplex shape is an equilateral triangle. + // Determine which simplex we are in. + int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords + if(x0>y0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1) + else {i1=0; j1=1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1) + + // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and + // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where + // c = (3-sqrt(3))/6 + + float x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords + float y1 = y0 - j1 + G2; + float x2 = x0 - 1.0f + 2.0f * G2; // Offsets for last corner in (x,y) unskewed coords + float y2 = y0 - 1.0f + 2.0f * G2; + + // Wrap the integer indices at 256, to avoid indexing perm[] out of bounds + int ii = i & 0xff; + int jj = j & 0xff; + + // Calculate the contribution from the three corners + float t0 = 0.5f - x0*x0-y0*y0; + if(t0 < 0.0f) n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad2(perm[ii+perm[jj]], x0, y0); + } + + float t1 = 0.5f - x1*x1-y1*y1; + if(t1 < 0.0f) n1 = 0.0f; + else { + t1 *= t1; + n1 = t1 * t1 * grad2(perm[ii+i1+perm[jj+j1]], x1, y1); + } + + float t2 = 0.5f - x2*x2-y2*y2; + if(t2 < 0.0f) n2 = 0.0f; + else { + t2 *= t2; + n2 = t2 * t2 * grad2(perm[ii+1+perm[jj+1]], x2, y2); + } + + // Add contributions from each corner to get the final noise value. + // The result is scaled to return values in the interval [-1,1]. + return 40.0f * (n0 + n1 + n2); // TODO: The scale factor is preliminary! + } + +// 3D simplex noise +float snoise3(float x, float y, float z) { + +// Simple skewing factors for the 3D case +#define F3 0.333333333 +#define G3 0.166666667 + + float n0, n1, n2, n3; // Noise contributions from the four corners + + // Skew the input space to determine which simplex cell we're in + float s = (x+y+z)*F3; // Very nice and simple skew factor for 3D + float xs = x+s; + float ys = y+s; + float zs = z+s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + int k = FASTFLOOR(zs); + + float t = (float)(i+j+k)*G3; + float X0 = i-t; // Unskew the cell origin back to (x,y,z) space + float Y0 = j-t; + float Z0 = k-t; + float x0 = x-X0; // The x,y,z distances from the cell origin + float y0 = y-Y0; + float z0 = z-Z0; + + // For the 3D case, the simplex shape is a slightly irregular tetrahedron. + // Determine which simplex we are in. + int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords + int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords + +/* This code would benefit from a backport from the GLSL version! */ + if(x0>=y0) { + if(y0>=z0) + { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order + else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order + else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order + } + else { // x0<y0 + if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } // Z Y X order + else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } // Y Z X order + else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } // Y X Z order + } + + // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), + // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and + // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where + // c = 1/6. + + float x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords + float y1 = y0 - j1 + G3; + float z1 = z0 - k1 + G3; + float x2 = x0 - i2 + 2.0f*G3; // Offsets for third corner in (x,y,z) coords + float y2 = y0 - j2 + 2.0f*G3; + float z2 = z0 - k2 + 2.0f*G3; + float x3 = x0 - 1.0f + 3.0f*G3; // Offsets for last corner in (x,y,z) coords + float y3 = y0 - 1.0f + 3.0f*G3; + float z3 = z0 - 1.0f + 3.0f*G3; + + // Wrap the integer indices at 256, to avoid indexing perm[] out of bounds + int ii = i & 0xff; + int jj = j & 0xff; + int kk = k & 0xff; + + // Calculate the contribution from the four corners + float t0 = 0.6f - x0*x0 - y0*y0 - z0*z0; + if(t0 < 0.0f) n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad3(perm[ii+perm[jj+perm[kk]]], x0, y0, z0); + } + + float t1 = 0.6f - x1*x1 - y1*y1 - z1*z1; + if(t1 < 0.0f) n1 = 0.0f; + else { + t1 *= t1; + n1 = t1 * t1 * grad3(perm[ii+i1+perm[jj+j1+perm[kk+k1]]], x1, y1, z1); + } + + float t2 = 0.6f - x2*x2 - y2*y2 - z2*z2; + if(t2 < 0.0f) n2 = 0.0f; + else { + t2 *= t2; + n2 = t2 * t2 * grad3(perm[ii+i2+perm[jj+j2+perm[kk+k2]]], x2, y2, z2); + } + + float t3 = 0.6f - x3*x3 - y3*y3 - z3*z3; + if(t3<0.0f) n3 = 0.0f; + else { + t3 *= t3; + n3 = t3 * t3 * grad3(perm[ii+1+perm[jj+1+perm[kk+1]]], x3, y3, z3); + } + + // Add contributions from each corner to get the final noise value. + // The result is scaled to stay just inside [-1,1] + return 32.0f * (n0 + n1 + n2 + n3); // TODO: The scale factor is preliminary! + } + + +// 4D simplex noise +float snoise4(float x, float y, float z, float w) { + + // The skewing and unskewing factors are hairy again for the 4D case +#define F4 0.309016994 // F4 = (Math.sqrt(5.0)-1.0)/4.0 +#define G4 0.138196601 // G4 = (5.0-Math.sqrt(5.0))/20.0 + + float n0, n1, n2, n3, n4; // Noise contributions from the five corners + + // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in + float s = (x + y + z + w) * F4; // Factor for 4D skewing + float xs = x + s; + float ys = y + s; + float zs = z + s; + float ws = w + s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + int k = FASTFLOOR(zs); + int l = FASTFLOOR(ws); + + float t = (i + j + k + l) * G4; // Factor for 4D unskewing + float X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space + float Y0 = j - t; + float Z0 = k - t; + float W0 = l - t; + + float x0 = x - X0; // The x,y,z,w distances from the cell origin + float y0 = y - Y0; + float z0 = z - Z0; + float w0 = w - W0; + + // For the 4D case, the simplex is a 4D shape I won't even try to describe. + // To find out which of the 24 possible simplices we're in, we need to + // determine the magnitude ordering of x0, y0, z0 and w0. + // The method below is a good way of finding the ordering of x,y,z,w and + // then find the correct traversal order for the simplex we’re in. + // First, six pair-wise comparisons are performed between each possible pair + // of the four coordinates, and the results are used to add up binary bits + // for an integer index. + int c1 = (x0 > y0) ? 32 : 0; + int c2 = (x0 > z0) ? 16 : 0; + int c3 = (y0 > z0) ? 8 : 0; + int c4 = (x0 > w0) ? 4 : 0; + int c5 = (y0 > w0) ? 2 : 0; + int c6 = (z0 > w0) ? 1 : 0; + int c = c1 + c2 + c3 + c4 + c5 + c6; + + int i1, j1, k1, l1; // The integer offsets for the second simplex corner + int i2, j2, k2, l2; // The integer offsets for the third simplex corner + int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner + + // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. + // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w + // impossible. Only the 24 indices which have non-zero entries make any sense. + // We use a thresholding to set the coordinates in turn from the largest magnitude. + // The number 3 in the "simplex" array is at the position of the largest coordinate. + i1 = simplex[c][0]>=3 ? 1 : 0; + j1 = simplex[c][1]>=3 ? 1 : 0; + k1 = simplex[c][2]>=3 ? 1 : 0; + l1 = simplex[c][3]>=3 ? 1 : 0; + // The number 2 in the "simplex" array is at the second largest coordinate. + i2 = simplex[c][0]>=2 ? 1 : 0; + j2 = simplex[c][1]>=2 ? 1 : 0; + k2 = simplex[c][2]>=2 ? 1 : 0; + l2 = simplex[c][3]>=2 ? 1 : 0; + // The number 1 in the "simplex" array is at the second smallest coordinate. + i3 = simplex[c][0]>=1 ? 1 : 0; + j3 = simplex[c][1]>=1 ? 1 : 0; + k3 = simplex[c][2]>=1 ? 1 : 0; + l3 = simplex[c][3]>=1 ? 1 : 0; + // The fifth corner has all coordinate offsets = 1, so no need to look that up. + + float x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords + float y1 = y0 - j1 + G4; + float z1 = z0 - k1 + G4; + float w1 = w0 - l1 + G4; + float x2 = x0 - i2 + 2.0f*G4; // Offsets for third corner in (x,y,z,w) coords + float y2 = y0 - j2 + 2.0f*G4; + float z2 = z0 - k2 + 2.0f*G4; + float w2 = w0 - l2 + 2.0f*G4; + float x3 = x0 - i3 + 3.0f*G4; // Offsets for fourth corner in (x,y,z,w) coords + float y3 = y0 - j3 + 3.0f*G4; + float z3 = z0 - k3 + 3.0f*G4; + float w3 = w0 - l3 + 3.0f*G4; + float x4 = x0 - 1.0f + 4.0f*G4; // Offsets for last corner in (x,y,z,w) coords + float y4 = y0 - 1.0f + 4.0f*G4; + float z4 = z0 - 1.0f + 4.0f*G4; + float w4 = w0 - 1.0f + 4.0f*G4; + + // Wrap the integer indices at 256, to avoid indexing perm[] out of bounds + int ii = i & 0xff; + int jj = j & 0xff; + int kk = k & 0xff; + int ll = l & 0xff; + + // Calculate the contribution from the five corners + float t0 = 0.6f - x0*x0 - y0*y0 - z0*z0 - w0*w0; + if(t0 < 0.0f) n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad4(perm[ii+perm[jj+perm[kk+perm[ll]]]], x0, y0, z0, w0); + } + + float t1 = 0.6f - x1*x1 - y1*y1 - z1*z1 - w1*w1; + if(t1 < 0.0f) n1 = 0.0f; + else { + t1 *= t1; + n1 = t1 * t1 * grad4(perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]], x1, y1, z1, w1); + } + + float t2 = 0.6f - x2*x2 - y2*y2 - z2*z2 - w2*w2; + if(t2 < 0.0f) n2 = 0.0f; + else { + t2 *= t2; + n2 = t2 * t2 * grad4(perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]], x2, y2, z2, w2); + } + + float t3 = 0.6f - x3*x3 - y3*y3 - z3*z3 - w3*w3; + if(t3 < 0.0f) n3 = 0.0f; + else { + t3 *= t3; + n3 = t3 * t3 * grad4(perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]], x3, y3, z3, w3); + } + + float t4 = 0.6f - x4*x4 - y4*y4 - z4*z4 - w4*w4; + if(t4 < 0.0f) n4 = 0.0f; + else { + t4 *= t4; + n4 = t4 * t4 * grad4(perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]], x4, y4, z4, w4); + } + + // Sum up and scale the result to cover the range [-1,1] + return 27.0f * (n0 + n1 + n2 + n3 + n4); // TODO: The scale factor is preliminary! + } +//--------------------------------------------------------------------- diff --git a/Projects/Asteroids/src/simplexnoise1234.h b/Projects/Asteroids/src/simplexnoise1234.h new file mode 100644 index 0000000..18c42f9 --- /dev/null +++ b/Projects/Asteroids/src/simplexnoise1234.h @@ -0,0 +1,70 @@ +/* SimplexNoise1234, Simplex noise with true analytic + * derivative in 1D to 4D. + * + * Author: Stefan Gustavson, 2003-2005 + * Contact: stegu@itn.liu.se + */ + +/* +This code was GPL licensed until February 2011. +As the original author of this code, I hereby +release it irrevocably into the public domain. +Please feel free to use it for whatever you want. +Credit is appreciated where appropriate, and I also +appreciate being told where this code finds any use, +but you may do as you like. Alternatively, if you want +to have a familiar OSI-approved license, you may use +This code under the terms of the MIT license: + +Copyright (C) 2003-2005 by Stefan Gustavson. All rights reserved. +This code is licensed to you under the terms of the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/** \file + \brief Header for "simplexnoise1234.c" for producing Perlin simplex noise. + \author Stefan Gustavson (stegu@itn.liu.se) +*/ + +/* + * This is a clean, fast, modern and free Perlin Simplex noise function. + * It is a stand-alone compilation unit with no external dependencies, + * highly reusable without source code modifications. + * + * + * Note: + * Replacing the "float" type with "double" can actually make this run faster + * on some platforms. Having both versions could be useful. + */ + +/** 1D, 2D, 3D and 4D float Perlin simplex noise + */ +#ifdef __cplusplus +extern "C" { +#endif + + float snoise1( float x ); + float snoise2( float x, float y ); + float snoise3( float x, float y, float z ); + float snoise4( float x, float y, float z, float w ); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Projects/Asteroids/src/simulation.cpp b/Projects/Asteroids/src/simulation.cpp new file mode 100644 index 0000000..74e9019 --- /dev/null +++ b/Projects/Asteroids/src/simulation.cpp @@ -0,0 +1,250 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#include "simulation.h" +#include "settings.h" +#include "texture.h" +#include "util.h" + +#include <random> +#include <limits> +#include <algorithm> +#include <iostream> +#include <ppl.h> + +using namespace DirectX; + +static int const COLOR_SCHEMES[] = { + 156, 139, 113, 55, 49, 40, + 156, 139, 113, 58, 38, 14, + 156, 139, 113, 98, 101, 104, + 156, 139, 113, 205, 197, 178, + 153, 146, 136, 88, 88, 88, + 189, 181, 164, 148, 108, 102, +}; + +static int const NUM_COLOR_SCHEMES = (int) (sizeof(COLOR_SCHEMES) / (6 * sizeof(int))); + +static XMVECTOR RandomPointOnSphere(std::mt19937& rng) +{ + std::normal_distribution<float> dist; + + XMVECTOR r; + for (;;) { + r = XMVectorSet(dist(rng), dist(rng), dist(rng), 0.0f); + auto d2 = XMVectorGetX(XMVector3LengthSq(r)); + if (d2 > std::numeric_limits<float>::min()) { + return XMVector3Normalize(r); + } + } + // Unreachable +} + +// From http://guihaire.com/code/?p=1135 +static inline float VeryApproxLog2f(float x) +{ + union { float f; uint32_t i; } ux; + ux.f = x; + return (float)ux.i * 1.1920928955078125e-7f - 126.94269504f; +} + + +AsteroidsSimulation::AsteroidsSimulation(unsigned int rngSeed, unsigned int asteroidCount, + unsigned int meshInstanceCount, unsigned int subdivCount, + unsigned int textureCount) + : mAsteroidStatic(asteroidCount) + , mAsteroidDynamic(asteroidCount) + , mIndexOffsets(subdivCount + 2) // Mesh subdivs are inclusive on both ends and need forward differencing for count + , mSubdivCount(subdivCount) +{ + std::mt19937 rng(rngSeed); + + // Create meshes + std::cout + << "Creating " << meshInstanceCount << " meshes, each with " + << subdivCount << " subdivision levels..." << std::endl; + + CreateAsteroidsFromGeospheres(&mMeshes, mSubdivCount, meshInstanceCount, + rng(), mIndexOffsets.data(), &mVertexCountPerMesh); + + CreateTextures(textureCount, rng()); + + // Constants + std::normal_distribution<float> orbitRadiusDist(SIM_ORBIT_RADIUS, 0.6f * SIM_DISC_RADIUS); + std::normal_distribution<float> heightDist(0.0f, 0.4f); + std::uniform_real_distribution<float> angleDist(-XM_PI, XM_PI); + std::uniform_real_distribution<float> radialVelocityDist(5.0f, 15.0f); + std::uniform_real_distribution<float> spinVelocityDist(-2.0f, 2.0f); + std::normal_distribution<float> scaleDist(1.3f, 0.7f); + std::normal_distribution<float> colorSchemeDist(0, NUM_COLOR_SCHEMES - 1); + std::uniform_int_distribution<unsigned int> textureIndexDist(0, textureCount-1); + + auto instancesPerMesh = std::max(1U, asteroidCount / meshInstanceCount); + + // Approximate SRGB->Linear for colors + float linearColorSchemes[NUM_COLOR_SCHEMES * 6]; + for (int i = 0; i < ARRAYSIZE(linearColorSchemes); ++i) { + linearColorSchemes[i] = std::powf((float)COLOR_SCHEMES[i] / 255.0f, 2.2f); + } + + // Create a torus of asteroids that spin around the ring + for (unsigned int i = 0; i < asteroidCount; ++i) { + auto scale = scaleDist(rng); +#if SIM_USE_GAMMA_DIST_SCALE + scale = scale * 0.3f; +#endif + scale = std::max(scale, SIM_MIN_SCALE); + auto scaleMatrix = XMMatrixScaling(scale, scale, scale); + + auto orbitRadius = orbitRadiusDist(rng); + auto discPosY = float(SIM_DISC_RADIUS) * heightDist(rng); + + auto disc = XMMatrixTranslation(orbitRadius, discPosY, 0.0f); + + auto positionAngle = angleDist(rng); + auto orbit = XMMatrixRotationY(positionAngle); + + auto meshInstance = (unsigned int)(i / instancesPerMesh); // Vcache friendly ordering + + // Static data + mAsteroidStatic[i].spinVelocity = spinVelocityDist(rng) / scale; // Smaller asteroids spin faster + mAsteroidStatic[i].orbitVelocity = radialVelocityDist(rng) / (scale * orbitRadius); // Smaller asteroids go faster, and use arc length + mAsteroidStatic[i].vertexStart = mVertexCountPerMesh * meshInstance; + mAsteroidStatic[i].spinAxis = XMVector3Normalize(RandomPointOnSphere(rng)); + mAsteroidStatic[i].scale = scale; + mAsteroidStatic[i].textureIndex = textureIndexDist(rng); + + auto colorScheme = ((int)abs(colorSchemeDist(rng))) % NUM_COLOR_SCHEMES; + auto c = linearColorSchemes + 6 * colorScheme; + mAsteroidStatic[i].surfaceColor = XMFLOAT3(c[0], c[1], c[2]); + mAsteroidStatic[i].deepColor = XMFLOAT3(c[3], c[4], c[5]); + + // Initialize dynamic data + mAsteroidDynamic[i].world = scaleMatrix * disc * orbit; + + assert(mAsteroidStatic[i].scale > 0.0f); + assert(mAsteroidStatic[i].orbitVelocity > 0.0f); + } +} + + +void AsteroidsSimulation::Update(float frameTime, DirectX::XMVECTOR cameraEye, const Settings& settings, + size_t startIndex, size_t count) +{ + bool animate = settings.animate; + + // TODO: This constant should really depend on resolution and/or be configurable... + static const float minSubdivSizeLog2 = std::log2f(0.0019f); + + size_t last = count ? startIndex + count : mAsteroidDynamic.size(); + for (size_t i = startIndex; i < last; ++i) { + const AsteroidStatic& staticData = mAsteroidStatic[i]; + AsteroidDynamic& dynamicData = mAsteroidDynamic[i]; + + if (animate) { + auto orbit = XMMatrixRotationY(staticData.orbitVelocity * frameTime); + auto spin = XMMatrixRotationNormal(staticData.spinAxis, staticData.spinVelocity * frameTime); + dynamicData.world = spin * dynamicData.world * orbit; + } + + // Pick LOD based on approx screen area - can be very approximate + auto position = dynamicData.world.r[3]; + auto distanceToEyeRcp = XMVectorGetX(XMVector3ReciprocalLengthEst(XMVectorSubtract(cameraEye, position))); + // Add one subdiv for each factor of 2 past min + auto relativeScreenSizeLog2 = VeryApproxLog2f(staticData.scale * distanceToEyeRcp); + float subdivFloat = std::max(0.0f, relativeScreenSizeLog2 - minSubdivSizeLog2); + auto subdiv = std::min(mSubdivCount, (unsigned int)subdivFloat); + + // TODO: Ignore/cull/force lowest subdiv if offscreen? + + dynamicData.indexStart = mIndexOffsets[subdiv]; + dynamicData.indexCount = mIndexOffsets[subdiv+1] - dynamicData.indexStart; + } +} + + +void AsteroidsSimulation::CreateTextures(unsigned int textureCount, unsigned int rngSeed) +{ + mTextureDim = TEXTURE_DIM; + mTextureCount = textureCount; + mTextureArraySize = 3; + { + DWORD msbIndex = 0; + auto result = _BitScanReverse(&msbIndex, mTextureDim); + assert(result); // Should only fail if mTextureDim = 0 + mTextureMipLevels = msbIndex + 1; + } + + assert((mTextureDim & (mTextureDim-1)) == 0); // Must be pow2 currently; we don't handle wacky mip chains + + std::cout + << "Creating " << textureCount << " " + << mTextureDim << "x" << mTextureDim << " textures..." << std::endl; + + // Allocate space + UINT texelSizeInBytes = 4; // RGBA8 + UINT extraSpaceForMips = 2; + UINT totalTextureSizeInBytes = texelSizeInBytes * mTextureDim * mTextureDim * mTextureArraySize * extraSpaceForMips; + totalTextureSizeInBytes = Align(totalTextureSizeInBytes, 64U); // Avoid false sharing + + mTextureDataBuffer.resize(totalTextureSizeInBytes * textureCount); + mTextureSubresources.resize(mTextureArraySize * mTextureMipLevels * textureCount); + + // Parallel over textures + std::vector<unsigned int> rngSeeds(textureCount); + { + std::mt19937 seeds; + for (auto &i : rngSeeds) i = seeds(); + } + + concurrency::parallel_for(UINT(0), textureCount, [&](UINT t) { + std::mt19937 rng(rngSeeds[t]); + auto randomNoise = std::uniform_real_distribution<float>(0.0f, 10000.0f); + auto randomNoiseScale = std::uniform_real_distribution<float>(100, 150); + auto randomPersistence = std::normal_distribution<float>(0.9f, 0.2f); + + BYTE* data = mTextureDataBuffer.data() + t * totalTextureSizeInBytes; + for (UINT a = 0; a < mTextureArraySize; ++a) { + for (UINT m = 0; m < mTextureMipLevels; ++m) { + auto width = mTextureDim >> m; + auto height = mTextureDim >> m; + + D3D11_SUBRESOURCE_DATA initialData = {}; + initialData.pSysMem = data; + initialData.SysMemPitch = width * texelSizeInBytes; + mTextureSubresources[SubresourceIndex(t, a, m)] = initialData; + + data += initialData.SysMemPitch * height; + } + } + + // Use same parameters for each of the tri-planar projection planes/cube map faces/etc. + float noiseScale = randomNoiseScale(rng) / float(mTextureDim); + float persistence = randomPersistence(rng); + float strength = 1.5f; + + for (UINT a = 0; a < mTextureArraySize; ++a) { + float redScale = 255.0f; + float greenScale = 255.0f; + float blueScale = 255.0f; + + // DEBUG colors +#if 0 + redScale = t & 1 ? 255.0f : 0.0f; + greenScale = t & 2 ? 255.0f : 0.0f; + blueScale = t & 4 ? 255.0f : 0.0f; +#endif + + FillNoise2D_RGBA8(&mTextureSubresources[SubresourceIndex(t, a)], mTextureDim, mTextureDim, mTextureMipLevels, + randomNoise(rng), persistence, noiseScale, strength, + redScale, greenScale, blueScale); + } + }); // parallel_for +} diff --git a/Projects/Asteroids/src/simulation.h b/Projects/Asteroids/src/simulation.h new file mode 100644 index 0000000..c14270d --- /dev/null +++ b/Projects/Asteroids/src/simulation.h @@ -0,0 +1,90 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include <d3d11.h> // For D3D11_SUBRESOURCE_DATA +#include <DirectXMath.h> +#include <vector> +#include <algorithm> +#include <random> + +#include "mesh.h" +#include "settings.h" + +// We may want to ISPC-ify this down the road and just let it own the data structure in AoSoA format or similar +// For now we'll just do the dumb thing and see if it's fast enough +struct AsteroidDynamic +{ + DirectX::XMMATRIX world; + // These depend on chosen subdiv level, hence are not constant + unsigned int indexStart; + unsigned int indexCount; +}; + +struct AsteroidStatic +{ + DirectX::XMFLOAT3 surfaceColor; + DirectX::XMFLOAT3 deepColor; + DirectX::XMVECTOR spinAxis; + float scale; + float spinVelocity; + float orbitVelocity; + unsigned int vertexStart; + unsigned int textureIndex; +}; + +class AsteroidsSimulation +{ +private: + // NOTE: Memory could be optimized further for efficient cache traversal, etc. + std::vector<AsteroidStatic> mAsteroidStatic; + std::vector<AsteroidDynamic> mAsteroidDynamic; + + Mesh mMeshes; + std::vector<unsigned int> mIndexOffsets; + unsigned int mSubdivCount; + unsigned int mVertexCountPerMesh; + + unsigned int mTextureDim; + unsigned int mTextureCount; + unsigned int mTextureArraySize; + unsigned int mTextureMipLevels; + std::vector<BYTE> mTextureDataBuffer; + std::vector<D3D11_SUBRESOURCE_DATA> mTextureSubresources; + + unsigned int SubresourceIndex(unsigned int texture, unsigned int arrayElement = 0, unsigned int mip = 0) + { + return mip + mTextureMipLevels * (arrayElement + mTextureArraySize * texture); + } + + void CreateTextures(unsigned int textureCount, unsigned int rngSeed); + +public: + AsteroidsSimulation(unsigned int rngSeed, unsigned int asteroidCount, + unsigned int meshInstanceCount, unsigned int subdivCount, + unsigned int textureCount); + + const Mesh* Meshes() { return &mMeshes; } + const D3D11_SUBRESOURCE_DATA* TextureData(unsigned int textureIndex) + { + return mTextureSubresources.data() + SubresourceIndex(textureIndex); + } + + unsigned int GetTextureMipLevels()const{return mTextureMipLevels;} + + const AsteroidStatic* StaticData() const { return mAsteroidStatic.data(); } + const AsteroidDynamic* DynamicData() const { return mAsteroidDynamic.data(); } + + // Can optionall provide a range of asteroids to update; count = 0 => to the end + // This is useful for multithreading + void Update(float frameTime, DirectX::XMVECTOR cameraEye, const Settings& settings, + size_t startIndex = 0, size_t count = 0); +}; diff --git a/Projects/Asteroids/src/skybox_ps.hlsl b/Projects/Asteroids/src/skybox_ps.hlsl new file mode 100644 index 0000000..4107073 --- /dev/null +++ b/Projects/Asteroids/src/skybox_ps.hlsl @@ -0,0 +1,16 @@ +struct Skybox_VSOut +{ + float3 coords : UVFACE; +}; + +TextureCube Skybox;// : register(t0); +SamplerState Skybox_sampler;// : register(s0); + +void skybox_ps(in float4 position : SV_Position, + in Skybox_VSOut vsoutput, + out float4 color : SV_Target) +{ + //return input.coords.xyzx; + float4 tex = Skybox.Sample(Skybox_sampler, vsoutput.coords); + color = float4(tex.xyz, 1.0f); +} diff --git a/Projects/Asteroids/src/skybox_vs.hlsl b/Projects/Asteroids/src/skybox_vs.hlsl new file mode 100644 index 0000000..acefcd5 --- /dev/null +++ b/Projects/Asteroids/src/skybox_vs.hlsl @@ -0,0 +1,20 @@ +cbuffer SkyboxConstantBuffer// : register(b0) +{ + float4x4 mViewProjection; +}; + +struct Skybox_VSOut +{ + float3 coords : UVFACE; +}; + +void skybox_vs( in float3 in_position : ATTRIB0, + in float3 uvFace : ATTRIB1, + out float4 position : SV_Position, + out Skybox_VSOut vsoutput) +{ + // NOTE: Don't translate skybox and make sure depth == 1 (no clipping) + position = mul(mViewProjection, float4(in_position, 0.0f)).xyww; + position.z = 0.0f; // 1-z + vsoutput.coords = in_position.xyz; +} diff --git a/Projects/Asteroids/src/sprite.h b/Projects/Asteroids/src/sprite.h new file mode 100644 index 0000000..4a8311d --- /dev/null +++ b/Projects/Asteroids/src/sprite.h @@ -0,0 +1,36 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +struct SpriteVertex { + float x; + float y; + float u; + float v; +}; + +inline SpriteVertex* DrawSprite(float x, float y, float width, float height, float viewportWidth, float viewportHeight, SpriteVertex* outVertex) +{ + outVertex[0] = {x , y , 0.0f, 0.0f}; + outVertex[1] = {x + width, y , 1.0f, 0.0f}; + outVertex[2] = {x + width, y + height, 1.0f, 1.0f}; + outVertex[3] = outVertex[0]; + outVertex[4] = outVertex[2]; + outVertex[5] = {x , y + height, 0.0f, 1.0f}; + + for (int i = 0; i < 6; ++i) { + outVertex[i].x = (outVertex[i].x / viewportWidth * 2.0f - 1.0f); + outVertex[i].y = -(outVertex[i].y / viewportHeight * 2.0f - 1.0f); + } + + outVertex += 6; + return outVertex; +} diff --git a/Projects/Asteroids/src/sprite_ps.hlsl b/Projects/Asteroids/src/sprite_ps.hlsl new file mode 100644 index 0000000..fa47f83 --- /dev/null +++ b/Projects/Asteroids/src/sprite_ps.hlsl @@ -0,0 +1,11 @@ +#include "sprite_vs.hlsl" + +Texture2D<float4> Tex;// : register(t0); +SamplerState Tex_sampler;// : register(s0); + +void sprite_ps(in float4 position : SV_Position, + in Font_VSOut vs_out, + out float4 color : SV_Target ) +{ + color = Tex.Sample(Tex_sampler, vs_out.uv); +} diff --git a/Projects/Asteroids/src/sprite_vs.hlsl b/Projects/Asteroids/src/sprite_vs.hlsl new file mode 100644 index 0000000..6fea9e5 --- /dev/null +++ b/Projects/Asteroids/src/sprite_vs.hlsl @@ -0,0 +1,14 @@ + +struct Font_VSOut +{ + float2 uv : UV; +}; + +void sprite_vs( float2 in_position : ATTRIB0, + float2 in_uv : ATTRIB1, + out float4 position : SV_Position, + out Font_VSOut vs_out) +{ + position = float4(in_position, 0, 1); + vs_out.uv = in_uv; +} diff --git a/Projects/Asteroids/src/stb_font_consolas_bold_50_usascii.inl b/Projects/Asteroids/src/stb_font_consolas_bold_50_usascii.inl new file mode 100644 index 0000000..066ba29 --- /dev/null +++ b/Projects/Asteroids/src/stb_font_consolas_bold_50_usascii.inl @@ -0,0 +1,1195 @@ +// Font generated by stb_font_inl_generator.c (4/1 bpp) +// +// Following instructions show how to use the only included font, whatever it is, in +// a generic way so you can replace it with any other font by changing the include. +// To use multiple fonts, replace STB_SOMEFONT_* below with STB_FONT_consolas_bold_50_usascii_*, +// and separately install each font. Note that the CREATE function call has a +// totally different name; it's just 'stb_font_consolas_bold_50_usascii'. +// +/* // Example usage: + +static stb_fontchar fontdata[STB_SOMEFONT_NUM_CHARS]; + +static void init(void) +{ + // optionally replace both STB_SOMEFONT_BITMAP_HEIGHT with STB_SOMEFONT_BITMAP_HEIGHT_POW2 + static unsigned char fontpixels[STB_SOMEFONT_BITMAP_HEIGHT][STB_SOMEFONT_BITMAP_WIDTH]; + STB_SOMEFONT_CREATE(fontdata, fontpixels, STB_SOMEFONT_BITMAP_HEIGHT); + ... create texture ... + // for best results rendering 1:1 pixels texels, use nearest-neighbor sampling + // if allowed to scale up, use bilerp +} + +// This function positions characters on integer coordinates, and assumes 1:1 texels to pixels +// Appropriate if nearest-neighbor sampling is used +static void draw_string_integer(int x, int y, char *str) // draw with top-left point x,y +{ + ... use texture ... + ... turn on alpha blending and gamma-correct alpha blending ... + glBegin(GL_QUADS); + while (*str) { + int char_codepoint = *str++; + stb_fontchar *cd = &fontdata[char_codepoint - STB_SOMEFONT_FIRST_CHAR]; + glTexCoord2f(cd->s0, cd->t0); glVertex2i(x + cd->x0, y + cd->y0); + glTexCoord2f(cd->s1, cd->t0); glVertex2i(x + cd->x1, y + cd->y0); + glTexCoord2f(cd->s1, cd->t1); glVertex2i(x + cd->x1, y + cd->y1); + glTexCoord2f(cd->s0, cd->t1); glVertex2i(x + cd->x0, y + cd->y1); + // if bilerping, in D3D9 you'll need a half-pixel offset here for 1:1 to behave correct + x += cd->advance_int; + } + glEnd(); +} + +// This function positions characters on float coordinates, and doesn't require 1:1 texels to pixels +// Appropriate if bilinear filtering is used +static void draw_string_float(float x, float y, char *str) // draw with top-left point x,y +{ + ... use texture ... + ... turn on alpha blending and gamma-correct alpha blending ... + glBegin(GL_QUADS); + while (*str) { + int char_codepoint = *str++; + stb_fontchar *cd = &fontdata[char_codepoint - STB_SOMEFONT_FIRST_CHAR]; + glTexCoord2f(cd->s0f, cd->t0f); glVertex2f(x + cd->x0f, y + cd->y0f); + glTexCoord2f(cd->s1f, cd->t0f); glVertex2f(x + cd->x1f, y + cd->y0f); + glTexCoord2f(cd->s1f, cd->t1f); glVertex2f(x + cd->x1f, y + cd->y1f); + glTexCoord2f(cd->s0f, cd->t1f); glVertex2f(x + cd->x0f, y + cd->y1f); + // if bilerping, in D3D9 you'll need a half-pixel offset here for 1:1 to behave correct + x += cd->advance; + } + glEnd(); +} +*/ + +#ifndef STB_FONTCHAR__TYPEDEF +#define STB_FONTCHAR__TYPEDEF +typedef struct +{ + // coordinates if using integer positioning + float s0,t0,s1,t1; + signed short x0,y0,x1,y1; + int advance_int; + // coordinates if using floating positioning + float s0f,t0f,s1f,t1f; + float x0f,y0f,x1f,y1f; + float advance; +} stb_fontchar; +#endif + +#define STB_FONT_consolas_bold_50_usascii_BITMAP_WIDTH 256 +#define STB_FONT_consolas_bold_50_usascii_BITMAP_HEIGHT 317 +#define STB_FONT_consolas_bold_50_usascii_BITMAP_HEIGHT_POW2 512 + +#define STB_FONT_consolas_bold_50_usascii_FIRST_CHAR 32 +#define STB_FONT_consolas_bold_50_usascii_NUM_CHARS 95 + +#define STB_FONT_consolas_bold_50_usascii_LINE_SPACING 33 + +static unsigned int stb__consolas_bold_50_usascii_pixels[]={ + 0x207fffff,0x08000000,0x00000000,0x0aa88000,0x2ea60000,0x359950cc, + 0x66540003,0xcccccccc,0x999950cc,0x99999999,0x3bb20001,0x8800002e, + 0x000000aa,0x2aaaa200,0x2aaaa61a,0x3fffe0aa,0x000ed83f,0x00fe6000, + 0xdfb95100,0x00000379,0x027fffd4,0xffffd300,0x3fff61ff,0xc8004fff, + 0xffffffff,0xff91ffff,0xffffffff,0x3a0003ff,0x80002fff,0xfffffdc8, + 0x00001cdf,0x3ffff200,0x3ffff20f,0x3fffe0ff,0x077fec3f,0x7fcc0000, + 0xff70003f,0xffffffff,0xf9800003,0x003fffff,0x7ffffe44,0xfffb0fff, + 0x005fffff,0x7fffffe4,0x91ffffff,0xffffffff,0x0003ffff,0x0007fffe, + 0xffffff50,0x09ffffff,0xff100000,0xffc8bfff,0x3fe0ffff,0x3ff63fff, + 0x00000eff,0x0fffffe6,0xffffd880,0xffffffff,0x3f200001,0x006fffff, + 0x7ffffff4,0xfffb0fff,0x03ffffff,0x3fffff20,0x1fffffff,0xfffffff9, + 0x003fffff,0x01ffff30,0x7fffec00,0xffffffff,0x00000dff,0x3ffffee0, + 0x7ffffe42,0x3ffffe0f,0xffffff13,0xf500001d,0x009fffff,0x3fffffe6, + 0xffffffff,0xfb00002f,0x00ffffff,0x7fffffd4,0xffb0ffff,0xdfffffff, + 0x3ffff200,0xffffffff,0xffffff91,0x03ffffff,0x0ffff500,0x3fffa200, + 0xffffffff,0x01efffff,0xfffd0000,0xffff90df,0x7fffc1ff,0x3fffe63f, + 0x20000eff,0x4ffffff9,0xfffff100,0xffb757df,0x0003ffff,0xffffff70, + 0x7fff400d,0x4c00aeff,0x3ffffffc,0x7ffffc80,0xfff98000,0xba8801ff, + 0xacffffec,0xfffb0009,0xffffffff,0xbfffffff,0xff500000,0xff707fff, + 0xfff8ffff,0x7ffcc3ff,0x10005fff,0x0bfffffd,0x7fffff40,0xffffd102, + 0xff10000b,0x2005ffff,0x05fffffa,0xfffff980,0xffffc806,0xff980007, + 0x3ea01fff,0xffffffff,0x405fffff,0xeffffff9,0xffca889b,0x001fffff, + 0x7fffec00,0xffffb80f,0x7ffffc7f,0xfffff983,0xffd8003f,0x32005fff, + 0x401fffff,0x00fffff8,0xfffe9800,0x3ffee003,0xf90000ff,0xf900ffff, + 0x0000ffff,0x03fffff3,0xffffffd3,0xffffffff,0xfffe80bf,0x3ee00fff, + 0x005fffff,0x3fffe200,0xffff704f,0xfffff8ff,0xfffff503,0x7fd4001f, + 0x2a006fff,0x001fffff,0x007ffff5,0x4000c400,0x005ffffc,0x3ffffe60, + 0x7fffe400,0xff980007,0x7fd41fff,0xffffffff,0x5fffffff,0x3ffffea0, + 0xfffb801f,0x00001fff,0x03fffff9,0x1fffffea,0x407fffff,0x05fffffd, + 0xffffff10,0x7fff4003,0x7ff4003f,0x0000006f,0x4ffffd80,0x3ffe2000, + 0x7fe401ff,0x980007ff,0x221fffff,0xffffffff,0xffffffff,0x3ffa05ff, + 0x3e004fff,0x004fffff,0xbfffff00,0x7ffffd40,0x1fffffc6,0xffffff10, + 0xffffb005,0x7fcc009f,0xfc8006ff,0x00001fff,0x7fff4000,0x7fc0003f, + 0x7e402fff,0x80007fff,0x21fffff9,0xdffffffe,0xa9ffffaa,0xff305fdc, + 0x4003ffff,0x06fffffd,0xffffb800,0x3ffea02f,0x7fffc6ff,0x7ffdc03f, + 0x3e600fff,0x000effff,0x00bffff6,0x13fffea0,0xddddddd3,0xdddddddd, + 0x3fa007dd,0x40003fff,0x402fffff,0x007ffffc,0xfffff980,0xffffff31, + 0x837ffd47,0xfffff701,0xfffa800d,0xe80007ff,0x5406ffff,0x7c6fffff, + 0xe803ffff,0x202fffff,0x02fffffc,0x1bfffe20,0xfff13008,0xffff989f, + 0xffffffff,0x004fffff,0x007ffffd,0x2fffff80,0x3ffffe40,0x7ffcc000, + 0xffff71ff,0x5fffb8ff,0x7fffe400,0x7fc4004f,0x0000ffff,0x0fffffe6, + 0xdfffff30,0x03fffff8,0x6fffff98,0xdfffff10,0xffffc800,0x77ffed43, + 0xfffd6fec,0xfffff98b,0xffffffff,0xd004ffff,0x0007ffff,0x02fffff8, + 0x03ffffe4,0x7fffcc00,0xfffff91f,0x04fffd8b,0x7fffff40,0xffff8003, + 0x360001ff,0x400fffff,0x45fffff9,0x003fffff,0x01fffffd,0x07fffff7, + 0x0ffffe80,0x3ffffff2,0xfffb6fff,0xfffff98d,0xffffffff,0xd004ffff, + 0x0007ffff,0x02fffff8,0x03ffffe4,0x7fffcc00,0xfffff91f,0x1ffff41f, + 0x3ffffa00,0xfff8003f,0x10002fff,0x009fffff,0x8bfffff3,0x003fffff, + 0x07fffff7,0x01fffffd,0x2ffffc40,0xfffffff9,0x3ff6bfff,0x77774c7f, + 0xeeeeeeee,0x004fffff,0x005fffff,0x3ffffe80,0x3ffffe40,0x7ffcc000, + 0xffff71ff,0x3ffe19ff,0x7ffc002f,0xe8002fff,0x003fffff,0x3fffff90, + 0xfffff100,0x3fffff8b,0xfffff300,0xfffff98d,0x7ffd4005,0xfffff12f, + 0x29ffffff,0x0007fffc,0x27ffffdc,0x7ffffc40,0x7fec0002,0x7fe404ff, + 0x980007ff,0xf31fffff,0x7fffffff,0x8003ffff,0x01ffffff,0xfffffe80, + 0xffff0003,0x3fe200df,0x7ffc4fff,0x3fa003ff,0x3ee1ffff,0x4002ffff, + 0xfb1ffffc,0xffb7ffff,0x3fff27ff,0x3ee0000f,0xa804ffff,0x001fffff, + 0x7ffffec0,0x3ffff200,0xff980007,0x3ffe1fff,0xffffffff,0x7fc4007f, + 0x8001ffff,0x03fffffd,0xfffffa80,0xffff1002,0xfffff89f,0x3ffee003, + 0x3fff22ff,0x7f4000ff,0x3fffe7ff,0x7ffff90f,0x007fffee,0xfffffb80, + 0x7fff4404,0xfa80006f,0x3204ffff,0x0007ffff,0x1fffff98,0x3fffffe6, + 0x1cffffff,0x3ffffe00,0xffe8002f,0xe8002fff,0x2007ffff,0x44fffff8, + 0x003fffff,0x8fffffea,0x007ffffd,0x9b7fffc4,0x3f25ffff,0xfff72fff, + 0x7dc0003f,0x2a24ffff,0xfffffcba,0xfd00003f,0x559dffff,0x1fffff25, + 0x3ffe6000,0x7ffdc1ff,0xffffffff,0xfe802eff,0x8003ffff,0x01ffffff, + 0x7ffffcc0,0x7fffc003,0x7ffffc4f,0x3ffe6003,0x3fffa4ff,0x7fcc006f, + 0xffff94ff,0x8ffffec5,0x000ffffb,0x3ffffee0,0x3ffffe64,0x0004ffff, + 0x3ffffa60,0xff95ffff,0x30000fff,0x503fffff,0xfffffffd,0x3dffffff, + 0x7fffff40,0xffff8003,0x7ec000ff,0x4000ffff,0x7c3fffff,0x2003ffff, + 0x25fffff8,0x005fffff,0xd97fffd4,0x3fa1ffff,0xfff90fff,0xffb8000f, + 0x3fe64fff,0x02dfffff,0xfeb88000,0xf95fffff,0x0000ffff,0x03fffff3, + 0x7fffffe4,0xffffffff,0xfffffb03,0xfff88009,0x7c4007ff,0x8005ffff, + 0x7c3fffff,0x4003ffff,0xf15fffff,0x8009ffff,0xfd2ffffa,0x7ff41fff, + 0xffff90ff,0xfffb8000,0x3ffe64ff,0x002cffff,0xffeb8800,0xff95ffff, + 0x30000fff,0x803fffff,0xfffffea8,0x2fffffff,0x6fffffc8,0x7fffd400, + 0x7fdc007f,0xf8001fff,0x7fc3ffff,0x7c003fff,0xff36ffff,0xb8007fff, + 0xfff1ffff,0x7ffff8ff,0x001ffff2,0x9fffff70,0x7fffffcc,0x00004fff, + 0x3fffffe6,0xfff95fff,0xf30000ff,0x2003ffff,0xfffffff8,0x41ffffff, + 0x0ffffffb,0x3ffff200,0x7ffc005f,0xfd0006ff,0xfff85fff,0x7f4003ff, + 0xfff36fff,0xfb8009ff,0xffff1fff,0x26ffff8d,0x0006fffd,0x27ffffdc, + 0xfffb7551,0x00005fff,0x3bfffffe,0xfff92aac,0xf30000ff,0x2003ffff, + 0xffcffffa,0x44ffffff,0x3ffffff8,0x3ffffe00,0x3fea001f,0xd0002fff, + 0xff85ffff,0x7c003fff,0xff35ffff,0xc800bfff,0xff88ffff,0x3ffe26ff, + 0x1bfffa6f,0xffff7000,0xfff9809f,0xa80006ff,0x204fffff,0x007ffffc, + 0xfffff980,0xdfff7001,0x3fffff62,0xffffd86f,0xffb800ef,0x74006fff, + 0x0007ffff,0x7ffffc00,0x3ffe2003,0xffff14ff,0xffd800df,0xffff88ff, + 0x93fffe66,0x0004ffff,0x27ffffdc,0x7ffffdc0,0x7fec0001,0x7fe406ff, + 0x980007ff,0x001fffff,0xfe89fff9,0xfa87ffff,0x00efffff,0x3fffffea, + 0x3ffe6003,0x000004ff,0x01fffffc,0x7fffff30,0x037ffffc,0x45ffff60, + 0x3ea6ffff,0xfff14fff,0xfb80005f,0x8804ffff,0x001fffff,0x27ffff40, + 0x1fffff20,0x3ffe6000,0xffb001ff,0xffffb87f,0xffff80ff,0x260aefff, + 0x7ffffffb,0x7fffe400,0x4000000f,0x003fffff,0x8bffffe6,0x007ffffe, + 0xf87fffe4,0x3ff66fff,0xffff74ff,0xffb80001,0xff004fff,0x80005fff, + 0x403ffffe,0x007ffffc,0xfffff980,0x5fffd001,0x6fffffa8,0xffffff70, + 0xffffffff,0x005fffff,0x2fffffc4,0x3bf66000,0x3fffff84,0x3fffee00, + 0x3ffff61f,0x3ff2001f,0xffffd0ff,0x9fffff51,0x0017fffa,0x3ffffee0, + 0xffffd004,0xfff80007,0x7fe402ff,0x980007ff,0x001fffff,0xfc83ffff, + 0x3205ffff,0xffffffff,0xffffffff,0x7fdc003f,0x20001fff,0x45fffff9, + 0x003fffff,0x83fffff6,0x04fffffc,0x47fffee0,0xffeffffd,0xffefffff, + 0xb80003ff,0x004fffff,0x007ffffd,0x2fffff80,0x3ffffe40,0x7ffcc000, + 0x103791ff,0x7dc1ffff,0x403fffff,0xfffffffc,0xffffffff,0xfffe8003, + 0x7ec0006f,0x3e1fffff,0x1003ffff,0x98bfffff,0x006fffff,0x5cbfffea, + 0xffffffff,0xffffffff,0xfb80000e,0xd004ffff,0x0007ffff,0x02fffff8, + 0x03ffffe4,0x7fffcc00,0x9bfffb1f,0x73ffff75,0xfffffffd,0xffff9001, + 0xffffffff,0xff50005d,0x80007fff,0x3fffffff,0x00fffffe,0x17ffffdc, + 0x0ffffff4,0x3ffff980,0xfffffff1,0xffffffd7,0x2e00001f,0x004fffff, + 0x007ffffd,0x2fffff80,0x3ffffe40,0x7ffcc000,0xffffb1ff,0xffffffff, + 0xffffffff,0xffea8003,0x02dfffff,0x3ffff600,0xffe80007,0x3fe2ffff, + 0xfd003fff,0x3ee0ffff,0x1004ffff,0x7d47ffff,0xff34ffff,0x0003ffff, + 0x7ffffdc0,0xffffd004,0xfff80007,0x7fe402ff,0x980007ff,0xfb1fffff, + 0xffffffff,0xffffffff,0x540005ff,0x003fffff,0x7ffffcc0,0xffc80004, + 0x3fe0ffff,0xf9803fff,0xf104ffff,0x001fffff,0x98dffff1,0x6dcc1cec, + 0xb800002c,0x004fffff,0x007ffffd,0x2fffff80,0x3ffffe40,0x7ffcc000, + 0xffffb1ff,0xffffffff,0x05dfffff,0xffff8800,0x7e40005f,0x0000ffff, + 0x85ffffb0,0x803fffff,0x01fffffd,0x13fffff6,0x0fffffc0,0x00000000, + 0x0fffffee,0x1fffff40,0x3fffe000,0x7ffe402f,0xf980007f,0xffb1ffff, + 0xffffffff,0x05dfffff,0x7fff4000,0x880601ff,0x005fffff,0x4055d400, + 0x403fffff,0x06fffffa,0x7fffffd4,0xffffc801,0x00000003,0x7ffffe40, + 0xffffb002,0x7fc40009,0x7e401fff,0x80007fff,0x41fffff9,0xfffedba9, + 0x001acdef,0xffffd800,0x27e443ff,0x2fffffb8,0x7c000000,0x2203ffff, + 0x01ffffff,0x6fffffd8,0x6ffff980,0x00000000,0x0fffffec,0x5ffffc80, + 0x3ffe6000,0x7fe400ff,0x980007ff,0x401fffff,0x000ffff9,0xfffa8000, + 0xffefffff,0xffe81fff,0x000006ff,0x3fffff80,0x3fffff20,0xffff1004, + 0xffd007ff,0x000005ff,0x3ffe2000,0x3ee007ff,0x0000ffff,0x00fffff7, + 0x00fffff9,0xfffff300,0x7fffa803,0x36000000,0xffffffff,0x546fffff, + 0x003fffff,0xfff80000,0xfff503ff,0xfa800dff,0x401fffff,0x02fffffb, + 0x00400440,0xdfffff90,0x7fffd400,0xff88004f,0xfc806fff,0x80007fff, + 0x01fffff9,0x002fffdc,0xffd10000,0xffffffff,0x7fec5fff,0x00000fff, + 0xfffff800,0xfffff983,0xffd8001f,0x2200ffff,0x01ffffff,0x4400fc88, + 0x7fe402df,0x2003ffff,0xdffffff8,0xfffb8801,0xfc803fff,0x80007fff, + 0x01fffff9,0x0027ffe4,0x3f220000,0xffffffff,0x4cccc1ef,0x00000009, + 0x87fffff0,0x3ffffff9,0xffff1000,0x7e401dff,0x1bdfffff,0x1fffb733, + 0xeffff880,0xfffedccc,0xb8005fff,0xffffffff,0xfffd90ef,0x00dfffff, + 0x3ffffff2,0x91ffffff,0xffffffff,0xe803ffff,0x00003fff,0xffdb1000, + 0x0007bdff,0xf0000000,0x7c47ffff,0x005fffff,0x7ffffcc0,0x3ffa00ef, + 0xffffffff,0x00ffffff,0x7fffffc4,0xffffffff,0xfd0000ff,0xffffffff, + 0x3fffff61,0x9002ffff,0xffffffff,0x3f23ffff,0xffffffff,0x7fc01fff, + 0x000002ff,0x00131000,0x00000000,0x13fffff8,0x0bfffffd,0x3ffe6000, + 0x3a205fff,0xffffffff,0x0fffffff,0x7ffffc40,0xffffffff,0x220002ff, + 0xfffffffe,0xfffffb0f,0x64007fff,0xffffffff,0xff91ffff,0xffffffff, + 0x000003ff,0x00000000,0x00000000,0x3fffff80,0x017ffff6,0xffff3000, + 0xfff9003f,0xffffffff,0xff1007df,0xffffffff,0x00019fff,0x3ffffaa0, + 0xffffb0ff,0xc8001bff,0xffffffff,0xff91ffff,0xffffffff,0x000003ff, + 0x00000000,0x00000000,0x3fffff80,0x0002ffec,0x01fff980,0x3fffae20, + 0x001cefff,0x7fffedc4,0x000ceeff,0x99753000,0x2af32a19,0x99500009, + 0x99999999,0x3332a199,0xcccccccc,0x0000000c,0x00000000,0x00000000, + 0x41fffffc,0x4000005d,0x440001f9,0x10000019,0x00000033,0x00000000, + 0x00000000,0x00000000,0x00000000,0x7fc00000,0x00003fff,0x00002000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x7ffffc00,0x00000003,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0xf8000000,0x0003ffff,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x55555500,0x20000000,0x00000999, + 0x00002620,0x33bf6e60,0x5554c002,0x026aaa0a,0x77774c00,0xeb8001ee, + 0x0004eeee,0x001004cc,0x4002a620,0x00aaaaa9,0x2a200000,0x7fe4000a, + 0x00000fff,0xfffed980,0xeeeeefff,0xb7005eee,0x07dfffff,0xffff7000, + 0x1001bfff,0x7c4dffff,0x2cefffff,0x3ffffa00,0xffe8005f,0x2a003fff, + 0xfffffedb,0x70ffdbbd,0xea87dddd,0x02deffff,0x0bfffff2,0x7dc00000, + 0x26004fff,0x003fffff,0x3ff62000,0xffffffff,0x6fffffff,0x7ffff4c0, + 0x02efffff,0xfffff900,0x900bffff,0x7c43ffff,0xffffffff,0xfffb802e, + 0x26000fff,0x00ffffff,0xfffffe98,0xffffffff,0xffff90ff,0x3ffff629, + 0x903fffff,0x005fffff,0xfff30000,0x74005fff,0x0007ffff,0xfffff100, + 0xffffffff,0x0dffffff,0x7fffffdc,0x2fffffff,0x7fffc400,0x1fffffef, + 0x0ffffe60,0xfffffff1,0x405dffff,0x2ffffff8,0x3ffff200,0xfffb805f, + 0xffffffff,0x90ffffff,0xff19ffff,0xffffffff,0xfff909ff,0x000005ff, + 0xffffff90,0x7ffd400d,0x800002ff,0xfffffffe,0xfffffffe,0xf306ffff, + 0xffffffff,0x01ffffff,0x8f7ffe40,0x205ffffa,0xf886fffe,0xffffffff, + 0x3602ffff,0x005fffff,0x0bfffffe,0xffffffd0,0xffffffff,0x3f21ffff, + 0xfffedfff,0xffffffff,0x7ffe43ff,0x000002ff,0xffffffd8,0x7fffc007, + 0x6400006f,0x41efffff,0xcffffffa,0xfffd03cc,0xff957dff,0x400bffff, + 0x7e44fffe,0xfff906ff,0xffff103f,0xffffffff,0x3fea03ff,0x9800ffff, + 0x406fffff,0xfffffffb,0xffeccace,0xff90ffff,0xffffffff,0xffffffdf, + 0xffffc8ff,0x8000002f,0x5ffffffc,0x7fffdc00,0x3e00001f,0x2206ffff, + 0x403fffff,0x84fffffa,0x07fffff9,0x70bfffe0,0xff30ffff,0x533009ff, + 0xfffffff9,0x3ffe01ff,0xfc803fff,0x2203ffff,0x1fffffff,0x3fffffa0, + 0xffffff90,0x36217dff,0x22ffffff,0x02fffffc,0xff880000,0x4002ffff, + 0x04fffff8,0xffff1000,0xfffc805f,0x7ffdc07f,0xfff900ff,0xff1001ff, + 0xfff983ff,0x06fffe87,0xffff7100,0x3ee0bfff,0xf806ffff,0x200fffff, + 0x0efffffd,0x7fffff40,0xffffff90,0x7ffec0bf,0x3fff26ff,0x000002ff, + 0x05fffd30,0x3ffff600,0xfa80000f,0x5400ffff,0x200fffff,0x206ffffd, + 0x01fffffa,0x42ffff88,0x7e47fffb,0x40001fff,0x7ffffffa,0xffffff10, + 0x7fffd403,0x3ffe605f,0xfe802fff,0xff90ffff,0x401dffff,0x0ffffffa, + 0x05fffff9,0x18800000,0x7ffcc000,0xb80003ff,0xa807ffff,0x200fffff, + 0x206ffffe,0x00fffffb,0xc89ffff0,0x3fe65fff,0x900004ff,0x01ffffff, + 0x13fffff6,0x2fffffd8,0x3ffffee0,0xffffd006,0x3ffff21f,0xfff800ef, + 0xfff91fff,0x026203ff,0x00000000,0x037ffff4,0x7fffd400,0x7ffdc00f, + 0x7ffe407f,0xfffb00ff,0x7ff400df,0xffff51ef,0x037fff49,0xffff3000, + 0x3fea05ff,0xff107fff,0xfc80ffff,0xd003ffff,0x321fffff,0x002fffff, + 0x25fffffb,0x21fffffc,0xdefffeca,0x00000002,0x3ffffea0,0x7fc40002, + 0x7f403fff,0x7dc05fff,0xfa82ffff,0x2004ffff,0xfefffffa,0xff70ffff, + 0x800003ff,0x03ffffff,0x0bfffffe,0x13ffffee,0x5fffffb0,0x3ffffa00, + 0xfffff90f,0x3fff6005,0xffff93ff,0x3ffff23f,0x203fffff,0xeeeeeeeb, + 0x002eeeee,0x17ffffe0,0x3fffe000,0xfff901ff,0xff9809ff,0x3ea0ffff, + 0x000fffff,0x7ffffff4,0xfff33fff,0x8800009f,0x02ffffff,0x17fffff2, + 0x03fffffa,0x3fffffd0,0x3ffffa00,0xfffff90f,0x3fff2005,0xffff94ff, + 0xfffffb3f,0x09ffffff,0x3ffffff2,0x03ffffff,0x3ffff200,0x7d40001f, + 0xaacfffff,0xffffffeb,0xffffd800,0xffffc8df,0xd88002ff,0x2fffffff, + 0x003bfffa,0xffff5000,0x7fc401ff,0x3e60ffff,0xf806ffff,0x000fffff, + 0x21fffffd,0x02fffffc,0x9fffff90,0x3bfffff2,0xffffffff,0xc83fffff, + 0xffffffff,0x0003ffff,0x13ffffe2,0x3fff6000,0xffffffff,0x3001ffff, + 0xffffffff,0x007fffff,0xbdfeca80,0x0bfffee0,0xfff10000,0xfb00ffff, + 0x7e45ffff,0x4402ffff,0x00ffffff,0x1fffffd0,0x0bfffff2,0x7ffffec0, + 0xffffff93,0xffdfffff,0x90ffffff,0xffffffff,0x0007ffff,0x0fffffd8, + 0x3ffe2000,0xffffffff,0x4003ffff,0xfffffffc,0x0001ffff,0xffff8800, + 0x73100004,0x7fffffff,0xfffff500,0x3fffffcb,0xffffff80,0xffffd001, + 0x3ffff21f,0xfffb002f,0x3fff25ff,0x0befffff,0xffffffb1,0xeeeeeb85, + 0x3ffffffe,0x7ffcc000,0x360003ff,0xffffffff,0x00cfffff,0xfffffd00, + 0x00019fff,0x3fffa000,0x3fe0000f,0xffffffff,0x3fe006ff,0xff98ffff, + 0xfd004fff,0x2003ffff,0x90fffffe,0x005fffff,0x43fffffe,0xfffffffc, + 0x3ffff605,0x3ff2006f,0x80003fff,0x006ffffe,0x2dffff50,0x0abcdcca, + 0x3ffe6000,0x001fffff,0x3fee0000,0x7c0002ff,0xffffffff,0x32001fff, + 0xfcbfffff,0xb001ffff,0x007fffff,0x1ffffff5,0x0bfffff2,0x3ffffe60, + 0x3fffff27,0x3fea00ef,0x9000ffff,0x007fffff,0xfffff700,0xfffb0005, + 0x4000005f,0xfffffffb,0x999904ff,0x7c400039,0x80005fff,0xffffffff, + 0x4c000dff,0xffefffff,0x32006fff,0x405fffff,0xfffffff9,0x5fffff90, + 0xfffffb00,0x7ffffe4d,0xffff800e,0xff9001ff,0x00007fff,0x017ffffe, + 0x0fffffe0,0x7fdc0000,0xffffffff,0x7fffc43f,0x3f60002f,0x80000fff, + 0xffffffff,0x3fa0002d,0xffffffff,0x3fea003f,0xf100ffff,0x1fffffff, + 0x0bfffff2,0xffffff50,0x7ffffe47,0xffffb002,0x3ff2005f,0x00003fff, + 0x01fffff9,0xffffff80,0x7d400002,0xffefffff,0x3e21ffff,0x0001ffff, + 0x885ffff5,0xfd0009aa,0x0003dfff,0x3ffffea0,0x000fffff,0x77fffffc, + 0x7ffff5c0,0xff90ffff,0x7dc05fff,0x645fffff,0x002fffff,0x07fffffb, + 0x3fffff20,0xff100003,0xd8009fff,0xefffffff,0x9accdeee,0xffffe800, + 0xfffffd3f,0x3fffe21f,0xff88000f,0x3ffea5ff,0xfe804fff,0x00004fff, + 0x7ffffffc,0xfb8004ff,0xcdffffff,0xffffffff,0xfff90fff,0x75559dff, + 0xfffffffb,0xfffffc81,0xffff9002,0x3ff2009f,0x00003fff,0x03fffff6, + 0xfffffa80,0xffffffff,0x501dffff,0x449fffff,0x8effffff,0x007ffffa, + 0x21ffffb0,0xfffffffc,0x3ff600ef,0x400004ff,0xfffffffc,0xff88001f, + 0xffffffff,0xffffffff,0xffff90ff,0xffffffff,0x07ffffff,0x05fffff9, + 0x3fffff20,0xffff9004,0x5400007f,0x003fffff,0x7fffffd4,0xffffffff, + 0xfe84ffff,0x7cc1ffff,0xfbdfffff,0xa8007fff,0xff33ffff,0xffffffff, + 0x7fffec09,0x7cc00003,0x05ffffff,0x3fffea00,0xffffffff,0x0fffffcd, + 0xfffffff9,0xffffffff,0x3ff207ff,0xfb002fff,0x2007ffff,0x03fffffc, + 0x7fff4000,0x7f44006f,0xffffffff,0xffffffff,0x7ffffc3f,0xfffff707, + 0x09ffffff,0x5ffff880,0x2efffffa,0xb00fffff,0x0007ffff,0xfffffd00, + 0xf980003f,0xffffffff,0xfffff94f,0x3fffff21,0xffffffff,0x3f200dff, + 0xb002ffff,0x005fffff,0x0ffffff2,0xfff70000,0x3a6003ff,0xeeefffff, + 0xfffffeee,0xff10ffff,0x7e40bfff,0xffffffff,0x7fec001f,0xffff30ff, + 0x17fffc43,0x20000000,0x05fffffe,0xfffb3000,0x7ec5dfff,0xff90ffff, + 0xffffffff,0x9005bdff,0x005fffff,0x03fffffe,0x7ffffe40,0x7c400003, + 0x8805ffff,0x01fffffe,0x7ffffe44,0xfffff12f,0xffffd80b,0x4006ffff, + 0x2a3ffffa,0xfff87fff,0x0000003f,0x3ffffea0,0x9800002f,0xffd81abb, + 0xfff90fff,0x355535ff,0xffff9000,0xfff3005f,0x7e400fff,0x0003ffff, + 0xfffffc80,0x7fffe400,0x3ff2002f,0x3ffe4fff,0x7f4407ff,0x03ffffff, + 0x1bfffe20,0xfb0dfff7,0x008809ff,0xffe88000,0x00006fff,0x3fff6000, + 0xffff90ff,0x3200005f,0x802fffff,0x06fffffd,0x3fffff20,0xf9800003, + 0x7c04ffff,0x4007ffff,0x24fffffb,0x02fffffe,0x7fffffcc,0x3ff2000f, + 0x7ffdc1ff,0x04fffd86,0x003dfff5,0x7fffec00,0x000001ff,0x3ffffa00, + 0xfffff90f,0x3f200005,0x5402ffff,0x03ffffff,0x3fffff20,0xfb000003, + 0x7c40ffff,0x4007ffff,0x22fffffc,0x1ffffffc,0x3ffffea0,0xff5004ff, + 0xfff507ff,0x07ffff0f,0x3ffffff3,0xffe98000,0x0002ffff,0x7ff40000, + 0xfff90fff,0x200005ff,0x02fffffc,0x3fffffee,0x7ffe4005,0x000003ff, + 0x05fffff5,0x17fffffc,0xfffffa80,0x3fffe60f,0xba9bdfff,0xfffffffd, + 0x7f4403ff,0xfff306ff,0x7fffc43f,0xfffffd82,0x3bb2005f,0xfffffffe, + 0x0000004f,0xfffffe80,0x5fffff90,0x3ff20000,0xaaacefff,0xffffffdb, + 0x7fe4000f,0x00003fff,0x1bffffa0,0xffffffd8,0x7ecc41ac,0xc84fffff, + 0xffffffff,0xffffffff,0x02ffffff,0x407ffff2,0xbcfffff8,0xff06ffff, + 0x00dfffff,0x7fffffe4,0x0006ffff,0xffd00000,0x3ff21fff,0x00002fff, + 0xfffffff9,0xffffffff,0x99307fff,0xffd99999,0x9999dfff,0xb8000599, + 0x501fffff,0xffffffff,0xffffffff,0x740bffff,0xffffffff,0xffffffff, + 0x80ffffff,0x403ffff9,0xfffffffb,0xffd02fff,0x400bffff,0xfffffffc, + 0x00000dff,0xfffd0000,0x3fff21ff,0x900002ff,0xffffffff,0xffffffff, + 0x3ffee07f,0xffffffff,0xffffffff,0x7c40004f,0x2a05ffff,0xffffffff, + 0xffffffff,0x7e4406ff,0xffffffff,0xff8aefff,0x740effff,0xfd006fff, + 0x9fffffff,0x7ffffdc0,0x3ff2002f,0x02efffff,0x40000000,0x90fffffe, + 0x005fffff,0x3ffff200,0xffffffff,0x2e00dfff,0xffffffff,0xffffffff, + 0x0004ffff,0x0fffffc8,0x3ffffaa0,0xffffffff,0x22002dff,0xfffffffd, + 0x7ffcc3ff,0x3ff25fff,0x3ee001ff,0x802fffff,0x004ffffc,0x677fffe4, + 0x00000003,0xfffffd00,0x3fffff21,0x2e600002,0xfffffffd,0xb802deff, + 0xffffffff,0xffffffff,0x0004ffff,0x4fffff98,0xfffec980,0x1cdeffff, + 0x654c4000,0x0000009a,0x01553000,0x001bb980,0x00003330,0x2e000000, + 0x950ccccc,0x00039999,0x554cc400,0xffb8001a,0xffffffff,0xffffffff, + 0xd00004ff,0x000fffff,0x00002662,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0xf5000000,0x0005ffff,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0xfffff000,0x555554cd,0x00000000,0x77ff65d4,0x55511bce,0x80000355, + 0xaaaaaaa9,0x001aaaaa,0x26000000,0x2000000b,0x00000aa8,0x13555100, + 0x2a660000,0x000099aa,0xf7000000,0x3f23ffff,0x0002ffff,0xffd50000, + 0xffffffff,0x3ffffea9,0x7e400004,0xffffffff,0x20003fff,0x000cefea, + 0x07fff6e6,0xfdc98000,0x1cdfffff,0xdca88000,0xffffffff,0x36a000bd, + 0xffffffff,0xea81bdff,0x00000cef,0x09999980,0x05fffff9,0xe8800000, + 0xffffffff,0xff54ffff,0x00009fff,0xffffffc8,0x03ffffff,0xfffff700, + 0x3ffa001d,0x00001fff,0xfffffff7,0x009fffff,0x7ffffdc0,0xffffffff, + 0xffe9803f,0xffffffff,0x2e0fffff,0x00efffff,0x32000000,0x002fffff, + 0x7fec0000,0xffffffff,0xfff54fff,0x800009ff,0xfffffffc,0x003fffff, + 0xffffff98,0xfffd004f,0x880003ff,0xfffffffd,0xdfffffff,0x3ff62000, + 0xffffffff,0x403fffff,0xfffffffb,0xffffffff,0xffff30ff,0x00009fff, + 0x15555540,0x05fffff9,0x7d400000,0xefffffff,0xf54fffee,0x0009ffff, + 0xfffffc80,0x3fffffff,0xffffb800,0xfd007fff,0x0003ffff,0x7fffffcc, + 0xffffffff,0x9801efff,0xfffffffe,0xffffffff,0xfffd103f,0xffffffff, + 0x1fffffff,0x3fffffee,0x2000007f,0x90fffffe,0x005fffff,0x3fe20000, + 0x102fffff,0x3fffea53,0x4400004f,0xfd999999,0x8003ffff,0xfffffffc, + 0xfffe800f,0x3a0001ff,0xffffffff,0xffffffff,0x7fcc05ff,0xffffffff, + 0xffffffff,0xfffff883,0xffffffff,0x0fffffff,0xfffffff9,0x2000001f, + 0x90fffffe,0x005fffff,0x3fe60000,0x2001ffff,0x04fffffa,0x3f200000, + 0x8003ffff,0xfffffffa,0xffffd006,0x3ea0003f,0x1befffff,0xfffff951, + 0x7ff403ff,0x9bdfffff,0x7ffb5310,0xffffff90,0x4c4159df,0xf50fffca, + 0x0dffffff,0x7ff40000,0xfff90fff,0x000005ff,0x3ffffea0,0x7ffd4004, + 0x000004ff,0x3fffff20,0xfff88003,0xd003ffff,0x003fffff,0x3fffffa0, + 0x3ffee00e,0xff505fff,0x005fffff,0xfff30aa2,0x800bffff,0xffff10c9, + 0x00007fff,0x7fffff40,0x5fffff90,0x32000000,0x002fffff,0x27ffffd4, + 0xf9000000,0x0007ffff,0x17ffffe6,0xfdddddd7,0xdddfffff,0x8bdddddd, + 0x0ffffffb,0xfffffb80,0xffffe80f,0xd80001ff,0x03ffffff,0xffff3000, + 0x800000bf,0x90fffffe,0x105fffff,0x20000153,0x01fffffd,0x7ffffd40, + 0x20000004,0x03fffffc,0x0b36e200,0x3ffffff2,0xffffffff,0x6fffffff, + 0x1ffffffc,0xffffff00,0xfffffb89,0xfa80002f,0x004fffff,0x166dc400, + 0x7f400000,0xff90ffff,0x7f543fff,0x001dffff,0x3fffffa0,0x7ffd4000, + 0x76c404ff,0x001eeeee,0x0ffffff2,0xff900000,0xffffffff,0xffffffff, + 0x7fccdfff,0x2001ffff,0x46fffffd,0x07ffffff,0xffffd000,0x000001ff, + 0xd0000000,0x321fffff,0xd89fffff,0xffffffff,0xffd0003f,0xa8001fff, + 0x404fffff,0x3ffffffd,0x7fffe400,0x4000003f,0xfffffffc,0xffffffff, + 0x26ffffff,0x06fffffb,0x7ffffd40,0x3ffffe27,0xff00003f,0x0009ffff, + 0x00000000,0x3fffffa0,0x3fffff90,0xfffffffd,0x0007ffff,0x01fffffd, + 0xfffffa80,0x3ffff204,0xfc8004ff,0x0003ffff,0x77775c00,0xffffffee, + 0xeeeeeeee,0x3ffff65e,0x7fc4004f,0xff30ffff,0x0001ffff,0xffffff10, + 0x00000001,0x42660000,0x90fffffe,0xffdfffff,0xffffffff,0x26660fff, + 0xfffe9999,0x99999aff,0x3fea0999,0xff704fff,0x000bffff,0x0ffffff2, + 0xe8000000,0x001fffff,0x1ffffff4,0x7ffffc00,0xfffff51f,0x3e60000f, + 0x0007ffff,0x50000000,0xfffffdb9,0x21ffffff,0xfffffffc,0xfffeffff, + 0xff83ffff,0xffffffff,0xffffffff,0x3ea6ffff,0xf984ffff,0x006fffff, + 0x3fffff20,0x00000003,0x07fffffa,0xffffff00,0xffff0007,0x3ffee3ff, + 0x500006ff,0x40dfffff,0xaaaaaaaa,0x00000aaa,0xfffffd30,0xffffffff, + 0x3fff21ff,0x0befffff,0xbfffffd5,0xfffffff0,0xffffffff,0xdfffffff, + 0x27ffffd4,0x3fffffe2,0x3f20000e,0x0003ffff,0x3ffa0000,0x7c001fff, + 0x002fffff,0x2fffffe8,0x0bfffffb,0x3ffee000,0xfff105ff,0xffffffff, + 0xc8800003,0xffffffff,0xffffffff,0xfffff90f,0x3fea0bff,0xfff86fff, + 0xffffffff,0xffffffff,0x3fea6fff,0x3fa24fff,0x000fffff,0x7ffffe40, + 0x00000003,0x07fffffa,0xffffff00,0xfffd0003,0x3fffa7ff,0xb00004ff, + 0x209fffff,0xfffffff8,0x0001ffff,0x7fffff40,0xffffffff,0xf90fffff, + 0x01dfffff,0x1fffffe2,0x3ffffffe,0xffffffff,0x6fffffff,0x93ffffea, + 0x1ffffffd,0xfffc8000,0x2e0003ff,0x74004efe,0x001fffff,0x0ffffffc, + 0x7fffec00,0xffffff3f,0x3fa00009,0xf104ffff,0xffffffff,0x002203ff, + 0xffffff70,0xfd9959df,0x321fffff,0x00efffff,0x07fffff4,0x2aaaaaaa, + 0xabfffffe,0x2aaaaaaa,0x53ffffea,0x2ffffffc,0xfff90000,0x320007ff, + 0x00dfffff,0x3fffffd0,0xfffff800,0xffe8002f,0xfffd3fff,0x20000bff, + 0x04fffffd,0xfffffff1,0xfb83ffff,0xf8801eff,0x01ffffff,0x43fffffa, + 0x02fffffc,0x0fffffe8,0x3ffffa00,0x7fd4000f,0xfffacfff,0x00003fff, + 0x0ffffff2,0x3fffe200,0xfd004fff,0x8003ffff,0x03fffffe,0xffffff80, + 0xdfffffb2,0x3ff20000,0x2aa05fff,0xffffeaaa,0x3ffff61f,0x7fec01ff, + 0x7400efff,0xf90fffff,0xd005ffff,0x001fffff,0x07fffff4,0x3fffea00, + 0xffffffef,0x7e400003,0x8003ffff,0xfffffffa,0xfffe800f,0x7ec001ff, + 0x8003ffff,0x92ffffff,0x00ffffff,0x3fffee00,0x7fec006f,0xfff31fff, + 0x4c0bffff,0x02ffffff,0x0fffffe8,0x05fffff9,0x1fffffd0,0x7ffff400, + 0x7fd4000f,0xffffffff,0xc800006f,0x003fffff,0xffffffa8,0xffe802ff, + 0x64001fff,0x004fffff,0x7fffffc4,0xffffff71,0x3fe60000,0x6c007fff, + 0xf71fffff,0x0fffffff,0x37ffffd4,0xfffffe80,0x5fffff90,0xfffffd00, + 0x7fff4001,0x7d4000ff,0xffffffff,0x00003fff,0x1fffffe4,0x7fffc400, + 0xe803ffff,0x001fffff,0x37ffffdc,0x3fffea00,0x3fffea7f,0x880003ff, + 0x01ffffff,0x3fffff60,0xffffff91,0x7ffe40ff,0xffd003ff,0x3ff21fff, + 0xfe802fff,0x2000ffff,0x00fffffe,0x7ffffd40,0xffffffdc,0x3f200001, + 0x0003ffff,0xfffffff5,0xffffd009,0xffa8003f,0x2000ffff,0x25fffffc, + 0x6ffffff9,0xffff0000,0x7ec00bff,0xff51ffff,0x40dfffff,0x02fffffd, + 0x1fffffd0,0x0bfffff2,0x3fffffa0,0x3fffa000,0x7d4000ff,0xfe8cffff, + 0x000fffff,0xfffff900,0x7fe40007,0xe803ffff,0x001fffff,0x7fffffc4, + 0x3fffe003,0x7fffc3ff,0x80002fff,0x0ffffffe,0xfffffb00,0x7fffff43, + 0x3fffa02f,0xffd001ff,0x3ff21fff,0xfe802fff,0x2000ffff,0x00fffffe, + 0x7ffffd40,0xffffff34,0x3f20000d,0x0003ffff,0x17fffff4,0x7fffff40, + 0xfffd8002,0xfb800eff,0xfb87ffff,0x01efffff,0x7fffcc00,0xffb005ff, + 0x7f443fff,0x7fc03fff,0xd000ffff,0x321fffff,0x802fffff,0x00fffffe, + 0x3fffffa0,0x7ffd4000,0x3ffee4ff,0x80005fff,0x03fffffc,0x7fffe400, + 0xfffd800f,0xf98003ff,0x406fffff,0x3ffffffa,0xffffffd0,0x0ae2005f, + 0xdffffffb,0xffffd801,0x00aba81f,0x7fffffc4,0xffffd000,0x3ffff21f, + 0xfffe802f,0x3fa000ff,0x4000ffff,0x44fffffa,0x3ffffffd,0x7ffe4000, + 0x6c0003ff,0x7007ffff,0x01ffffff,0xfffffd00,0x7dcc15df,0x206fffff, + 0xfffffffa,0x2e609bdf,0x7fc43ffd,0xabffffff,0x7fffec40,0xff80001f, + 0xd001ffff,0x321fffff,0x802fffff,0x00fffffe,0x3fffffa0,0x7ffd4000, + 0x7ffc44ff,0x0001ffff,0x0ffffff2,0xffff8800,0xfff5002f,0x3357ffff, + 0xff50bb75,0xffffffff,0xffffffff,0xfffe805f,0xffffffff,0x3fffffff, + 0xffffffc8,0xfeefffff,0x01ffffff,0xffffe800,0xfffd001f,0x3fff21ff, + 0xffe802ff,0x3a000fff,0x000fffff,0x27ffffd4,0x7fffffd4,0xff90000f, + 0x20007fff,0x05fffff9,0x7fffff40,0xffffffff,0xfffffb06,0xffffffff, + 0x300bffff,0xfffffffd,0xffffffff,0xffd107ff,0xffffffff,0xffffffff, + 0xfb00003f,0x5007ffff,0x21ffffff,0x02fffffc,0x0fffffe8,0x3ffffa00, + 0x7fd4000f,0xff904fff,0x260dffff,0xeccccccc,0xccefffff,0x5512cccc, + 0xdfffffd7,0xfff98001,0xffffffff,0x3fee06ff,0xffffffff,0x003fffff, + 0x7fffffe4,0xffffffff,0x3fee03ff,0xffffffff,0xffffffff,0xffc80001, + 0x7cc05fff,0x90ffffff,0x005fffff,0x01fffffd,0x7fffff40,0x7ffd4000, + 0x3ffa04ff,0xfb85ffff,0xffffffff,0xffffffff,0xfff94fff,0x03dfffff, + 0x3fffee00,0xffffffff,0x7fffcc06,0xffffffff,0xfd50001e,0xffffffff, + 0x805fffff,0xffffffe9,0xffffffff,0xa80000ef,0x00ffffff,0xfffffff1, + 0x3ffff21f,0xfffe802f,0x3fa000ff,0x4000ffff,0x04fffffa,0x3fffffe2, + 0x7fffdc3f,0xffffffff,0xffffffff,0xffffff94,0x9100007f,0xffffffff, + 0xd9100bff,0xdfffffff,0xb8800019,0xffffffec,0x2000adff,0xfffffedb, + 0x00beffff,0x7fffc000,0x7f5c0eff,0x0fffffff,0x05fffff9,0x1fffffd0, + 0x7ffff400,0x7fd4000f,0x7d404fff,0x22ffffff,0xfffffffb,0xffffffff, + 0xf94fffff,0x0019dfff,0x79553000,0x44000355,0x00001aba,0x09aaa880, + 0x32a60000,0x000099aa,0x3fffee00,0xfffcdfff,0xffffffff,0x5fffff90, + 0xfffffd00,0x7fff4001,0x7d4000ff,0xc804ffff,0x0fffffff,0xfffffff7, + 0xffffffff,0x2a9fffff,0x0000009a,0x00000000,0x00000000,0x00000000, + 0xffff1000,0xffffffff,0xfffffbff,0x00000001,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x3ffea000,0xffffffff, + 0xfffff8df,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x3ffe6000,0x4fffffff,0x003ffffe,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0xfffffb30,0xffff85df,0x0000000f,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x2e600000,0x000001ab,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x0006aa20,0x55554c40,0x44000009,0x00009aa9, + 0x4d554c40,0xffffc801,0xffffffff,0x005fffff,0x3b72ea60,0x20007fff, + 0x00009a98,0x0026a620,0x0fffffe8,0x3ffff200,0x9998002f,0xaaa98019, + 0x5c4002aa,0xefffffed,0xfb71000c,0xffffffff,0x2a0003bf,0xfffffffe, + 0xd98002ef,0xfffffffe,0xfc81ceff,0xffffffff,0xffffffff,0x7fdc4005, + 0xffffffff,0x7ff5c007,0x02efffff,0x7ff65c40,0x402dffff,0x00fffffe, + 0x3fffff20,0x3ffaa002,0xffb807ff,0x2a007fff,0xffffffff,0xd802ffff, + 0xffffffff,0x1dffffff,0xffffd500,0xffffffff,0xffb3005d,0xffffffff, + 0xf909ffff,0xffffffff,0xffffffff,0x3ff6600b,0xffffffff,0xfd5007ff, + 0xffffffff,0xf7001bff,0xffffffff,0x3a03bfff,0x000fffff,0x0bfffff2, + 0x3ffffa60,0xffb807ff,0xf7007fff,0xffffffff,0x809fffff,0xfffffffd, + 0xffffffff,0x7ffdc00f,0xffffffff,0x202fffff,0xfffffffb,0xffffffff, + 0xffffc84f,0xffffffff,0x805fffff,0xfffffff9,0x7fffffff,0x7fffec40, + 0xffffffff,0xfd302fff,0xffffffff,0x03ffffff,0x01fffffd,0x7ffffe40, + 0x3fff6602,0x807fffff,0x06fffffa,0xffffffd8,0xffffffff,0x3ff605ff, + 0xffffffff,0x06ffffff,0x3fffffe6,0xffffffff,0xfa81ffff,0xffffffff, + 0xffffffff,0xfffffc84,0xffffffff,0x5405ffff,0xffffffff,0x7fffffff, + 0x7ffffec0,0xffffffff,0x7dc0ffff,0xffffffff,0xffffffff,0xfffffe86, + 0x3fff2000,0xffd882ff,0xffffffff,0xffffa807,0x7ffe406f,0xfdbdffff, + 0x2fffffff,0xbddfffb0,0xfffffb99,0xff107fff,0x37bfffff,0xfffffb75, + 0xffff88bf,0xeeefffff,0x84ffffee,0xeefffffc,0xeeeeeeee,0x3fea04ee, + 0xccffffff,0x0199999a,0x3fffffea,0xfffeccef,0x7dc4ffff,0xefffffff, + 0xffffffff,0x7ffff44f,0x3ff2000f,0x3f222fff,0xffffffff,0xf9807fff, + 0x2205ffff,0x85ffffff,0xffffffa8,0x80159906,0x5ffffffb,0x5fffffa8, + 0x7ffffcc0,0x7ffffe47,0x6dcc01df,0x7ffffc83,0x7ff40000,0x000cffff, + 0x3ffffe20,0xffe881ef,0x7e40ffff,0x260acfff,0x7ffffffd,0x07fffff4, + 0xfffff900,0x7fffffc5,0xffffffff,0xffff9807,0x3fff205f,0x3ea00eff, + 0x001fffff,0xfffffb80,0xfffffc87,0xffffc800,0x3ffffa1f,0xf900005f, + 0x0000ffff,0x7fffffdc,0xffb80001,0x2200ffff,0x85fffffe,0x7ec01efe, + 0x3a1fffff,0x000fffff,0x8bfffff2,0xeffffffd,0x07fffffb,0x4fffff88, + 0xffffff10,0xffffb001,0xf10000df,0xd81fffff,0x7007ffff,0x7c3fffff, + 0x002fffff,0xfffff900,0x3fe20000,0x0003ffff,0x7fffffb0,0xfffff500, + 0x1004881f,0x45ffffff,0x00fffffe,0x3fffff20,0x3ffffe62,0xffffff13, + 0xfffff100,0x3fffee09,0xfff1005f,0x00003fff,0x81ffffff,0x00fffffd, + 0x0fffffc8,0x5ffffff3,0x3ff20000,0x500007ff,0x00dfffff,0x7ffff400, + 0xfff8801f,0x40002fff,0x24ffffff,0x00fffffe,0x3fffff20,0x1067ff42, + 0x00ffffff,0x40fffffe,0x01fffffe,0xffffff30,0xff880007,0xffc87fff, + 0x7c404fff,0x3e27ffff,0x004fffff,0xfffff900,0x3ff20000,0x00003fff, + 0x0ffffff1,0x7ffffec0,0x7ff40003,0x3ffa4fff,0x32000fff,0x5c2fffff, + 0xffff880d,0xffff007f,0x3fffe07f,0xfff7006f,0x000bffff,0x5fffffa8, + 0xffffffa8,0x3ffff203,0x7ffffc3f,0xc80003ff,0x0007ffff,0x3fffffd0, + 0x3fe20000,0x32007fff,0x005fffff,0x7fffff40,0x3fffffa2,0x3fff2000, + 0x3e2002ff,0xd007ffff,0xf105ffff,0x880bffff,0xfffffffd,0x3e20006f, + 0xd01fffff,0x1bffffff,0x7fffffc8,0xffffffd8,0x320002ef,0xeeefffff, + 0x8800abcc,0x517fffff,0x359bddb9,0xffffff00,0x3ffee001,0x220005ff, + 0x21ffffff,0x00fffffe,0x3fffff20,0x3ffe2002,0x997007ff,0xfff30399, + 0x7fd409ff,0xffffffff,0xffc88007,0x2a03ffff,0xffffffff,0xfffffeac, + 0xffffb81f,0x0bffffff,0x7fffe400,0xffffffff,0x3fe602df,0xfffdffff, + 0xdfffffff,0x3ffffa00,0xfff7003f,0x5c000dff,0x20ffffff,0x00fffffe, + 0x3fffff20,0x3ffe2002,0x400007ff,0x03fffffa,0xfffffff9,0x640fffff, + 0xffffeeee,0xb801efff,0xffffffff,0x1fffffff,0x3fffff60,0x2dffffff, + 0xfffff900,0xffffffff,0xff501dff,0xffffffff,0xffffffff,0x3fff609f, + 0xfc800fff,0x0006ffff,0x13fffffa,0x01fffffd,0x7ffffe40,0x3ffe2002, + 0x400007ff,0x43fffffb,0xffffffe9,0x0ffffffe,0xffffffb0,0x001bffff, + 0x7fffffdc,0x0dffffff,0x7ffffc40,0xffffffff,0x7ffe403e,0xffffffff, + 0x40efffff,0xfffffffa,0xffffffff,0xb83fffff,0xbfffffff,0x3fff2621, + 0x0006ffff,0x3ffffff7,0x0fffffe8,0x3ffff200,0x3fe2002f,0x54007fff, + 0x7fe43efd,0x3fee2fff,0xfd4fffff,0x3601ffff,0xffffffff,0x2001ceff, + 0xffffffe8,0x1004ffff,0xfffffffb,0x1dffffff,0x3fffff20,0xffffffff, + 0x2e0effff,0xffffffff,0xffffffff,0xe80fffff,0xffffffff,0xffffffff, + 0x8006ffff,0x5ffffff9,0x0fffffe8,0x3ffff200,0x3fe2002f,0x36007fff, + 0xb0efffff,0xb13fffff,0x5fffffff,0x07fffff4,0xffffffd8,0xdfffffff, + 0xffffb800,0xffffffff,0xfff7001e,0xffffffff,0x88005fff,0xfffffba9, + 0x3fee4fff,0x9befffff,0xffffb988,0xff985fff,0xffffffff,0xffffffff, + 0x744005ff,0x80efffff,0x00fffffe,0x3fffff20,0x3ffe2002,0xff7007ff, + 0x32bfffff,0xffcfffff,0x40dfffff,0x207fffff,0xfffeeeec,0xefffffff, + 0xffffd100,0xffffffff,0x54003fff,0xfffffffe,0x000fffff,0x7ffffdc0, + 0xffff90ff,0xfe8803df,0xf707ffff,0xffffffff,0xffffffff,0x744009ff, + 0x01ffffff,0x01fffffd,0x7ffffe40,0x3ffe2002,0xffd007ff,0x91ffffff, + 0xffffffff,0x3e07ffff,0x0006ffff,0xffffff93,0xfffd10bf,0xffd59fff, + 0x03ffffff,0xffffc980,0x06ffffff,0xffffc800,0xffff72ff,0x3fe600df, + 0xb301ffff,0xffffffff,0xffffddff,0x7ff4007f,0x3a03ffff,0x000fffff, + 0x0bfffff2,0xfffff880,0xfffff007,0xff75ffff,0xffffffff,0x3ffe203d, + 0xd80005ff,0x42ffffff,0x1efffffe,0x7fffffdc,0x3aa0006f,0xffffffff, + 0x7fc40002,0xff52ffff,0x7400dfff,0x402fffff,0xdefeecb9,0xfffff91c, + 0x3fff6007,0x7f403fff,0x2000ffff,0x02fffffc,0x3ffffe20,0xfffff007, + 0xff53ffff,0xbfffffff,0x7fffcc01,0xe880004f,0x2a4fffff,0x00efffff, + 0xffffffd3,0xffb80005,0x003fffff,0xffffff80,0xffffff33,0x7fffec00, + 0x3a00003f,0x802fffff,0x4ffffffd,0xfffffe80,0x3fff6000,0x3e2000ff, + 0xb007ffff,0xffffffff,0x3fffffe6,0xffa802ff,0x00003fff,0x4bfffff9, + 0x01ffffff,0x7fffffc4,0xffa80004,0x0005ffff,0x2fffffe8,0x0ffffff1, + 0x7ffffe40,0xff100003,0xfb00ffff,0x009fffff,0x07fffff6,0x7ffffe80, + 0x7fffc400,0xfff1007f,0x7fc7ffff,0x000effff,0x05fffffb,0x3ffee000, + 0xffff16ff,0x3fea00bf,0x00005fff,0x0dffffff,0xffff8800,0x3fffe0ff, + 0xffd002ff,0x00003fff,0x13ffffea,0xffffffb0,0x7ffe4009,0x3fe002ff, + 0x44006fff,0x007fffff,0x0fffffea,0x07fffffd,0x3ffffe20,0xf900000f, + 0x3ea9ffff,0x1004ffff,0x00ffffff,0x3ffff600,0x7dc0004f,0x7f47ffff, + 0x8805ffff,0x00ffffff,0xffff8800,0x3ff601ff,0x4003ffff,0x05fffffb, + 0xbfffff30,0xffff8800,0x5d44007f,0xffffa80a,0xffb800ff,0x00004fff, + 0x4ffffffa,0x04fffffb,0xdfffff10,0x3ffe0000,0x20003fff,0x5ffffff9, + 0x7fffffd4,0x7fffe400,0xfb00006f,0x6c0dffff,0x03ffffff,0xfffffa80, + 0xfffd801f,0x7c4003ff,0x0007ffff,0xfffffd00,0xffff980b,0x900000ff, + 0x23ffffff,0x06fffff9,0x9fffff50,0x7dc0006a,0x061fffff,0x7fffe440, + 0xffe82fff,0xf901ffff,0x009fffff,0xffffea80,0xfffb03ff,0x40005fff, + 0x1ffffffe,0x3fffff20,0x7fc4000f,0x00007fff,0xffffff50,0xffff3017, + 0x800109ff,0xffffffda,0x3ffffe27,0x7ffcc04f,0xbff92fff,0x7ecc0137, + 0x227fffff,0xccccdeff,0xffffffed,0xfff503ff,0x979bffff,0xdffffffd, + 0x26666620,0xfffecaa9,0xfb04ffff,0x55bfffff,0x55555555,0x7ffd4555, + 0xbaceffff,0xffffffec,0x33333302,0xffffff53,0x03333333,0xffffe800, + 0xfdbadfff,0x80ffffff,0xccccdefc,0xffffeecc,0x7f41ffff,0xbdffffff, + 0xffffca99,0xfff90fff,0xfdddffff,0xffffffff,0x7fffc45f,0xffffffff, + 0x404fffff,0xfffffffe,0xffffffff,0xfff500ff,0xffffffff,0x20bfffff, + 0xfffffffc,0xffffffff,0x746fffff,0xffffffff,0xffffffff,0xffff305f, + 0xffffffff,0xffffffff,0xffa8000f,0xffffffff,0x3fffffff,0xffffff90, + 0xffffffff,0xf305ffff,0xffffffff,0xffffffff,0x7ffe43ff,0xffffffff, + 0xffffffff,0x7ffffc44,0xffffffff,0xe8804fff,0xffffffff,0x2fffffff, + 0x3ffffea0,0xffffffff,0xffd00eff,0xffffffff,0xffffffff,0xfff98dff, + 0xffffffff,0x00efffff,0xfffffff3,0xffffffff,0x00ffffff,0xfffff500, + 0xffffffff,0x7fe403ff,0xffffffff,0x3fffffff,0x3ffffea0,0xffffffff, + 0x7e42ffff,0xffffffff,0xffffffff,0xffff885f,0xffffffff,0x64000cff, + 0xffffffff,0x400dffff,0xfffffffa,0x2fffffff,0x7fffff40,0xffffffff, + 0x6fffffff,0xfffffc88,0xffffffff,0x7fffcc03,0xffffffff,0xffffffff, + 0xfd100007,0xffffffff,0xfc801dff,0xffffffff,0x0cffffff,0xffffea80, + 0xffffffff,0xfffc82ef,0xffffffff,0x02efffff,0xfffffff1,0x019dffff, + 0x7ffed400,0x01dfffff,0xffffff50,0x07dfffff,0x3fffffa0,0xffffffff, + 0x6fffffff,0x3ffff660,0x00dfffff,0xffffff98,0xffffffff,0x07ffffff, + 0x7ff5c000,0x03dfffff,0xffffff90,0x7bffffff,0x3ffaa000,0xdfffffff, + 0x3ff6e602,0xffffffff,0x33002dff,0x01355555,0x2ea20000,0xfa80009b, + 0xceeeffff,0x7ff4000a,0xffffffff,0xffffffff,0x531006ff,0x98001359, + 0xffffffff,0xffffffff,0x0007ffff,0x02aea600,0x5554c400,0x00009aaa, + 0x56554c40,0x5310001a,0x01357955,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0xfffffff9,0xffffffff, + 0x3ffe21ff,0x2a0000ff,0xffd5ffff,0xddffffff,0xe800579b,0x00ffffff, + 0x3fffffe0,0x7ffffc0f,0xffffffff,0xffffffff,0xffffb4ff,0x7fc00dff, + 0x3fea2fff,0x4c04ffff,0x46ffffff,0x07fffffe,0x3ffffe00,0xfffffd2f, + 0xffff7003,0x7ffdcbff,0xffffffff,0xafffffff,0xfffffffc,0xffffffff, + 0xffff10ff,0x7dc0001f,0xfffd4fff,0xffffffff,0x0017ffff,0x9ffffff5, + 0x3fffee00,0xffff83ff,0xffffffff,0xffffffff,0xfffb4fff,0x2003ffff, + 0x2a2fffff,0x06ffffff,0x7fffffdc,0x7ffffe46,0xff98001f,0xffd0ffff, + 0xf8803fff,0x20ffffff,0xfffffffb,0xffffffff,0xfffcafff,0xffffffff, + 0x20ffffff,0x000fffff,0x53fffee0,0xfffffffe,0xffffffff,0xffe801ff, + 0xf800ffff,0xf07fffff,0xffffffff,0xffffffff,0x29ffffff,0xfffffffd, + 0xfffff005,0x7ffffdc5,0x3ffa00ff,0x7cc7ffff,0x003fffff,0x5fffffc8, + 0x07fffffa,0xffffffb0,0xfffffb85,0xffffffff,0xfcafffff,0xffffffff, + 0xffffffff,0x07ffffe0,0xffffb800,0xffffffd3,0xffffffff,0x9801ffff, + 0x04ffffff,0x7fffffdc,0xffffff02,0xffffffff,0xffffffff,0x3ffff69f, + 0xf801ffff,0x3ee2ffff,0x03ffffff,0xfffffff1,0xffffff0f,0xfffd000b, + 0x7fff47ff,0x3fea01ff,0xfb84ffff,0xffffffff,0xffffffff,0xfffffcaf, + 0xffffffff,0x3fe0ffff,0x20001fff,0xfd3ffffb,0xffffffff,0xffffffff, + 0xffd801df,0x3e00ffff,0x206fffff,0xffffffff,0xffffffff,0x4fffffff, + 0xfffffffb,0xffff009f,0x7fffdc5f,0xff706fff,0x90ffffff,0x00ffffff, + 0xffffff88,0x3fffffa0,0xfffff101,0x3ffee0df,0xffffffff,0x2fffffff, + 0xfffff800,0x3ffffa0f,0x3ff20001,0xffffd2ff,0x7f5ccc1f,0x02ffffff, + 0x7fffffcc,0xfffff704,0x7d40005f,0x2006ffff,0xfffffffd,0x7ffc00ff, + 0x3fff22ff,0xd80fffff,0x7fffffff,0xffffffa8,0x3ffee002,0x7fff46ff, + 0xfffb01ff,0x3ee03fff,0x999dffff,0x99999999,0xfff80009,0x3ffa0fff, + 0x320002ff,0xffd2ffff,0x7dc01fff,0x804fffff,0x0ffffffc,0x5ffffff8, + 0x7ffd4000,0x3f6006ff,0xffffffff,0x7ffffc04,0x3fffff22,0x7fc42fff, + 0x0fffffff,0x7fffffc4,0x3fff6004,0x7fff43ff,0xfffa81ff,0x3ee03fff, + 0x0004ffff,0xfffff000,0x7fffec1f,0x3ff20002,0xffffd1ff,0xfffd801f, + 0xff8805ff,0x7dc5ffff,0x001fffff,0x7ffffd40,0x3fff6006,0x0fffffff, + 0x8bffffe0,0xffeefffd,0x7fffd45f,0xd80ffffd,0x006fffff,0x07fffffe, + 0x83fffffd,0x5ffffff8,0x7ffffdc0,0xf0000004,0x6c1fffff,0x0002ffff, + 0x747ffff6,0x400fffff,0x07fffffb,0xffffff70,0x7fffffc3,0xffa80005, + 0x36006fff,0xffffffff,0x3ffe03ff,0x3fff62ff,0x6c7fffce,0xfffcdfff, + 0xffffb81f,0xff9800ff,0xffe87fff,0x7fec1fff,0x5c00ffff,0x004fffff, + 0xffff0000,0x7ffec1ff,0x0133302f,0x747ffff6,0x400fffff,0x07fffff9, + 0xffffff10,0x3ffffeeb,0xfa80000f,0x2006ffff,0xffdffffd,0x3fe06fff, + 0x3ff62fff,0x2ffffaef,0xf95ffff1,0xff103fff,0x9005ffff,0xd09fffff, + 0x543fffff,0x02ffffff,0x4fffffb8,0xff000000,0x7e41ffff,0xff983fff, + 0xffffb07f,0x3fffffa1,0x7fffdc00,0x3fee005f,0xfff9ffff,0x00004fff, + 0x0dfffff5,0x6ffffec0,0x02fffffb,0x745fffff,0xfff8efff,0x1ffff54f, + 0x203ffff9,0x05fffffe,0x2fffffe8,0x1fffffe8,0xbffffff1,0x3fffee00, + 0x0000004f,0x41ffffff,0xb83ffffc,0xfd82ffff,0xfffd0fff,0xffd801ff, + 0x74004fff,0xffffffff,0x0000ffff,0xdfffff50,0x7fffec00,0x6fffff8d, + 0x45fffff0,0xffb6fffe,0x5bfff2df,0x702ffffc,0x80ffffff,0x07fffff8, + 0x23fffffd,0x0efffffc,0xfffff700,0x20000009,0x20ffffff,0xe83ffffb, + 0xfe84ffff,0x3fffa7ff,0x3ff200ff,0x4001ffff,0xfffffffa,0x0003ffff, + 0x3ffffea0,0x3fff6006,0xfffffb5f,0x5fffff03,0xfbaffffc,0xfffe8fff, + 0x05ffff73,0x3fffffe6,0x3fffea01,0xffffd05f,0xfffff53f,0x7fdc003f, + 0x00004fff,0xffffff00,0x27fffdc1,0x1fffffe2,0xfe9ffffa,0x5440ffff, + 0x4ffffffe,0xffffb000,0x00dfffff,0xffffa800,0x3ff6006f,0xffff35ff, + 0xfffff0bf,0x9affffc5,0xfffcffff,0x7ffff70f,0x7fffffc0,0x3ffff603, + 0xffffd02f,0xfffffd3f,0xfffb8007,0x000004ff,0x1ffffff0,0x227fffd4, + 0x1ffffffa,0xfd3ffff4,0xfdddffff,0xffffffff,0x3e60001d,0xffffffff, + 0x7d400002,0x2006ffff,0x365ffffd,0x7c1fffff,0x3fe2ffff,0x3fffa5ff, + 0x3ee6ffff,0x3f203fff,0x3e06ffff,0xd00fffff,0xffdfffff,0x7000dfff, + 0xffffffff,0xffffffff,0x3fe0009f,0x3ea0ffff,0x7fec4fff,0x7f43ffff, + 0x3fffa6ff,0xffffffff,0x003fffff,0xfffffd80,0x800006ff,0x06fffffa, + 0x97ffff60,0x44fffffa,0xf12fffff,0x7fe4bfff,0x2e3fffff,0x2a03ffff, + 0x80ffffff,0x06fffff9,0x3ffffffa,0x002fffff,0xffffffb8,0xffffffff, + 0xf0004fff,0x4c1fffff,0x7fc4ffff,0x7c6fffff,0x3ffa6fff,0xffffffff, + 0x000adfff,0xfffff880,0x0001ffff,0x7ffffd40,0x3fff6006,0x7ffff45f, + 0x3ffffe0f,0x49ffff12,0xfffffffa,0x13fffea0,0x5ffffff0,0x7fffff90, + 0x7fffff40,0x0fffffff,0x7fffdc00,0xffffffff,0x004fffff,0x1ffffff0, + 0x52ffffcc,0xffffffff,0xd2ffffc1,0xffffffff,0x03dfffff,0x3fff2000, + 0x06ffffff,0x7ffd4000,0x3f6006ff,0x7fdc5fff,0x3ffe4fff,0xffff12ff, + 0xffffff89,0x27fffd46,0x3fffff60,0xfffffe84,0x3ffffa01,0xffffffaf, + 0x7ffdc005,0xffffffff,0x04ffffff,0xffffff00,0x2ffffcc1,0xfffdfff9, + 0x2ffffc7f,0xddfffffd,0xffffffff,0xff980005,0xffffffff,0x2a00002f, + 0x006fffff,0x217ffff6,0xf0ffffff,0x3e65ffff,0x7fec4fff,0x7fd43fff, + 0x7fd405ff,0x7fc47fff,0x7f406fff,0xffb9ffff,0x2002ffff,0xfffffffb, + 0xffffffff,0xff0004ff,0x7c41ffff,0x3ffe5fff,0x25ffff9f,0x3fa4ffff, + 0xf510ffff,0x01ffffff,0x7fffec00,0xffffffff,0xff500000,0x6c00dfff, + 0xfc85ffff,0xfff3ffff,0x3ffe65ff,0x7fffdc4f,0x7fffd41f,0x7fffc405, + 0x3ffea1ff,0x7ff404ff,0xfffd1fff,0x2e001fff,0x004fffff,0xffff0000, + 0x7ffc41ff,0x2ffff36f,0xf88ffffd,0x3ffa4fff,0x7fcc0fff,0x0005ffff, + 0xbffffff5,0x09ffffff,0x3ffea000,0x3f6006ff,0xff885fff,0xfff8efff, + 0xffff52ff,0x6ffff887,0x05ffff98,0x3fffffe8,0x07fffff2,0x3fffffd0, + 0x3fffffe6,0xffff7005,0x0000009f,0x03fffffe,0x3f2dffff,0xffff74ff, + 0x49ffff15,0x80fffffe,0x1ffffffb,0xffffe800,0xfffffd6f,0xf500001f, + 0x400dffff,0xb05ffffd,0xff5fffff,0x3fea5fff,0xfffe83ff,0x6ffff984, + 0xfffffb80,0x1fffffe6,0x3fffffa0,0x3fffff61,0xfffb802f,0x000004ff, + 0x7fffff88,0xfd7ffff8,0x3ffe65ff,0x3ffff9df,0x03fffffa,0x2ffffff4, + 0x3fffee00,0xffff52ff,0x50000bff,0x00dfffff,0x82ffffec,0xfdfffff9, + 0xff72ffff,0x999507ff,0xdffff301,0xfffff300,0xfffff31f,0xffffd00b, + 0x7fffc43f,0x7dc00fff,0x0004ffff,0xffff9800,0xfffff86f,0x3a0ffff8, + 0xfff9ffff,0x3ffffa3f,0xffff700f,0x3e2003ff,0x746fffff,0x02ffffff, + 0x7fffd400,0x3ff6006f,0x3ff605ff,0xffffffff,0x07ffff72,0x3fffe600, + 0xffffd007,0xfffff75f,0xffffd005,0xffffb83f,0x7fdc05ff,0x00004fff, + 0xfffffb80,0xbffffe85,0x7fe45fff,0x2ffffbff,0x03fffffa,0x7fffffc4, + 0xffff9005,0xfff985ff,0x40006fff,0x06fffffa,0x17ffff60,0xffffffa8, + 0xff72ffff,0x220005ff,0x9007ffff,0xfb9fffff,0xd001ffff,0xd03fffff, + 0x07ffffff,0x27ffffdc,0x8800b800,0x84ffffff,0xffdffffe,0x7fffcc2f, + 0x3a2ffffd,0x200fffff,0x0ffffffc,0x7ffffc40,0xffffb06f,0x540007ff, + 0x006fffff,0x017ffff6,0xfffffffd,0x3fff25ff,0xff10002f,0x3e600fff, + 0xfffeffff,0xffd005ff,0xff303fff,0x201fffff,0x04fffffb,0x2039fb00, + 0xffffffe9,0xfffffd82,0xffe80fff,0x21ffffff,0x00fffffe,0x3fffffe2, + 0x7fffec04,0xfff301ff,0x0001ffff,0x1bffffea,0x5ffffd80,0x7ffffdc0, + 0xff92ffff,0x220005ff,0x000fffff,0xffffffff,0x3a007fff,0x901fffff, + 0x0bffffff,0x13ffffee,0x7fffec00,0xffffdccd,0xffb05fff,0x20bfffff, + 0xfffffffc,0x3ffffa1f,0x7ffec00f,0xff300fff,0xd80bffff,0x04ffffff, + 0xfffff500,0x7ffec00d,0xffff805f,0xfb2fffff,0x20005fff,0x00fffff8, + 0xffffffb0,0x2001ffff,0x01fffffe,0x3ffffffa,0xfffffb83,0xfffb0004, + 0xffffffff,0x3201ffff,0x3fffffff,0xffffff30,0x7fff41ff,0x7fd400ff, + 0xfd04ffff,0x803fffff,0xfffffff9,0xfffa8001,0x3f6006ff,0xfc805fff, + 0x2fffffff,0x003ffffb,0x07ffffc0,0xfffffa80,0x2006ffff,0x01fffffe, + 0x3fffffea,0x7fffdc0f,0xffb0004f,0xffffffff,0x6407ffff,0x0fffffff, + 0x3fffffe0,0x3fffa0ff,0xffe800ff,0x7d40ffff,0x005fffff,0xbffffff9, + 0xffff5000,0x7fec00df,0xff8805ff,0xb2ffffff,0x0003ffff,0x00fffffc, + 0xffffff88,0x3a004fff,0x401fffff,0x6ffffffd,0x27ffffdc,0xffffd800, + 0xffffffff,0x7ffe401e,0x7e406fff,0x20ffffff,0x00fffffe,0xffffffb8, + 0x7fffff43,0xfff1001f,0x8005ffff,0x06fffffa,0x17ffff60,0x7ffffec0, + 0xffffd2ff,0x7ffc0003,0x3f6001ff,0x1fffffff,0x3ffffa00,0x7ffc401f, + 0x3ee3ffff,0x0004ffff,0x3fffff6a,0x7002efff,0x07ffffff,0xffffffa8, + 0x7fffff47,0xfffff000,0x7fffdcff,0x7e4005ff,0x006fffff,0x37ffffd4, + 0xbffffb00,0x3fffe600,0xfffd2fff,0x7fc0003f,0x2e002fff,0x7fffffff, + 0x7ffff400,0xfffb801f,0xff71ffff,0x00009fff,0x0026aa66,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0xffffc800,0xfa8000ff,0x7fc7ffff,0xffffffff, + 0xffffffff,0xfff95fff,0x7f4005ff,0x5400ffff,0xff02ffff,0x3fee0dff, + 0xffffffff,0xffffffff,0xffffffd5,0x3579dfff,0xffff8800,0x7f40006f, + 0xffffffff,0x001bcdee,0xfffff900,0x6c001fff,0xffffffff,0x009accef, + 0x7ffffc40,0xffe8004f,0x7ffc3fff,0xffffffff,0xffffffff,0xffff95ff, + 0x7ff4005f,0x7dc00fff,0xfff01fff,0x3ffee0bf,0xffffffff,0x5fffffff, + 0xfffffffd,0xffffffff,0xfff10019,0xe8000dff,0xffffffff,0xefffffff, + 0x3fa0000b,0x2fffffff,0x3ffff600,0xffffffff,0x2000cfff,0x0ffffffc, + 0x3fffea00,0xfffff87f,0xffffffff,0xffffffff,0x5fffff95,0x7ffff400, + 0x7ffe400f,0xffff881f,0xfffff704,0xffffffff,0x3abfffff,0xffffffff, + 0xffffffff,0x7ffc402f,0x740006ff,0xffffffff,0xffffffff,0xf88000ef, + 0xffffffff,0x3fff6004,0xffffffff,0x04ffffff,0xffffff10,0x7fff4007, + 0xffff83ff,0xffffffff,0xffffffff,0xfffff95f,0x7fff4005,0x7fe400ff, + 0xfff980ff,0xffff703f,0xffffffff,0x2bffffff,0xfffffffe,0xffffffff, + 0xf100efff,0x000dffff,0xffffffe8,0xffffffff,0x8006ffff,0xfffffffb, + 0x3f6007ff,0xffffffff,0xffffffff,0xfff9005f,0x3ea00fff,0xff06ffff, + 0xffffffff,0xffffffff,0x3ff2bfff,0x3a002fff,0x400fffff,0xf507fffd, + 0x3ee07fff,0xffffffff,0xffffffff,0xfffffd5f,0xffffffff,0x0dffffff, + 0x1bffffe2,0xffffd000,0xfffddddf,0x9fffffff,0xffffd800,0x01ffffff, + 0xffffffb0,0xffffffff,0x007fffff,0x7ffffff1,0xfffffd00,0x33333207, + 0xcccccccc,0xfffffffc,0x5fffff92,0x7ffff400,0x7fff400f,0x5ffff707, + 0x3ffffee0,0x9999999d,0xfd099999,0x3333ffff,0xfffffb75,0xff107fff, + 0x8000dfff,0x00fffffe,0xffffffb5,0xffff800d,0x3fffffff,0xfffffb00, + 0xfffba985,0x801fffff,0x06fffffc,0x37ffffd4,0x3fee0000,0x3f25ffff, + 0x2002ffff,0x00fffffe,0xb837fffc,0xf701ffff,0x0009ffff,0x07fffff4, + 0xfffffd10,0xfff881ff,0x740006ff,0x400fffff,0x0ffffffd,0xfffff500, + 0x0dfffffb,0x3fffff60,0x3fff2202,0xf8805fff,0x202fffff,0x02fffffe, + 0x3ffe2000,0x3f20ffff,0x2002ffff,0x20fffffe,0xfff99998,0xd99999df, + 0x999affff,0x9fffff70,0x7fff4000,0xffc800ff,0x7c44ffff,0x0006ffff, + 0x07fffff4,0x3ffffe20,0xfff9001f,0xfffff1ff,0xfffb001f,0xffd005ff, + 0x3200dfff,0x506fffff,0x00dfffff,0xffffe800,0x7ffe42ff,0x3fa002ff, + 0x3f60ffff,0xffffffff,0xffffffff,0x73ffffff,0x009fffff,0x7fffff40, + 0xffffd000,0x7ffc41ff,0x740006ff,0x800fffff,0x01ffffff,0x2bffffd0, + 0x02fffffd,0x2fffffd8,0xfffff980,0xfff8800f,0xffe82fff,0x00002fff, + 0x3fffffee,0xfffffc84,0x3fffa002,0x3fff60ff,0xffffffff,0xffffffff, + 0xff73ffff,0x40009fff,0x00fffffe,0xffffff70,0x7ffffc47,0x7ff40006, + 0xff800fff,0x9800ffff,0xf73fffff,0xb00bffff,0x005fffff,0x3ffffff1, + 0x3ffff200,0x7fffd46f,0x2200006f,0x0fffffff,0x2fffffc8,0x3ffffa00, + 0x3ffff60f,0xffffffff,0xffffffff,0xfff73fff,0x740009ff,0x000fffff, + 0x9ffffff1,0x37ffffc4,0x3fffa000,0x7fcc00ff,0xf7006fff,0x3e63ffff, + 0xd807ffff,0x002fffff,0x05fffffd,0x3ffffe20,0x3ffffa1f,0x3a00002f, + 0x02ffffff,0x05fffff9,0x7fffff40,0x3fffff60,0xffffffff,0xffffffff, + 0xffff73ff,0x7f40009f,0x2000ffff,0x26fffffd,0x06fffff8,0x7ffff400, + 0x7fff400f,0xffb003ff,0xffff8fff,0x7fec01ff,0xff002fff,0x4003ffff, + 0x35fffffc,0x00dfffff,0x7fffdc00,0x3ff204ff,0x3a002fff,0x220fffff, + 0xffffc999,0xffa9999a,0x09999dff,0x09fffff7,0x7ffff400,0x3ff2000f, + 0x3fe27fff,0x40006fff,0x00fffffe,0xdfffffd3,0x3fffe200,0x7fffe44f, + 0x7ffec04f,0xff8802ff,0x44007fff,0xd8ffffff,0x002fffff,0xfffff100, + 0x7fe401df,0xffffffff,0xffffffff,0x3200ffff,0xf980ffff,0x3ee03fff, + 0xeeefffff,0xeeeeeeee,0xfffffd0e,0x7ffdc001,0x3ffe27ff,0x740006ff, + 0xeeefffff,0xffffffee,0xff5000ef,0xffa85fff,0x7ec06fff,0xb802ffff, + 0x006fffff,0xdfffffc8,0x006fffff,0x3ffffa00,0x7fe401ff,0xffffffff, + 0xffffffff,0x3600ffff,0xff507fff,0x7fdc07ff,0xffffffff,0xffffffff, + 0x1fffffd0,0x7fffd400,0xffff10ff,0xfe8000df,0xffffffff,0x3fffffff, + 0x7fffe400,0x7fffc40f,0x3ff600ff,0x7c402fff,0x005fffff,0xffffff88, + 0x002fffff,0xfffff700,0xfff9009f,0xffffffff,0xffffffff,0x7f401fff, + 0xfff706ff,0x7ffdc05f,0xffffffff,0x0fffffff,0x01fffffd,0x7ffffcc0, + 0xfffff10f,0xffe8000d,0xffffffff,0x2dffffff,0x3ffffe00,0xfffffd06, + 0x7fffec07,0x3ffa602f,0x0001ffff,0xfffffff9,0x20000dff,0x6ffffff8, + 0xfffff900,0xffffffff,0xffffffff,0x7fffc01f,0x3ffff706,0x7ffffdc0, + 0xffffffff,0xfd0fffff,0x4001ffff,0x0ffffff9,0x0dfffff1,0xffffe800, + 0xffffffff,0x0dffffff,0x7ffffcc0,0xfffff904,0x7fffec0b,0xdba999bf, + 0x3fffffff,0x3ffe2000,0x02ffffff,0xffffb000,0x3f2003ff,0xffffffff, + 0xffffffff,0x200fffff,0xf905ffff,0x7dc01fff,0xffffffff,0xffffffff, + 0xfffffd0f,0x7ffd4001,0x3ffe27ff,0x740006ff,0xeeefffff,0xfffffffe, + 0x7e406fff,0xf301ffff,0x6c0fffff,0xffffffff,0xffffffff,0xc80006ff, + 0x6fffffff,0xfff70000,0x64009fff,0x99bfffff,0x99999999,0x00fffffe, + 0x209ffff1,0x5c07fffd,0x004fffff,0x3fffffa0,0x3ffee000,0x3ffe26ff, + 0x740006ff,0x300fffff,0xfffffff9,0x7ffff409,0x7ffffc07,0xffffb02f, + 0xffffffff,0x01dfffff,0xffff1000,0x00005fff,0xdffffff1,0xffffc800, + 0x3ffa002f,0xdddb0fff,0xdddffffd,0xfffffddd,0x7dc1dddd,0x0004ffff, + 0x03fffffa,0xfffffc80,0x3ffffe24,0x7ff40006,0x7c400fff,0x80ffffff, + 0x05fffff8,0x27ffffec,0xffffffd8,0xffffffff,0x400003ff,0x06fffffc, + 0xffffb000,0xfc8003ff,0x2002ffff,0xf0fffffe,0xffffffff,0xffffffff, + 0x1fffffff,0x27ffffdc,0xffffd000,0x7fec001f,0x3fe23fff,0x40006fff, + 0x00fffffe,0xffffff98,0xfffffb81,0x9999999c,0x07fffffc,0xfffffffb, + 0x9fffffff,0xf5000001,0x000bffff,0xffffff70,0xfff90007,0x7f4005ff, + 0xfff0ffff,0xffffffff,0xffffffff,0x5c1fffff,0x004fffff,0x3fffffa0, + 0xffff1000,0x7ffc45ff,0x740006ff,0x000fffff,0x07ffffff,0xfffffffb, + 0xffffffff,0xb03fffff,0xdddfffff,0x0001359b,0xffffa800,0x7c40005f, + 0x006fffff,0x5fffff90,0x7ffff400,0xffffff0f,0xffffffff,0xffffffff, + 0x7ffdc1ff,0x3a0004ff,0x000fffff,0x1ffffff9,0x37ffffc4,0x3fffa000, + 0xffd000ff,0xfff07fff,0xffffffff,0xffffffff,0xfffb07ff,0x000005ff, + 0x7fffd400,0x7ec0005f,0x001fffff,0x5fffff90,0x7ffff400,0xfd99990f, + 0x99999fff,0x99bffffb,0x7ffdc199,0x3a0004ff,0x800fffff,0x4ffffff8, + 0x37ffffc4,0x3fffa000,0xff8800ff,0x7cc2ffff,0xffffffff,0xffffffff, + 0xfd85ffff,0x0002ffff,0x3fea0000,0x20005fff,0x3ffffffb,0x3fff2000, + 0x3fa002ff,0xfb00ffff,0x3fea0fff,0x7fdc02ff,0x20004fff,0x00fffffe, + 0x7ffffec4,0x7fffc40f,0x7f40006f,0xb800ffff,0x40ffffff,0xfffffffc, + 0xffffffff,0x0fffffff,0x17ffffec,0x50000000,0x00bfffff,0x3ffffe20, + 0x7e40006f,0x2002ffff,0x00fffffe,0x2e0dfffd,0x5c01ffff,0x004fffff, + 0x3fffffa0,0x3fffa600,0xff883fff,0x40006fff,0x00fffffe,0x7fffffcc, + 0xfffffe87,0xeeeeeeee,0xfffffeee,0x7fffec2f,0x0000002f,0x3ffffea0, + 0xfffb0005,0x55559fff,0x55555555,0x3ffff255,0x3ffa002f,0xfff00fff, + 0x3fff20bf,0x7ffdc01f,0x3a0004ff,0x220fffff,0xfffffdba,0xff880fff, + 0x9999ffff,0x99999999,0xfffffd09,0xfff93101,0xf88bffff,0x4004ffff, + 0x44fffffd,0x02fffffd,0x2a000000,0x005fffff,0xffffffa8,0xffffffff, + 0x7fffffff,0x05fffff9,0x7fffff40,0x5ffff880,0x01ffff90,0xffffffb8, + 0xffffffff,0xffd5ffff,0xffffffff,0xffffffff,0x3ffe205f,0xffffffff, + 0xffffffff,0xffffffd2,0xffffffff,0x81dfffff,0x02fffffb,0x7ffffdc0, + 0x7ffffec7,0x00000002,0x17ffffea,0x3fffee00,0xffffffff,0xffffffff, + 0xfffff97f,0x7fff4005,0xfff980ff,0xffffb04f,0xfffff700,0xffffffff, + 0x3abfffff,0xffffffff,0xffffffff,0x3fe202ff,0xffffffff,0xffffffff, + 0xfffffd2f,0xffffffff,0x03ffffff,0x01fffffb,0xfffff980,0x3ffff61f, + 0x0000002f,0x3ffffea0,0xfffb8005,0xffffffff,0xffffffff,0xffff97ff, + 0x7ff4005f,0xff980fff,0xfffd03ff,0xffff700d,0xffffffff,0x2bffffff, + 0xfffffffe,0xffffffff,0x7fc401ef,0xffffffff,0xffffffff,0xfffffd2f, + 0xffffffff,0x105fffff,0x00bfffff,0x3fffffe0,0x3fffff64,0x00000002, + 0x17ffffea,0x3fffee00,0xffffffff,0xffffffff,0xfffff97f,0x7fff4005, + 0xfffa80ff,0xdffff02f,0xfffff700,0xffffffff,0x3abfffff,0xffffffff, + 0x2effffff,0xfffff100,0xffffffff,0x25ffffff,0xfffffffe,0xffffffff, + 0x3ffea02e,0xf90003ff,0x7ecdffff,0x0002ffff,0x3fea0000,0xb8005fff, + 0xffffffff,0xffffffff,0xf97fffff,0x4005ffff,0x80fffffe,0x881ffffb, + 0xb805ffff,0xffffffff,0xffffffff,0xffffd5ff,0x9ddfffff,0xff880015, + 0xffffffff,0xffffffff,0xfffffd2f,0x9bdfffff,0xfff90037,0x2a0003ff, + 0xb0ffffff,0x005fffff,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x7fffd400,0xffffffff, + 0x6fffffff,0xfffffff5,0xffffffff,0x0bffffff,0x7ffff400,0x00004fff, + 0x00000000,0x00266000,0x00260000,0x00099800,0x999a9800,0x54cc0000, + 0x00000009,0xffffffa8,0xffffffff,0xf56fffff,0xffffffff,0xffffffff, + 0x000bffff,0x3fffffee,0x5d1004ff,0x80000000,0x5c4004d8,0xdfffffed, + 0x2a20000c,0xfffffedb,0xca800bde,0xcdfffffe,0x7f644000,0xffffffff, + 0x7f5cc04e,0xefffffff,0x7e44001d,0x7fd402df,0xffffffff,0xffffffff, + 0xfffff56f,0xffffffff,0xffffffff,0xfff1000b,0x09ffffff,0x007ffd10, + 0x3a200000,0xff7004ff,0xffffffff,0xf50007ff,0xffffffff,0x4405ffff, + 0xfffffffd,0x8802ffff,0xfffffffc,0x07ffffff,0xfffffff5,0xffffffff, + 0x3ffa003b,0x3ea04fff,0xffffffff,0xffffffff,0xffff56ff,0xffffffff, + 0xffffffff,0xffb000bf,0x9fffffff,0xffffe880,0x40000004,0x04fffff9, + 0x3fffff62,0xffffffff,0xfd8801ef,0xffffffff,0x302fffff,0xfffffffd, + 0x1bffffff,0x3ffffa20,0xffffffff,0xfff507ff,0xffffffff,0x01ffffff, + 0xffffffa8,0xffff502f,0xffffffff,0xdfffffff,0x3fffffea,0xffffffff, + 0x5fffffff,0x7fffcc00,0x04ffffff,0x7ffffff4,0x8000000d,0xfffffffa, + 0xfffff883,0xffffffff,0x4c06ffff,0xffffffff,0xffffffff,0xfffffa82, + 0xffffffff,0xffd04fff,0xffffffff,0x20ffffff,0xfffffffa,0xffffffff, + 0x7fe405ff,0x005fffff,0x5fffff98,0xeeeeea80,0xeeeeeeee,0xffffffee, + 0x7fff4004,0x4fffffff,0x7ffffd40,0x00000eff,0x3fffff20,0xfffb05ff, + 0xffdfffff,0x7fffffff,0x7fffff40,0xffffffff,0xffe82fff,0xa99aefff, + 0x1ffffffe,0x7fffffe4,0xb75331bd,0x3ffea0ff,0xba99aacd,0x2fffffff, + 0x3fffff20,0x4c000fff,0x005fffff,0x7ffd4000,0x2e000fff,0xffcfffff, + 0xe9804fff,0x1fffffff,0xffd80000,0x304fffff,0x5dffffff,0x7fffdc41, + 0xffb80fff,0x0acfffff,0x70bfae62,0x409fffff,0x46fffffc,0x06fffffe, + 0x056d4020,0x7ffff440,0x3ffea04f,0x001fffff,0x2fffffcc,0x3fa00000, + 0x2005ffff,0x8efffff8,0x004fffff,0xffffffb1,0x2200007f,0xfffffffe, + 0x3ffffa02,0x3fe600ef,0x7cc5ffff,0x02ffffff,0x7ffc4130,0xffe805ff, + 0x3ffe2fff,0x00002fff,0xffff3000,0xfffd80bf,0x4002ffff,0x05fffff9, + 0x3fea0000,0x2001ffff,0x89fffffd,0x004fffff,0x7fffffe4,0x74c0004f, + 0x1effffff,0x3ffffea0,0xfffc800f,0x7ffec7ff,0x20001fff,0x01fffffc, + 0x3fffffa8,0x7ffffff1,0x40000000,0x807fffff,0x1ffffffe,0x7fffcc00, + 0x2000005f,0x05fffffe,0x3ffffea0,0x9fffff14,0xffff7000,0x0001bfff, + 0xfffffff5,0xfffc801d,0xff1005ff,0x7fc1ffff,0x0004ffff,0x03fffff4, + 0x4fffff98,0x3ffffffe,0x0000000b,0x07ffffe8,0x7fffff98,0xffff9800, + 0x5000005f,0x03ffffff,0x37ffff40,0x09fffff1,0x3fffea00,0x2000efff, + 0xfffffffb,0xffffb004,0x7ff4005f,0xfff11fff,0x80001fff,0x99efffff, + 0x99999999,0x365fffff,0xffffffff,0x2000001c,0xffff9999,0xffff007f, + 0xff3000df,0x0000bfff,0x3fffffa0,0x3fff2005,0x3ffe21ff,0x260004ff, + 0xfffffffe,0xffffc801,0x3a003fff,0x000fffff,0x4ffffff6,0x07fffffa, + 0x7fffc400,0xffffffff,0xffffffff,0x3fffe67f,0xcfffffff,0xdb910001, + 0xffffffff,0xf100ffff,0x0009ffff,0x0bfffff3,0xfff50000,0x22003fff, + 0x445fffff,0x004fffff,0x7fffec40,0xfb102fff,0x05ffffff,0xffffff80, + 0x3fff2000,0xffff74ff,0xf98000df,0xffffffff,0xffffffff,0x7e47ffff, + 0xffffffff,0x800befff,0xffffffd9,0xffffffff,0xfffb807f,0xf98000ff, + 0x0005ffff,0xfffffd80,0x3fff6006,0x7ffc40ff,0x900004ff,0x7fffffff, + 0xfffffe88,0x7c4000ef,0x4007ffff,0xb5fffffb,0x00bfffff,0xfffffa80, + 0xffffffff,0xffffffff,0xfffffa87,0xffffffff,0x3fff601e,0xffffffff, + 0x07ffffff,0x17ffffdc,0xffff9800,0x4c00005f,0x02ffffff,0x5fffff50, + 0x9fffff10,0x7fdc0000,0xf34fffff,0x1dffffff,0xffff1000,0xffc800ff, + 0xfff94fff,0xb8000bff,0xffffffff,0xffffffff,0x106fffff,0xfffffff9, + 0x05ffffff,0xfffffff9,0xffffffff,0x554cffff,0x5ffffffc,0x3ffe6000, + 0x400005ff,0x06fffffd,0xbfffff10,0x3ffffe20,0xfd100004,0x41dfffff, + 0xfffffffb,0xffff0004,0x7e4001ff,0xff72ffff,0x8000ffff,0x9dfffff9, + 0x99999999,0x00999999,0xfffffc98,0x20ffffff,0xfffffffa,0xfffe809b, + 0x3ffffa7f,0x000dffff,0x3ffffe60,0x3e600005,0x002fffff,0x01fffff9, + 0x13ffffe2,0x3ffea000,0xa80dffff,0xdfffffff,0x7fff4000,0x3fa001ff, + 0xff51ffff,0x0001ffff,0x2fffffc4,0x26000000,0xfffffffc,0x3ffff63f, + 0xfffe806f,0x3ffffa7f,0x80001eff,0x05fffff9,0x3fff6000,0xff3006ff, + 0x7c407fff,0x0004ffff,0x7fffffdc,0x7ffcc04f,0x000effff,0x13fffff6, + 0x7ffffc40,0xfffff10f,0xff80009f,0x00007fff,0xfffb1000,0x7ffc9fff, + 0xfe801fff,0x3ffa7fff,0x00002eff,0x17ffffe6,0x7ffcc000,0xfd003fff, + 0xf880dfff,0x0004ffff,0x3ffffff2,0xffd1003f,0x005fffff,0x3ffffff2, + 0xffffc800,0x7ffffc7f,0x3a0000ff,0x002fffff,0x3fa00000,0xff36ffff, + 0xf100ffff,0x55cfffff,0x30000009,0x00bfffff,0x3ffff600,0xfff7006f, + 0xff8803ff,0x88004fff,0xfffffffe,0x7fec4002,0x803fffff,0x4ffffffa, + 0x7ffffcc0,0x7fffec3f,0x82001eff,0x0ffffffc,0xb0000000,0x269fffff, + 0x01ffffff,0x3fffffe6,0x40000007,0x05fffff9,0xffff8800,0xfff003ff, + 0xdddddfff,0xffffdddd,0x05ddddff,0x7fffff4c,0x320001ef,0x4fffffff, + 0xfffffd80,0xfffa80df,0xff886fff,0x0bffffff,0x7c47d730,0x01efffff, + 0x01c88620,0x3ffffea0,0xfffff12f,0x3ffea09f,0x3f67ffff,0xffffffff, + 0x001fffff,0x0bfffff3,0xffff9000,0x7ffc00ff,0xffffffff,0xffffffff, + 0x03ffffff,0xfffffff5,0xf700001d,0x1bffffff,0x7ffffcc0,0xffdcefff, + 0x02ffffff,0xfffffff7,0xffdddfff,0xfffb87ff,0x9abdffff,0x4ffdbaa9, + 0x2ab7ffe2,0x3ffee609,0x3fe0ffff,0x9bdfffff,0xffffffeb,0x3fffa7ff, + 0xffffffff,0xf3001fff,0x000bffff,0xffffff88,0x3fffe003,0xffffffff, + 0xffffffff,0xb83fffff,0x5fffffff,0x7fcc0000,0x01efffff,0x3ffffff2, + 0xffffffff,0x7f405fff,0xffffffff,0x3fffffff,0xffffffe8,0xffffffff, + 0x3fe24fff,0xffffffff,0xffffffff,0x7ffffdc5,0xffffffff,0x27ffffff, + 0xfffffffe,0x1fffffff,0xfffff300,0xffc8000b,0x2000ffff,0xffffffff, + 0xffffffff,0xffffffff,0x7fffec3f,0x00003fff,0xfffffd10,0x3f6205ff, + 0xffffffff,0x04ffffff,0xfffffd88,0xffffffff,0xffe883ff,0xffffffff, + 0x24ffffff,0xfffffff8,0xffffffff,0xfffd05ff,0xffffffff,0xfffff3df, + 0x7ffffff4,0xffffffff,0xffff3001,0x7c4000bf,0x004fffff,0x7ffffffc, + 0xffffffff,0xffffffff,0x3fffa3ff,0x0002ffff,0x7ffec400,0x2a02ffff, + 0xffffffff,0x002fffff,0x7fffffd4,0xffffffff,0x3fffee03,0xffffffff, + 0x3fe24fff,0xffffffff,0x04ffffff,0x3fffffe6,0x88dfffff,0x3fa7ffff, + 0xffffffff,0x001fffff,0x0bfffff3,0x7fffe400,0x664000ff,0xcccccccc, + 0xfffdcccc,0x1cccceff,0x3fffffee,0x20000001,0x0efffffc,0x7fff6440, + 0x00ceffff,0x3fffae00,0x2cefffff,0xffffd880,0xefffffff,0x3ffb621c, + 0xffffffff,0xc8800bef,0xdfffffff,0x9ffffe22,0xaaaaaaa9,0x0aaaaaaa, + 0xfffff300,0x3fe2000b,0x0004ffff,0x3ffe6000,0xffb804ff,0x000000ef, + 0x0efffb80,0x55d4c400,0x31000001,0x00013355,0xaabcca98,0x2aaa6001, + 0x0019abcb,0x15595310,0x40000000,0xfffffffa,0xffffffff,0x3206ffff, + 0x00ffffff,0x3e600000,0x7004ffff,0x000001bf,0x0077d400,0x00000000, + 0x00000000,0x00000000,0x00000000,0x3ffffea0,0xffffffff,0x06ffffff, + 0x9ffffff1,0x98000000,0x004fffff,0x0000000a,0x000004c0,0x00000000, + 0x00000000,0x00000000,0x54000000,0xffffffff,0xffffffff,0xff706fff, + 0x0001ffff,0xfff98000,0x000004ff,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x3ffffea0,0xffffffff,0x06ffffff,0x0bffffff, + 0xf3000000,0x0009ffff,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x7ffd4000,0xffffffff,0xffffffff,0xfffffb86,0x0000001f, + 0x4fffff98,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x000054c4,0x31004cc4,0x26200001, + 0xeeeb800a,0xeed801ee,0xddd30eee,0x70003ddd,0x009ddddd,0x01333330, + 0xeeeeea80,0x3bae004e,0x3bb25eee,0x440005ee,0x3a0eeeee,0xeeeeeeee, + 0xeeeeeeee,0x553003ee,0x75c00155,0x7ed44eee,0x701dffff,0x7fdcbddd, + 0x7fec44ff,0xeeeb83ff,0x7fff543e,0xff901dff,0xfd003fff,0x7f41ffff, + 0x8005ffff,0x03fffffe,0x3fffff80,0xffffd800,0xff9802ff,0x3f22ffff, + 0x40007fff,0x7c7ffff9,0xffffffff,0xffffffff,0xffb004ff,0x7e4003ff, + 0xffb16fff,0x7fffffff,0x32dfff90,0x13ffffff,0x9ffffffd,0x14ffffc8, + 0xfffffffb,0xfff907ff,0xffd003ff,0x7fdc1fff,0x2000ffff,0x0ffffff9, + 0xfffff800,0xfff88003,0x7400ffff,0x5c5fffff,0x000fffff,0x1ffffea0, + 0xffffffff,0xffffffff,0x32009fff,0x2000ffff,0xe8fffffc,0xffffffff, + 0x7fe44fff,0xfffff9ef,0xffffb6ff,0x7e41ffff,0xfff8cfff,0xffffffff, + 0x7fffe43f,0xfffe801f,0x3ffe20ff,0x32002fff,0x005fffff,0x07fffff0, + 0x3fffea00,0x3ff205ff,0x7d40ffff,0x0001ffff,0xf17fffee,0xffffffff, + 0xffffffff,0xf70089ff,0x64020fff,0xffdfffff,0xffffffff,0x3ff20fff, + 0xfffffeff,0xffffcfff,0x323fffff,0xffedffff,0xffffffff,0x7ffe47ff, + 0xffe801ff,0x7fec0fff,0x3e005fff,0x002fffff,0x07fffff0,0x7fffe400, + 0xfff983ff,0xff981fff,0x20002fff,0x7c4ffffc,0xffffffff,0xffffffff, + 0x2076c3ff,0xfb87fffb,0xfffffc81,0xedffffff,0x23ffffff,0xfffffffc, + 0xffffffdc,0xffffebff,0x3fffff25,0xfeffffff,0x23ffffff,0x01fffffc, + 0x0fffffe8,0x7fffffd4,0xffff9800,0x3fe0006f,0x40003fff,0x0ffffffe, + 0x27fffff4,0x07fffff0,0x7fffec00,0x4cccccc3,0xffb99999,0x7cc5ffff, + 0x3ffea2ff,0x21bff626,0xfffffffc,0x7ffec2ef,0x3fff26ff,0x3ffe2fff, + 0xff50efff,0x7ffe4dff,0x0befffff,0xbfffffd5,0x0fffffe4,0x7fffff40, + 0xffffff80,0xffffc803,0x3fe0003f,0x40003fff,0x6ffffff9,0x1bfffff2, + 0x09ffffd0,0x7fffec00,0xfff10002,0xfe81ffff,0xfff34fff,0x3ffffe6b, + 0x7ffffe42,0xfff105ff,0x7ffe4fff,0x7fff45ff,0x3ffe22ff,0x3ffff27f, + 0xff505fff,0x7fe4dfff,0xfe801fff,0xfb80ffff,0xf806ffff,0x000fffff, + 0x0fffffe0,0x3ffee000,0xfff9bfff,0x7ec01fff,0xffc85fff,0xfffe81ff, + 0xffd0001f,0xfb83ffff,0xfaefffff,0xffffcdff,0x7ffe46ff,0x7f406fff, + 0xff90ffff,0xffe83fff,0x7ffc46ff,0x3ffff27f,0xff100eff,0x7fe4ffff, + 0xfe801fff,0xf880ffff,0x201fffff,0x05fffffa,0x7ffffc00,0xffb00003, + 0xfffdffff,0xff9007ff,0xfffd0dff,0xfffff09f,0xfffb0001,0x3ae07fff, + 0xffffffff,0xffffffff,0x7fffe41d,0x7fec00ff,0xfff91fff,0xffffb0bf, + 0x7ffff887,0x3bfffff2,0x7ffff400,0xfffff90f,0xffffd003,0x3fff601f, + 0x3ff604ff,0x40002fff,0x003fffff,0xfffff100,0x0dffffff,0x1ffffee0, + 0x8ffffff3,0x007ffff8,0xffffffb8,0xfffea805,0xffffffff,0xfff900cf, + 0xdd7007ff,0x3ff23ddd,0xfffd84ff,0x7fffc41f,0x3fffff27,0xffffe802, + 0xfffff90f,0xffffd003,0x3ffea01f,0xfff107ff,0x77440fff,0xfeeeeeee, + 0xeeeeffff,0x003eeeee,0xfffffff5,0x2a001fff,0x320fffff,0x21ffffff, + 0x006ffff9,0x7fffffcc,0x3f66000e,0xbfffffff,0x7fffe400,0xfc80003f, + 0xffd84fff,0x7ffc41ff,0x3ffff27f,0xfffe802f,0xffff90ff,0xfffd003f, + 0x7ffc01ff,0xffb82fff,0x3e204fff,0xffffffff,0xffffffff,0x04ffffff, + 0x3fffff20,0x26003fff,0x3a1fffff,0x24ffffff,0x005ffff9,0x3fffffe2, + 0x7e4c001f,0x2effffff,0xfffffc80,0xffc80003,0xfffd84ff,0x7fffc41f, + 0x3fffff27,0xffffe802,0xfffff90f,0xffffd003,0x7ffe401f,0xfffe85ff, + 0x3fe200ff,0xffffffff,0xffffffff,0x004fffff,0x3fffffe2,0xfff8007f, + 0xffff32ff,0x7fd4ffff,0x3f6004ff,0x002fffff,0x3fffff66,0xbfffffff, + 0xfffff900,0xff900007,0xfffb09ff,0xffff883f,0x3fffff27,0xffffe802, + 0xfffff90f,0xffffd003,0x7ffc401f,0x3fe60fff,0x7c406fff,0xffffffff, + 0xffffffff,0x04ffffff,0x3fffff20,0x74003fff,0xff93ffff,0x25ffffff, + 0x002ffffb,0x9ffffff9,0x3fffaa00,0xffffffff,0x40cfffff,0x03fffffc, + 0xffffc800,0x1ffffd84,0x93ffffc4,0x005fffff,0x21fffffd,0x01fffffc, + 0x0fffffe8,0x7ffffec0,0x3fffff22,0x7fffc402,0xffffffff,0xffffffff, + 0xf5004fff,0xffffffff,0x7fec003f,0xdfffd4ff,0x3f2bffff,0xfa801fff, + 0x006fffff,0xfffffff7,0xffbbfff7,0xfc8fffff,0x0003ffff,0x84ffffc8, + 0x441ffffd,0x3f27ffff,0xe802ffff,0xf90fffff,0xd003ffff,0x801fffff, + 0x25fffffa,0x007fffff,0x33333333,0x39fffff3,0x13333333,0xfffff100, + 0x0dffffff,0x6ffffe40,0xffaffff9,0xfffd8fff,0x7ffc400f,0x2000ffff, + 0x98dffffe,0xfff55fff,0xfffc87ff,0xc80003ff,0xfd84ffff,0x7fc41fff, + 0x3fff27ff,0xffe802ff,0xfff90fff,0xffa805ff,0xf800ffff,0xf98fffff, + 0x0004ffff,0x0fffffe0,0x7fff4000,0xfffffeff,0xfff7004f,0x1ffff7df, + 0xfd5ffffb,0xffd00fff,0x8005ffff,0x3ea3fffa,0x3ffa26ff,0xfffffc86, + 0xffc80003,0xfffd84ff,0x7fffc41f,0x3fffff27,0xffffe802,0xfffff90f, + 0x7fffcc09,0xfc800fff,0xffcbffff,0x00001fff,0x00fffffe,0x3ffff200, + 0xffffd8ff,0xffa802ff,0x5fffdfff,0xffbffff5,0xffc80dff,0x0003ffff, + 0xfffa83db,0xfc81fc86,0x0003ffff,0x84ffffc8,0x441ffffd,0x3f27ffff, + 0xe802ffff,0xf70fffff,0x220dffff,0xffffffff,0xffff9800,0x6fffffef, + 0x7ffc0000,0x540003ff,0x13ffffff,0x1fffffff,0xfffff980,0xff13ffff, + 0xbfffffff,0x7ffffdc0,0x4020005f,0x0307fffb,0x0ffffff2,0x3fff2000, + 0xffffd84f,0x3ffffc41,0x05fffff9,0x1fffffd0,0x3fffffea,0x3fffee22, + 0x000fffff,0xfffffffd,0x00007fff,0x03fffff8,0x3fffe200,0x7ffd45ff, + 0x7c405fff,0xffffffff,0x3fffff60,0xff304fff,0x333fffff,0x33333333, + 0x3fff2001,0x3ff2000f,0x80003fff,0xd84ffffc,0x7c41ffff,0x3ff27fff, + 0xfe802fff,0xff10ffff,0xf9dfffff,0xffffffff,0x3ea001ff,0xffffffff, + 0x7c00000f,0x0003ffff,0x3ffffffa,0xfffffd80,0x7fffc03f,0x7d46ffff, + 0x3fffffff,0xfffffe88,0xffffffff,0x006fffff,0x003ffff9,0x1fffffe4, + 0x7ffe4000,0xffffd84f,0x3ffffc41,0x05fffff9,0x1fffffd0,0x7fffffe4, + 0xdfffffff,0x000fffff,0x3ffffffe,0x800004ff,0x003fffff,0xffffff90, + 0x3fffe205,0x3f601fff,0x43ffffff,0xfffffff8,0xffffa82f,0xffffffff, + 0x6fffffff,0x19999700,0x7fffe400,0xfc80003f,0xffd84fff,0x7ffc41ff, + 0x3ffff27f,0xfffe802f,0x3ffe20ff,0xffffffff,0xfffff8df,0x3fff2000, + 0x001fffff,0xfffff800,0xfffa8003,0x7d405fff,0x00efffff,0xfffffff9, + 0xfffffb01,0xfff503ff,0xffffffff,0xffffffff,0x2000000d,0x03fffffc, + 0xffffc800,0x1ffffd84,0x93ffffc4,0x005fffff,0x81fffffd,0xfffffffa, + 0xfff14fff,0x7cc001ff,0x06ffffff,0xffff0000,0xff88007f,0x800fffff, + 0x4ffffffd,0xffffff70,0x3fffea0d,0xfff507ff,0xffffffff,0xffffffff, + 0x2000000d,0x03fffffc,0xffffc800,0x1ffffd84,0x93ffffc4,0x005fffff, + 0x01fffffd,0xffffffd1,0x7fffc45d,0x7ff4000f,0x0003ffff,0x39999900, + 0xffffd800,0xff1002ff,0x505fffff,0x07ffffff,0x3fffffe2,0xfffff507, + 0xffffffff,0x0dffffff,0x3f200000,0x0003ffff,0x84ffffc8,0x441ffffd, + 0x3f27ffff,0xe802ffff,0x200fffff,0x001abb98,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x1ffffd00, + 0x66665c00,0xcccccccc,0xcccccccc,0x80000000,0x42aaaaa8,0x42aaaaa8, + 0xaaaaaaa8,0x6eeeec01,0xdddddddd,0xdddddddd,0x02dddddd,0x00000000, + 0x00000000,0x00000000,0x7dc00000,0x2005ffff,0xfffffffd,0xffffffff, + 0x501fffff,0x005bdfd9,0xfffff500,0xfffffa8d,0xfffffb86,0x3ffe02ff, + 0xffffffff,0xffffffff,0xffffffff,0x00000003,0x00000000,0x00000000, + 0x20000000,0xfffffff8,0xffffb002,0xffffffff,0xffffffff,0xfffffb03, + 0xa9801bff,0xfff50aaa,0xfffa8dff,0xffd306ff,0x3e05ffff,0xffffffff, + 0xffffffff,0xffffffff,0x000003ff,0x00000000,0x00000000,0x00000000, + 0x3fffff60,0xffb006ff,0xffffffff,0xffffffff,0x7ff443ff,0xffffffff, + 0x3ffff601,0xbfffff31,0x5fffff98,0x3ffff620,0xffff81ff,0xffffffff, + 0xffffffff,0x3fffffff,0x00000000,0x00000000,0x00000000,0xf3000000, + 0xffffdfff,0xffffb009,0xffffffff,0xffffffff,0x7ffffdc3,0x2fffffff, + 0x21ffffb0,0x45fffff9,0x05fffff9,0xffffffb8,0x7fffffc1,0xffffffff, + 0xffffffff,0x003fffff,0x00000000,0x00000000,0x00000000,0xfffd0000, + 0x03ffffad,0x33333310,0x33333333,0xe8333333,0xffffffff,0x442fffff, + 0x3e27ffff,0x7c44ffff,0x3004ffff,0x03fffffd,0x00000000,0x00000000, + 0x00000000,0x00000000,0x7fdc0000,0xffff51ff,0x0000000b,0x67ffffd4, + 0xffffffb9,0xfffe98cf,0x3fffe26f,0xfffff84f,0x3bb22004,0x00000dee, + 0x00000000,0x00000000,0x00000000,0x00000000,0x45ffff88,0x002ffffd, + 0xff700000,0xffe889ff,0xffffffff,0x7ffc3fff,0xffff83ff,0x0000003f, + 0x00000000,0x00000000,0x00000000,0x00000000,0x3fff2000,0x7fffcc1f, + 0x0000000f,0x81ffffc8,0xffffffe8,0x40ffffff,0xf82fffff,0x0003ffff, + 0x00000000,0x00000000,0x00000000,0x00000000,0xf3000000,0x3f209fff, + 0x00004fff,0xffffd800,0xffffb101,0x07ffffff,0xd05ffffd,0x0005ffff, + 0x00000000,0x00000000,0x00000000,0x00000000,0x3a000000,0xf100ffff, + 0xd903ffff,0xdddddddd,0xdddddddd,0x2aaa3ddd,0x7fe400aa,0x02ffffff, + 0xd03ffffd,0x0003ffff,0x00000000,0x00000000,0x00000000,0x00000000, + 0xf5000000,0xfb807fff,0xffd86fff,0xffffffff,0xffffffff,0x4c0001ff, + 0x01cefffd,0x207ffff6,0x001ffffd,0x00000000,0x00000000,0x00000000, + 0x00000000,0x44000000,0xd006ffff,0xfd87ffff,0xffffffff,0xffffffff, + 0x00001fff,0xccca8002,0xcccca80c,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x17fffe40,0xfffffa80,0x3fffff60,0xffffffff, + 0x1fffffff,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x7ffcc000,0x7ff4006f,0x3bbb24ff,0xeeeeeeee,0xeeeeeeee, + 0x0000001e,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x65400000,0x4c001ccc,0x000ccccc,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, +}; + +static signed short stb__consolas_bold_50_usascii_x[95]={ 0,9,5,1,2,0,0,10,6,5,3,1,5,6, +8,1,1,2,3,3,0,3,2,2,2,1,9,5,2,3,4,6,0,0,3,2,2,4,4,1,2,3,4,3, +4,1,2,0,3,0,3,2,1,2,0,0,0,0,2,7,2,6,2,0,0,2,3,3,1,2,0,1,3,3, +2,3,3,1,3,1,3,1,4,3,1,3,0,0,0,0,3,3,11,5,1, }; +static signed short stb__consolas_bold_50_usascii_y[95]={ 37,2,2,5,0,2,2,2,0,0,2,11,27,21, +27,2,4,4,4,4,5,5,5,5,4,4,11,11,9,16,9,2,1,5,5,4,5,5,5,4,5,5,5,5, +5,5,5,4,5,4,5,4,5,5,5,5,5,5,5,1,2,1,5,42,2,11,2,11,2,11,2,11,2,1, +1,2,2,11,11,11,11,11,11,11,4,12,12,12,12,12,12,1,-3,1,17, }; +static unsigned short stb__consolas_bold_50_usascii_w[95]={ 0,9,17,26,24,28,29,8,17,16,22,25,14,16, +11,24,26,23,22,22,27,22,24,23,23,24,10,14,21,22,21,18,28,28,23,23,25,20,20,25,24,21,19,24, +21,26,24,27,23,28,24,23,25,24,28,27,28,28,23,14,24,14,24,28,17,23,23,21,24,23,26,25,22,22, +21,24,22,26,22,25,23,24,22,21,23,22,28,28,27,28,21,20,6,19,26, }; +static unsigned short stb__consolas_bold_50_usascii_h[95]={ 0,36,13,32,44,36,36,13,48,48,22,25,19,6, +11,41,34,33,33,34,32,33,33,32,34,33,27,35,29,15,29,36,47,32,32,34,32,32,32,34,32,32,33,32, +32,32,32,34,32,43,32,34,32,33,32,32,32,32,32,46,41,46,16,6,11,27,36,27,36,27,35,37,35,36, +47,35,35,26,26,27,36,36,26,27,34,26,25,25,25,36,25,46,51,46,13, }; +static unsigned short stb__consolas_bold_50_usascii_s[95]={ 254,244,76,79,165,82,52,244,25,8,231, +126,237,237,244,219,1,220,172,28,47,99,122,23,51,147,241,124,97,26,75, +111,43,199,175,191,127,106,235,215,54,1,1,210,153,154,129,163,228,190,49, +75,103,195,181,21,74,1,30,135,1,150,1,112,94,213,208,145,1,167,49, +26,26,232,72,76,101,24,51,119,184,159,1,191,139,74,97,180,152,130,209, +94,1,115,49, }; +static unsigned short stb__consolas_bold_50_usascii_t[95]={ 1,1,294,201,1,53,53,132,1,1,267, +267,234,254,146,1,132,132,132,132,234,132,132,234,132,132,91,91,234,294,234, +53,1,201,201,91,201,201,167,91,201,234,167,167,201,167,167,91,201,1,167, +132,167,132,167,167,167,201,201,1,53,1,294,294,294,234,53,234,95,234,91, +53,91,53,1,91,91,267,267,234,53,53,267,234,91,267,267,267,267,53,267, +1,1,1,294, }; +static unsigned short stb__consolas_bold_50_usascii_a[95]={ 440,440,440,440,440,440,440,440, +440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, +440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, +440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, +440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, +440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440, +440,440,440,440,440,440,440, }; + +// Call this function with +// font: NULL or array length +// data: NULL or specified size +// height: STB_FONT_consolas_bold_50_usascii_BITMAP_HEIGHT or STB_FONT_consolas_bold_50_usascii_BITMAP_HEIGHT_POW2 +// return value: spacing between lines +static void stb_font_consolas_bold_50_usascii(stb_fontchar font[STB_FONT_consolas_bold_50_usascii_NUM_CHARS], + unsigned char data[STB_FONT_consolas_bold_50_usascii_BITMAP_HEIGHT][STB_FONT_consolas_bold_50_usascii_BITMAP_WIDTH], + int height) +{ + int i,j; + if (data != 0) { + unsigned int *bits = stb__consolas_bold_50_usascii_pixels; + unsigned int bitpack = *bits++, numbits = 32; + for (i=0; i < STB_FONT_consolas_bold_50_usascii_BITMAP_WIDTH*height; ++i) + data[0][i] = 0; // zero entire bitmap + for (j=1; j < STB_FONT_consolas_bold_50_usascii_BITMAP_HEIGHT-1; ++j) { + for (i=1; i < STB_FONT_consolas_bold_50_usascii_BITMAP_WIDTH-1; ++i) { + unsigned int value; + if (numbits==0) bitpack = *bits++, numbits=32; + value = bitpack & 1; + bitpack >>= 1, --numbits; + if (value) { + if (numbits < 3) bitpack = *bits++, numbits = 32; + data[j][i] = (bitpack & 7) * 0x20 + 0x1f; + bitpack >>= 3, numbits -= 3; + } else { + data[j][i] = 0; + } + } + } + } + + // build font description + if (font != 0) { + float recip_width = 1.0f / STB_FONT_consolas_bold_50_usascii_BITMAP_WIDTH; + float recip_height = 1.0f / height; + for (i=0; i < STB_FONT_consolas_bold_50_usascii_NUM_CHARS; ++i) { + // pad characters so they bilerp from empty space around each character + font[i].s0 = (stb__consolas_bold_50_usascii_s[i]) * recip_width; + font[i].t0 = (stb__consolas_bold_50_usascii_t[i]) * recip_height; + font[i].s1 = (stb__consolas_bold_50_usascii_s[i] + stb__consolas_bold_50_usascii_w[i]) * recip_width; + font[i].t1 = (stb__consolas_bold_50_usascii_t[i] + stb__consolas_bold_50_usascii_h[i]) * recip_height; + font[i].x0 = stb__consolas_bold_50_usascii_x[i]; + font[i].y0 = stb__consolas_bold_50_usascii_y[i]; + font[i].x1 = stb__consolas_bold_50_usascii_x[i] + stb__consolas_bold_50_usascii_w[i]; + font[i].y1 = stb__consolas_bold_50_usascii_y[i] + stb__consolas_bold_50_usascii_h[i]; + font[i].advance_int = (stb__consolas_bold_50_usascii_a[i]+8)>>4; + font[i].s0f = (stb__consolas_bold_50_usascii_s[i] - 0.5f) * recip_width; + font[i].t0f = (stb__consolas_bold_50_usascii_t[i] - 0.5f) * recip_height; + font[i].s1f = (stb__consolas_bold_50_usascii_s[i] + stb__consolas_bold_50_usascii_w[i] + 0.5f) * recip_width; + font[i].t1f = (stb__consolas_bold_50_usascii_t[i] + stb__consolas_bold_50_usascii_h[i] + 0.5f) * recip_height; + font[i].x0f = stb__consolas_bold_50_usascii_x[i] - 0.5f; + font[i].y0f = stb__consolas_bold_50_usascii_y[i] - 0.5f; + font[i].x1f = stb__consolas_bold_50_usascii_x[i] + stb__consolas_bold_50_usascii_w[i] + 0.5f; + font[i].y1f = stb__consolas_bold_50_usascii_y[i] + stb__consolas_bold_50_usascii_h[i] + 0.5f; + font[i].advance = stb__consolas_bold_50_usascii_a[i]/16.0f; + } + } +} + +#ifndef STB_SOMEFONT_CREATE +#define STB_SOMEFONT_CREATE stb_font_consolas_bold_50_usascii +#define STB_SOMEFONT_BITMAP_WIDTH STB_FONT_consolas_bold_50_usascii_BITMAP_WIDTH +#define STB_SOMEFONT_BITMAP_HEIGHT STB_FONT_consolas_bold_50_usascii_BITMAP_HEIGHT +#define STB_SOMEFONT_BITMAP_HEIGHT_POW2 STB_FONT_consolas_bold_50_usascii_BITMAP_HEIGHT_POW2 +#define STB_SOMEFONT_FIRST_CHAR STB_FONT_consolas_bold_50_usascii_FIRST_CHAR +#define STB_SOMEFONT_NUM_CHARS STB_FONT_consolas_bold_50_usascii_NUM_CHARS +#define STB_SOMEFONT_LINE_SPACING STB_FONT_consolas_bold_50_usascii_LINE_SPACING +#endif + diff --git a/Projects/Asteroids/src/subset_d3d12.h b/Projects/Asteroids/src/subset_d3d12.h new file mode 100644 index 0000000..8fe2a1b --- /dev/null +++ b/Projects/Asteroids/src/subset_d3d12.h @@ -0,0 +1,50 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include "util.h" +#include "descriptor.h" + +#include <d3d12.h> + +__declspec(align(64)) // Avoid false sharing +class SubsetD3D12 +{ +public: + SubsetD3D12(ID3D12Device* mDevice, UINT srvCount, ID3D12PipelineState* pso) + { + ThrowIfFailed(mDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCmdAlloc))); + ThrowIfFailed(mDevice->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, mCmdAlloc, pso, IID_PPV_ARGS(&mCmdLst))); + ThrowIfFailed(mCmdLst->Close()); + } + + ~SubsetD3D12() + { + SafeRelease(&mCmdLst); + SafeRelease(&mCmdAlloc); + } + + ID3D12GraphicsCommandList* Begin(ID3D12PipelineState* pso) + { + ThrowIfFailed(mCmdAlloc->Reset()); + ThrowIfFailed(mCmdLst->Reset(mCmdAlloc, pso)); + return mCmdLst; + } + + ID3D12GraphicsCommandList* End() + { + ThrowIfFailed(mCmdLst->Close()); + return mCmdLst; + } + + ID3D12GraphicsCommandList* mCmdLst = nullptr; + ID3D12CommandAllocator* mCmdAlloc = nullptr; +}; diff --git a/Projects/Asteroids/src/texture.cpp b/Projects/Asteroids/src/texture.cpp new file mode 100644 index 0000000..d62b913 --- /dev/null +++ b/Projects/Asteroids/src/texture.cpp @@ -0,0 +1,285 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#include "texture.h" +#include "util.h" +#include "noise.h" +#include "DDSTextureLoader.h" + +#include <stdint.h> +#include <sstream> + + +static void WaitForAll(ID3D12Device* device, ID3D12CommandQueue* queue) +{ + // Kind of ugly, but yeah... + ID3D12Fence* fence = nullptr; + ThrowIfFailed(device->CreateFence( 0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence))); + auto eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); + + queue->Signal(fence, 1); + fence->SetEventOnCompletion(1, eventHandle); + WaitForSingleObject(eventHandle, INFINITE); + + CloseHandle(eventHandle); + fence->Release(); +} + + +void GenerateMips2D_XXXX8(D3D11_SUBRESOURCE_DATA* subresources, size_t widthLevel0, size_t heightLevel0, size_t mipLevels) +{ + for (size_t m = 1; m < mipLevels; ++m) { + auto rowPitchSrc = subresources[m - 1].SysMemPitch; + const BYTE* dataSrc = (BYTE*)subresources[m - 1].pSysMem; + + auto rowPitchDst = subresources[m].SysMemPitch; + BYTE* dataDst = (BYTE*)subresources[m].pSysMem; + + auto width = widthLevel0 >> m; + auto height = heightLevel0 >> m; + + // Iterating byte-wise is simpler in this case (pulls apart color nicely) + // Not optimized at all, obviously... + for (size_t y = 0; y < height; ++y) { + auto rowSrc0 = (dataSrc + (y*2+0)*rowPitchSrc); + auto rowSrc1 = (dataSrc + (y*2+1)*rowPitchSrc); + auto rowDst = (dataDst + (y )*rowPitchDst); + for (size_t x = 0; x < width; ++x) { + for (size_t comp = 0; comp < 4; ++comp) { + uint32_t c = rowSrc0[x*8+comp+0]; + c += rowSrc0[x*8+comp+4]; + c += rowSrc1[x*8+comp+0]; + c += rowSrc1[x*8+comp+4]; + c = c / 4; + assert(c < 256); + rowDst[4*x+comp] = (byte)c; + } + } + } + } +} + + +void FillNoise2D_RGBA8(D3D11_SUBRESOURCE_DATA* subresources, size_t width, size_t height, size_t mipLevels, + float seed, float persistence, float noiseScale, float noiseStrength, + float redScale, float greenScale, float blueScale) +{ + NoiseOctaves<4> textureNoise(persistence); + + // Level 0 + for (size_t y = 0; y < height; ++y) { + uint32_t* row = (uint32_t*)((BYTE*)subresources[0].pSysMem + y*subresources[0].SysMemPitch); + for (size_t x = 0; x < width; ++x) { + auto c = textureNoise((float)x*noiseScale, (float)y*noiseScale, seed); + c = std::max(0.0f, std::min(1.0f, (c - 0.5f) * noiseStrength + 0.5f)); + + int32_t cr = (int32_t)(c * redScale); + int32_t cg = (int32_t)(c * greenScale); + int32_t cb = (int32_t)(c * blueScale); + assert(cr >= 0 && cr < 256); + assert(cg >= 0 && cg < 256); + assert(cb >= 0 && cb < 256); + + row[x] = (cr) << 16 | (cg) << 8 | (cb) << 0; + } + } + + if (mipLevels > 1) + GenerateMips2D_XXXX8(subresources, width, height, mipLevels); +} + + +void InitializeTexture2D( + ID3D12Device* device, ID3D12CommandQueue* cmdQueue, + ID3D12Resource* texture, const D3D12_RESOURCE_DESC* desc, UINT bytesPerPixel, + const D3D11_SUBRESOURCE_DATA* initialData, + D3D12_RESOURCE_STATES stateAfter) +{ + // Pull some data + auto format = desc->Format; + UINT width = (UINT)desc->Width; + UINT height = desc->Height; + UINT arraySize = desc->DepthOrArraySize; + UINT mipLevels = desc->MipLevels; + + // Pow2 mip chain! + assert(mipLevels == 1 || ((width & (width-1)) == 0 && (height & (height-1)) == 0)); + + std::vector<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedUpload; + UINT64 totalSize = 0; + for (UINT a = 0; a < arraySize; ++a) { + for (UINT m = 0; m < mipLevels; ++m) { + D3D12_PLACED_SUBRESOURCE_FOOTPRINT placed = {}; + placed.Footprint.Format = format; + placed.Footprint.Width = width >> m; // TODO: Handle mip sizes properly! + placed.Footprint.Height = height >> m; // TODO: Handle mip sizes properly! + placed.Footprint.Depth = 1; + placed.Footprint.RowPitch = Align<UINT>(placed.Footprint.Width * bytesPerPixel, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); + placed.Offset = totalSize; + + totalSize = Align<UINT64>(placed.Offset + (placed.Footprint.RowPitch * placed.Footprint.Height), + D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); + placedUpload.push_back(placed); + } + } + + ID3D12Resource* uploadBuffer = nullptr; + ThrowIfFailed(device->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(totalSize), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&uploadBuffer) + )); + + BYTE *baseData = nullptr; + ThrowIfFailed(uploadBuffer->Map(0, nullptr, reinterpret_cast<void**>(&baseData))); + + // Fill in data (RGBA8) + for (UINT a = 0; a < arraySize; ++a) { + for (UINT m = 0; m < mipLevels; ++m) { + auto subresource = a * mipLevels + m; + + BYTE* dataSrc = (BYTE*)initialData[subresource].pSysMem; + auto rowPitchSrc = initialData[subresource].SysMemPitch; + + auto placed = &placedUpload[subresource]; + BYTE* dataDst = baseData + placed->Offset; + auto rowPitchDst = placed->Footprint.RowPitch; + UINT width_mip = placed->Footprint.Width; + UINT height_mip = placed->Footprint.Height; + + for (UINT y = 0; y < height_mip; ++y) { + memcpy(dataDst + y*rowPitchDst, dataSrc + y*rowPitchSrc, bytesPerPixel * width_mip); + } + } + } + + // Create some new resources for initialization + ID3D12GraphicsCommandList* cmdLst = nullptr; + ID3D12CommandAllocator* cmdAlloc = nullptr; + ThrowIfFailed(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc))); + ThrowIfFailed(device->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, nullptr, IID_PPV_ARGS(&cmdLst))); + + { + ResourceBarrier rb; + rb.AddTransition(texture, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST); + rb.Submit(cmdLst); + } + + // Copy data from each subresource into texture + for (size_t s = 0; s < placedUpload.size(); ++s) { + CD3DX12_TEXTURE_COPY_LOCATION dest(texture, static_cast<UINT>(s)); + CD3DX12_TEXTURE_COPY_LOCATION src(uploadBuffer, placedUpload[s]); + + cmdLst->CopyTextureRegion( + &dest, 0, 0, 0, + &src, nullptr); + } + + { + ResourceBarrier rb; + rb.AddTransition(texture, D3D12_RESOURCE_STATE_COPY_DEST, stateAfter); + rb.Submit(cmdLst); + } + + ThrowIfFailed(cmdLst->Close()); + cmdQueue->ExecuteCommandLists(1, reinterpret_cast<ID3D12CommandList*const*>(&cmdLst)); + + // Kind of ugly... but yeah + WaitForAll(device, cmdQueue); + + SafeRelease(&uploadBuffer); + SafeRelease(&cmdLst); + SafeRelease(&cmdAlloc); +} + + +HRESULT CreateTexture2DFromDDS_XXXX8( + ID3D12Device* device, ID3D12CommandQueue* cmdQueue, + ID3D12Resource** texture, + const char* fileName, + DXGI_FORMAT format, + D3D12_RESOURCE_STATES stateAfter ) +{ + BYTE* heapData = nullptr; + DDS_HEADER* header = nullptr; + BYTE* bitData = nullptr; + UINT bitSize = 0; + + std::wostringstream wfileName; + wfileName << fileName; + + HRESULT hr = LoadTextureDataFromFile(wfileName.str().c_str(), &heapData, &header, &bitData, &bitSize); + if (FAILED(hr)) { + delete[] heapData; + return hr; + } + + unsigned int arraySize = 1; + + if (header->dwCaps2 & DDS_CUBEMAP) { + assert((header->dwCaps2 & DDS_CUBEMAP_ALLFACES ) == DDS_CUBEMAP_ALLFACES); + arraySize = 6; + } + + // We only support XXXX8_UNORM[_SRGB] atm... + if (format != DXGI_FORMAT_B8G8R8A8_UNORM && format != DXGI_FORMAT_R8G8B8A8_UNORM && + format != DXGI_FORMAT_B8G8R8A8_UNORM_SRGB && format != DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) { + return E_NOTIMPL; + } + + unsigned int mipLevels = header->dwMipMapCount; + if (mipLevels == 0) mipLevels = 1; // Hacky... but good enough for now + + // TODO: lots of stuff is not checked... just don't be stupid, this is hacky sample code after all :) + + auto desc = CD3DX12_RESOURCE_DESC::Tex2D( + format, header->dwWidth, header->dwHeight, + (UINT16)arraySize, (UINT16)mipLevels ); + + ThrowIfFailed(device->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &desc, + D3D12_RESOURCE_STATE_COMMON, + nullptr, + IID_PPV_ARGS(texture) + )); + + std::vector<D3D11_SUBRESOURCE_DATA> initialData(desc.MipLevels * arraySize); + + BYTE* srcBits = bitData; + const BYTE *endBits = bitData + bitSize; + + for (UINT a = 0; a < arraySize; ++a) { + for (UINT m = 0; m < desc.MipLevels; ++m) { + auto width = (UINT)desc.Width >> m; + auto height = desc.Height >> m; + auto subresource = a * desc.MipLevels + m; + auto rowPitch = 4 * width; + auto bytes = rowPitch * height; + + assert(srcBits + bytes <= endBits); + + initialData[subresource].pSysMem = (void*)srcBits; + initialData[subresource].SysMemPitch = rowPitch; + initialData[subresource].SysMemSlicePitch = bytes; + + srcBits += bytes; + } + } + + InitializeTexture2D(device, cmdQueue, *texture, &desc, 4, initialData.data(), stateAfter); + + delete[] heapData; + return S_OK; +} diff --git a/Projects/Asteroids/src/texture.h b/Projects/Asteroids/src/texture.h new file mode 100644 index 0000000..d3ed698 --- /dev/null +++ b/Projects/Asteroids/src/texture.h @@ -0,0 +1,46 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include <d3d12.h> +#include <d3dx12.h> +#include <d3d11.h> + +void GenerateMips2D_XXXX8(D3D11_SUBRESOURCE_DATA* subresources, size_t widthLevel0, size_t heightLevel0, size_t mipLevels); + +// Will generate mips (into subresources array) is mipLevels > 0 +void FillNoise2D_RGBA8(D3D11_SUBRESOURCE_DATA* subresources, size_t width, size_t height, size_t mipLevels, + float seed, float persistence, float noiseScale, float noiseStrength, + float redScale = 255.0f, float greenScale = 255.0f, float blueScale = 255.0f); + + +// Helper for uploading initial texture data in D3D12; as with D3D11, one initialData structure per subresource +// Creates temporary resources internally and syncs with GPU... this is a convenience function for init time! +// NOTE: Currently textures with mip chain must be pow2! +// Transitions resource from D3D12_RESOURCE_USAGE_INITIAL to "stateAfter" +void InitializeTexture2D( + ID3D12Device* device, + ID3D12CommandQueue* cmdQueue, + ID3D12Resource* texture, + const D3D12_RESOURCE_DESC* desc, + UINT bytesPerPixel, + const D3D11_SUBRESOURCE_DATA* initialData, + D3D12_RESOURCE_STATES stateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + +// NOTE: This function very much only works for the specific path(s) that we use it for! +// Not very general-purpose yet. +HRESULT CreateTexture2DFromDDS_XXXX8( + ID3D12Device* device, + ID3D12CommandQueue* cmdQueue, + ID3D12Resource** texture, + const char* fileName, + DXGI_FORMAT format, // Should match file otherwise expect explosion/wackiness... + D3D12_RESOURCE_STATES stateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); diff --git a/Projects/Asteroids/src/upload_heap.h b/Projects/Asteroids/src/upload_heap.h new file mode 100644 index 0000000..582925e --- /dev/null +++ b/Projects/Asteroids/src/upload_heap.h @@ -0,0 +1,60 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include "util.h" +#include <d3d12.h> + +// Untyped version +class UploadHeap +{ +public: + UploadHeap(ID3D12Device* device, UINT64 size) + { + ThrowIfFailed(device->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES( D3D12_HEAP_TYPE_UPLOAD ), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer( size ), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&mHeap) + )); + + ThrowIfFailed(mHeap->Map(0, nullptr, reinterpret_cast<void**>(&mHeapWO))); + } + + ~UploadHeap() + { + SafeRelease(&mHeap); + } + + ID3D12Resource* Heap() { return mHeap; } + + // Write-only! + void* DataWO() { return mHeapWO; } + +private: + ID3D12Resource* mHeap = nullptr; + void* mHeapWO = nullptr; +}; + + +// Structure/typed version +template <typename T> +class UploadHeapT : public UploadHeap +{ +public: + UploadHeapT(ID3D12Device* device) + : UploadHeap(device, sizeof(T)) + {} + + T* DataWO() { return (T*)UploadHeap::DataWO(); } +}; diff --git a/Projects/Asteroids/src/util.h b/Projects/Asteroids/src/util.h new file mode 100644 index 0000000..7779954 --- /dev/null +++ b/Projects/Asteroids/src/util.h @@ -0,0 +1,79 @@ +// Copyright 2014 Intel Corporation All Rights Reserved +// +// Intel makes no representations about the suitability of this software for any purpose. +// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, +// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, +// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY +// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// Intel does not assume any responsibility for any errors which may appear in this software +// nor any responsibility to update it. + +#pragma once + +#include <assert.h> +#include <d3d12.h> + +#include <algorithm> +#include <vector> + +#define CBUFFER_ALIGN __declspec(align(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT)) + +#define WIDE_HELPER_2(x) L##x +#define WIDE_HELPER_1(x) WIDE_HELPER_2(x) +#define W__FILE__ WIDE_HELPER_1(__FILE__) + +template<typename T> +inline void SafeRelease(T** p) +{ + auto q = *p; + if (q != nullptr) { + q->Release(); + *p = nullptr; + } +} + +inline HRESULT ThrowIfFailed(HRESULT hr) +{ + if (FAILED(hr)) throw; + return hr; +} + +template <typename T> +inline T Align(T v, T align) +{ + return (v + (align-1)) & ~(align-1); +} + +struct ResourceBarrier { + std::vector<D3D12_RESOURCE_BARRIER> mDescs; + + void AddTransition( + ID3D12Resource* resource, + D3D12_RESOURCE_STATES stateBefore, + D3D12_RESOURCE_STATES stateAfter, + UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES) + { + D3D12_RESOURCE_BARRIER desc = {}; + desc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + desc.Transition.pResource = resource; + desc.Transition.StateBefore = stateBefore; + desc.Transition.StateAfter = stateAfter; + desc.Transition.Subresource = subresource; + mDescs.push_back(desc); + } + + void ReverseTransitions() + { + for (auto ii = mDescs.begin(), ie = mDescs.end(); ii != ie; ++ii) { + if (ii->Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION) { + std::swap(ii->Transition.StateBefore, ii->Transition.StateAfter); + } + } + } + + void Submit(ID3D12GraphicsCommandList* commandList) const + { + assert(mDescs.size() <= UINT_MAX); + commandList->ResourceBarrier((UINT)mDescs.size(), mDescs.data()); + } +}; |
